From 8fbc70988d592fb9ae64e4ccf73d4ab0fe4ac861 Mon Sep 17 00:00:00 2001 From: harshbaz <106158714+harshbaz@users.noreply.github.com> Date: Fri, 19 May 2023 17:39:44 +0530 Subject: [PATCH] Add airdrop form and waitlist (#1889) * Create component * Move page to airdrop * Add info icon * Create waitlist component * Add confetti package * Add confetti effect * Bind prop * Cleanup * Add coin icon * Update form * Add airdrop graphics * Creare airdrop popup * Fix lockfile * Add checkbox sample field * Add wallet balance fetching logic * Add dot separator * Add airdrop guide page * Update title * Add airdrop completed graphics * Add completed and loading states to the popup * Update popup * Add countdown component * Update popup * Add countdown util * Fix link * Update guide * Add socials link to airdrop * Add question icon * Add airdrop guide link in menu * Cleanup * Add airdrop icon * Add airdrop button * Show airdrop button on hot or not feed * Cleanup * Update position * Add animation to airdrop button * Rename form component * Update reference * Update guide * Do not show countdown when it's over * Update popup for smaller screens * Fix timer not working * Rename splash screen store * Update references * Add type * Move hot or not onboarding popup store to popups * Update refernces * Update popup store name * Update reference * Add airdrop popup store * Use airdrop store to show popup * Show airdrop popup only on feed layout * Remove airdrop popup from player layout * Add optional input component * Add optional inputs to the form * Fix header style * Fix spacing * Update text * Fix grammer * Update labels * Update page title * Export type * Fix language * Create separate component for completion * Use completed screen * Update popup * Disable hot or not onboarding * Cleanup * Install firebase * Fix completed popup for small screens * Add logic to check participation * Add firestore helper * Cleanup * Set intial value to false * Check login and participation status * Fix searching * Add validation * Fix graphics margin * Update usage * Cleanup * Add style to hyperlinks * Update form * Cleanup * Use prod env * Send user canister id as well * Move text * Update guide * Update url regex * Cleanup * Fix guide * Update date * Fix guide * Fix collection name * Cleanup * Add airdrop helper * Use updated airdrop helper * Update worker package name * Cleanup * Remove firebase package * Update lockfile * Update amount * Update usage * Update text and add a register now button * Use new countdown component * Add method for checking in waitlist * Do not check splash screen * Add popup * Update time * Use form element * Add registermethod * Handle waitlist response * Update url * Use method * Update countdown style * Update airdrop page * Update message --- .gitignore | 3 +- package-lock.json | 27 +- package.json | 7 +- packages/functions/README.md | 1 - packages/web-client/package.json | 1 + .../airdrop-form/AirdropCompleted.svelte | 55 + .../airdrop-form/AirdropForm.svelte | 355 +++++ .../airdrop-form/OptionalInput.svelte | 31 + .../icons/AirdropCompleteGraphics.svelte | 265 ++++ .../components/icons/AirdropGraphic.svelte | 1164 +++++++++++++++++ .../src/components/icons/AirdropIcon.svelte | 188 +++ .../src/components/icons/Coin3dIcon.svelte | 167 +++ .../src/components/icons/InfoIcon.svelte | 19 + .../src/components/icons/QuestionIcon.svelte | 17 + .../src/components/layout/DotSeparator.svelte | 5 + .../src/components/layout/PlayerLayout.svelte | 40 +- .../src/components/layout/SplashScreen.svelte | 4 +- .../notification/NotificationItem.svelte | 6 +- .../components/popup/AirdropCountdown.svelte | 45 + .../src/components/popup/AirdropPopup.svelte | 82 ++ .../popup/AirdropPopupOnlyCountdown.svelte | 113 ++ .../popup/HotorNotOnboarding.svelte | 16 +- .../components/profile/SpeculationPost.svelte | 2 +- .../profile/SpeculationPosts.svelte | 4 +- .../web-client/src/components/seo/GA.svelte | 4 +- .../components/wallet/TransactionItem.svelte | 15 +- .../web-client/src/lib/helpers/airdrop.ts | 123 ++ .../web-client/src/lib/helpers/profile.ts | 2 +- packages/web-client/src/lib/utils/timeLeft.ts | 60 +- .../src/routes/(feed)/(splash)/+layout.svelte | 5 + .../(splash)/feed/[id=videoId]/+page.svelte | 4 +- .../(splash)/feed/no-videos/+page.svelte | 2 +- .../(feed)/(splash)/hotornot/+layout.svelte | 2 +- .../hotornot/[id=videoId]/+page.svelte | 3 +- .../(splash)/hotornot/no-videos/+page.svelte | 2 +- .../src/routes/(feed)/menu/+page.svelte | 9 +- .../src/routes/airdrop-guide/+page.svelte | 257 ++++ .../src/routes/airdrop/+page.svelte | 35 + .../[postId=videoId]/+page.svelte | 4 +- .../src/stores/hotOrNotOnboarding.ts | 3 - packages/web-client/src/stores/popups.ts | 24 + .../web-client/src/stores/splashScreen.ts | 19 - packages/workers/package.json | 2 +- 43 files changed, 3124 insertions(+), 68 deletions(-) delete mode 100644 packages/functions/README.md create mode 100644 packages/web-client/src/components/airdrop-form/AirdropCompleted.svelte create mode 100644 packages/web-client/src/components/airdrop-form/AirdropForm.svelte create mode 100644 packages/web-client/src/components/airdrop-form/OptionalInput.svelte create mode 100644 packages/web-client/src/components/icons/AirdropCompleteGraphics.svelte create mode 100644 packages/web-client/src/components/icons/AirdropGraphic.svelte create mode 100644 packages/web-client/src/components/icons/AirdropIcon.svelte create mode 100644 packages/web-client/src/components/icons/Coin3dIcon.svelte create mode 100644 packages/web-client/src/components/icons/InfoIcon.svelte create mode 100644 packages/web-client/src/components/icons/QuestionIcon.svelte create mode 100644 packages/web-client/src/components/layout/DotSeparator.svelte create mode 100644 packages/web-client/src/components/popup/AirdropCountdown.svelte create mode 100644 packages/web-client/src/components/popup/AirdropPopup.svelte create mode 100644 packages/web-client/src/components/popup/AirdropPopupOnlyCountdown.svelte create mode 100644 packages/web-client/src/lib/helpers/airdrop.ts create mode 100644 packages/web-client/src/routes/airdrop-guide/+page.svelte create mode 100644 packages/web-client/src/routes/airdrop/+page.svelte delete mode 100644 packages/web-client/src/stores/hotOrNotOnboarding.ts create mode 100644 packages/web-client/src/stores/popups.ts delete mode 100644 packages/web-client/src/stores/splashScreen.ts diff --git a/.gitignore b/.gitignore index 7d33d643c..d755701a0 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,5 @@ tsconfig.tsbuildinfo todo.md packages/web-client/static/~partytown packages/web-client/coverage/** -packages/web-client/cypress/reports \ No newline at end of file +packages/web-client/cypress/reports +packages/functions \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index abaa8e545..a9e7e2b19 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1146,7 +1146,7 @@ "resolved": "packages/web-client", "link": true }, - "node_modules/@hnn/workers-api": { + "node_modules/@hnn/workers": { "resolved": "packages/workers", "link": true }, @@ -1489,6 +1489,11 @@ "node": ">=16.13" } }, + "node_modules/@neoconfetti/svelte": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@neoconfetti/svelte/-/svelte-1.0.0.tgz", + "integrity": "sha512-SmksyaJAdSlMa9cTidVSIqYo1qti+WTsviNDwgjNVm+KQ3DRP2Df9umDIzC4vCcpEYY+chQe0i2IKnLw03AT8Q==" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "dev": true, @@ -11068,9 +11073,10 @@ } }, "node_modules/yargs": { - "version": "17.6.2", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, - "license": "MIT", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -11180,6 +11186,7 @@ "@dfinity/identity": "0.15.6", "@dfinity/identity-secp256k1": "0.15.6", "@dfinity/principal": "0.15.6", + "@neoconfetti/svelte": "^1.0.0", "@sentry/svelte": "7.51.0", "@sentry/tracing": "7.51.0", "buffer": "6.0.3", @@ -11232,7 +11239,7 @@ } }, "packages/workers": { - "name": "@hnn/workers-api", + "name": "@hnn/workers", "version": "1.0.0", "license": "ISC", "dependencies": { @@ -11972,6 +11979,7 @@ "@dfinity/identity": "0.15.6", "@dfinity/identity-secp256k1": "0.15.6", "@dfinity/principal": "0.15.6", + "@neoconfetti/svelte": "^1.0.0", "@sentry/svelte": "7.51.0", "@sentry/tracing": "7.51.0", "@sveltejs/adapter-cloudflare": "2.2.2", @@ -12020,7 +12028,7 @@ } } }, - "@hnn/workers-api": { + "@hnn/workers": { "version": "file:packages/workers", "requires": { "itty-router": "3.0.12", @@ -12281,6 +12289,11 @@ "ws": "^8.2.2" } }, + "@neoconfetti/svelte": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@neoconfetti/svelte/-/svelte-1.0.0.tgz", + "integrity": "sha512-SmksyaJAdSlMa9cTidVSIqYo1qti+WTsviNDwgjNVm+KQ3DRP2Df9umDIzC4vCcpEYY+chQe0i2IKnLw03AT8Q==" + }, "@nodelib/fs.scandir": { "version": "2.1.5", "dev": true, @@ -18669,7 +18682,9 @@ "dev": true }, "yargs": { - "version": "17.6.2", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "requires": { "cliui": "^8.0.1", diff --git a/package.json b/package.json index 717d7c610..a9a498f3a 100644 --- a/package.json +++ b/package.json @@ -24,8 +24,8 @@ "wc:test:record": "npm run test:record --w @hnn/web-client", "wc:test:vi": "npm run test:vi --w @hnn/web-client", "wc:sync": "npm run sync --w @hnn/web-client", - "workers:dev": "npm run dev --w @hnn/workers-api", - "workers:publish": "npm run publish --w @hnn/workers-api" + "workers:dev": "npm run dev --w @hnn/workers", + "workers:publish": "npm run publish --w @hnn/workers" }, "devDependencies": { "@sveltejs/eslint-config": "github:sveltejs/eslint-config#v5.8.0", @@ -40,5 +40,6 @@ }, "dependencies": { "date-fns": "^2.29.3" - } + }, + "private": true } diff --git a/packages/functions/README.md b/packages/functions/README.md deleted file mode 100644 index e8f031be4..000000000 --- a/packages/functions/README.md +++ /dev/null @@ -1 +0,0 @@ -# Google cloud functions diff --git a/packages/web-client/package.json b/packages/web-client/package.json index 379906eee..7c03fa7af 100644 --- a/packages/web-client/package.json +++ b/packages/web-client/package.json @@ -28,6 +28,7 @@ "@dfinity/identity": "0.15.6", "@dfinity/identity-secp256k1": "0.15.6", "@dfinity/principal": "0.15.6", + "@neoconfetti/svelte": "^1.0.0", "@sentry/svelte": "7.51.0", "@sentry/tracing": "7.51.0", "buffer": "6.0.3", diff --git a/packages/web-client/src/components/airdrop-form/AirdropCompleted.svelte b/packages/web-client/src/components/airdrop-form/AirdropCompleted.svelte new file mode 100644 index 000000000..62a409ab3 --- /dev/null +++ b/packages/web-client/src/components/airdrop-form/AirdropCompleted.svelte @@ -0,0 +1,55 @@ + + +
+ +
+
+
+ Congratulations +
+
+ We have registered your interest. Airdrop will be live on 23 May +
+ + Learn more about the rewards here + +
+ +
+ For more queries, you can get in touch with us on our socials +
+
+
diff --git a/packages/web-client/src/components/airdrop-form/AirdropForm.svelte b/packages/web-client/src/components/airdrop-form/AirdropForm.svelte new file mode 100644 index 000000000..eabc6b5d5 --- /dev/null +++ b/packages/web-client/src/components/airdrop-form/AirdropForm.svelte @@ -0,0 +1,355 @@ + + + +
+ {#if !participated} +
+ + + + + Hot or Not's + + $ 300,000 * + + Airdrop is here +
+
+ + Join us at Hot or Not as we take over TikTok! Register for the + whitelist to receive "HOT" governance tokens in our decentralization + sale. + +
+
+ + Learn more about the airdrop here + +
+ + {/if} + + {#if !authorized} +
+ +
+ {:else if loading} +
+ +
+ {:else if !participated} +
+ Your Hot or Not Principal ID + {$authState.idString} +
+
+ Your Current Wallet Balance + {#if wallet.error} +
+ + Error fetching balance. +
+ {:else if wallet.loading} +
Loading ...
+ {:else} + {wallet.balance} Coyns + + Note: final balance at the end of 30 days will be considered for + airdrop allotment + + {/if} +
+
+ + Email + * + + +
+
+ + Tweet Link + * + +
+ + + + + You need to tweet with the hashtag #hotornot and paste your tweet's + link + +
+ +
+
+ + Do you own any of the following assets? Please select all that apply + for additional rewards: + + + + + +
+
+ Note: Every email ID can only be associated with one login account. If + the same mail is used with multiple airdrop entries, the previous + entries will be overwritten +
+
+ * + Subject to full SNS subscription & ICP price +
+ {#if formErrors.length} +
+ Error(s): + {#each formErrors as err, i (i)} +
  • {err}
  • + {/each} +
    + {/if} +
    + +
    +
    + By joining, you agree to + + terms of service + + & + + privacy policy + +
    + {:else} +
    + +
    + {/if} +
    +
    diff --git a/packages/web-client/src/components/airdrop-form/OptionalInput.svelte b/packages/web-client/src/components/airdrop-form/OptionalInput.svelte new file mode 100644 index 000000000..7e46cdb5f --- /dev/null +++ b/packages/web-client/src/components/airdrop-form/OptionalInput.svelte @@ -0,0 +1,31 @@ + + +
    + + {#if checked} +
    + + {inputLabel} + * + + +
    + {/if} +
    diff --git a/packages/web-client/src/components/icons/AirdropCompleteGraphics.svelte b/packages/web-client/src/components/icons/AirdropCompleteGraphics.svelte new file mode 100644 index 000000000..004b164fd --- /dev/null +++ b/packages/web-client/src/components/icons/AirdropCompleteGraphics.svelte @@ -0,0 +1,265 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/web-client/src/components/icons/AirdropGraphic.svelte b/packages/web-client/src/components/icons/AirdropGraphic.svelte new file mode 100644 index 000000000..d0037ab87 --- /dev/null +++ b/packages/web-client/src/components/icons/AirdropGraphic.svelte @@ -0,0 +1,1164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/web-client/src/components/icons/AirdropIcon.svelte b/packages/web-client/src/components/icons/AirdropIcon.svelte new file mode 100644 index 000000000..2974bbee7 --- /dev/null +++ b/packages/web-client/src/components/icons/AirdropIcon.svelte @@ -0,0 +1,188 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/web-client/src/components/icons/Coin3dIcon.svelte b/packages/web-client/src/components/icons/Coin3dIcon.svelte new file mode 100644 index 000000000..1bd3fb0b7 --- /dev/null +++ b/packages/web-client/src/components/icons/Coin3dIcon.svelte @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/web-client/src/components/icons/InfoIcon.svelte b/packages/web-client/src/components/icons/InfoIcon.svelte new file mode 100644 index 000000000..957cf7e0d --- /dev/null +++ b/packages/web-client/src/components/icons/InfoIcon.svelte @@ -0,0 +1,19 @@ + + + + + + + diff --git a/packages/web-client/src/components/icons/QuestionIcon.svelte b/packages/web-client/src/components/icons/QuestionIcon.svelte new file mode 100644 index 000000000..3d296b5c1 --- /dev/null +++ b/packages/web-client/src/components/icons/QuestionIcon.svelte @@ -0,0 +1,17 @@ + + + + + + diff --git a/packages/web-client/src/components/layout/DotSeparator.svelte b/packages/web-client/src/components/layout/DotSeparator.svelte new file mode 100644 index 000000000..8e2d08ed4 --- /dev/null +++ b/packages/web-client/src/components/layout/DotSeparator.svelte @@ -0,0 +1,5 @@ +
    + {#each Array(6) as _} +
    + {/each} +
    diff --git a/packages/web-client/src/components/layout/PlayerLayout.svelte b/packages/web-client/src/components/layout/PlayerLayout.svelte index 9d3b1c519..da33e4993 100644 --- a/packages/web-client/src/components/layout/PlayerLayout.svelte +++ b/packages/web-client/src/components/layout/PlayerLayout.svelte @@ -2,6 +2,7 @@ import { page } from '$app/stores' import Avatar from '$components/avatar/Avatar.svelte' import IconButton from '$components/button/IconButton.svelte' +import AirdropIcon from '$components/icons/AirdropIcon.svelte' import EyeIcon from '$components/icons/EyeIcon.svelte' import FireIcon from '$components/icons/FireIcon.svelte' import FlagIcon from '$components/icons/FlagIcon.svelte' @@ -19,6 +20,7 @@ import Log from '$lib/utils/Log' import { generateRandomName } from '$lib/utils/randomUsername' import { getShortNumber } from '$lib/utils/shortNumber' import { authState } from '$stores/auth' +import { showAirdropPopup } from '$stores/popups' import userProfile from '$stores/userProfile' import { debounce } from 'throttle-debounce' @@ -32,6 +34,7 @@ export let showReportButton = false export let showHotOrNotButton = false export let showDescription = false export let unavailable = false +export let showAirdropButton = false export let watchHistoryDb: 'watch' | 'watch-hon' export let source: 'hon_feed' | 'main_feed' | 'speculation' | 'post' @@ -246,6 +249,17 @@ $: avatarUrl =
    + {#if showAirdropButton} + { + e.stopImmediatePropagation() + $showAirdropPopup = true + }} + ariaLabel="Join airdrop"> + + + {/if} {#if showReportButton} {/if} {#if showWalletLink} - + {/if} @@ -313,3 +327,27 @@ $: avatarUrl = {/if}
    + + diff --git a/packages/web-client/src/components/layout/SplashScreen.svelte b/packages/web-client/src/components/layout/SplashScreen.svelte index 649b580b9..9e24dff88 100644 --- a/packages/web-client/src/components/layout/SplashScreen.svelte +++ b/packages/web-client/src/components/layout/SplashScreen.svelte @@ -1,6 +1,6 @@ -{#if $splashScreen.show} +{#if $splashScreenPopup.show} diff --git a/packages/web-client/src/components/notification/NotificationItem.svelte b/packages/web-client/src/components/notification/NotificationItem.svelte index 67f2a07a2..b866a6570 100644 --- a/packages/web-client/src/components/notification/NotificationItem.svelte +++ b/packages/web-client/src/components/notification/NotificationItem.svelte @@ -20,11 +20,11 @@ function getNotificationMessage(item: NotificationHistory) { case 'WinningsEarnedFromBet': { switch (item.eventOutcome) { case 'Draw': - return 'The Result was a draw on a video you vote' + return 'The Result was a draw on a video you voted on' case 'Lost': - return `You lost on a video you vote` + return `You lost on a video you voted on` case 'Won': - return `Congratulations! You won ${item.token} tokens on a video you vote.` + return `Congratulations! You won ${item.token} tokens on a video you voted on.` } } } diff --git a/packages/web-client/src/components/popup/AirdropCountdown.svelte b/packages/web-client/src/components/popup/AirdropCountdown.svelte new file mode 100644 index 000000000..83f92a0bf --- /dev/null +++ b/packages/web-client/src/components/popup/AirdropCountdown.svelte @@ -0,0 +1,45 @@ + + +{#if !countdownOver} +
    +
    +
    + {$time.days.toString().padStart(2, '0')} +
    + Days +
    +
    +
    + {$time.hours.toString().padStart(2, '0')} +
    + Hours +
    +
    +
    + {$time.minutes.toString().padStart(2, '0')} +
    + Minutes +
    +
    +
    + {$time.seconds.toString().padStart(2, '0')} +
    + Seconds +
    +
    +{/if} diff --git a/packages/web-client/src/components/popup/AirdropPopup.svelte b/packages/web-client/src/components/popup/AirdropPopup.svelte new file mode 100644 index 000000000..ea3ec6e8a --- /dev/null +++ b/packages/web-client/src/components/popup/AirdropPopup.svelte @@ -0,0 +1,82 @@ + + +{#if $showAirdropPopup} + +
    + {#if participated} +
    + ($showAirdropPopup = false)} /> +
    + {:else} +
    + +
    +
    +
    + Airdrop +
    +
    + Join the whitelist and receive free HOT tokens +
    +
    + +
    + + + Learn more +
    + {/if} +
    +
    + ($showAirdropPopup = false)}> + + +
    +
    +{/if} diff --git a/packages/web-client/src/components/popup/AirdropPopupOnlyCountdown.svelte b/packages/web-client/src/components/popup/AirdropPopupOnlyCountdown.svelte new file mode 100644 index 000000000..decbc4865 --- /dev/null +++ b/packages/web-client/src/components/popup/AirdropPopupOnlyCountdown.svelte @@ -0,0 +1,113 @@ + + +{#if $showAirdropPopup} + +
    + {#if participated} +
    + ($showAirdropPopup = false)} /> +
    + {:else} +
    + +
    +
    +
    Coming Soon
    +
    + hot token airdrop +
    +
    + +
    + +
    + + +
    + + + Learn more about the airdrop here + +
    + {/if} +
    +
    + ($showAirdropPopup = false)}> + + +
    +
    +{/if} diff --git a/packages/web-client/src/components/popup/HotorNotOnboarding.svelte b/packages/web-client/src/components/popup/HotorNotOnboarding.svelte index 9eedccfc2..2f7195a3e 100644 --- a/packages/web-client/src/components/popup/HotorNotOnboarding.svelte +++ b/packages/web-client/src/components/popup/HotorNotOnboarding.svelte @@ -1,6 +1,6 @@ -{#if $showOnboarding} +{#if $showOnboardingPopup} @@ -37,7 +37,7 @@ let step: 1 | 2 | 3 | 4 = 1
    @@ -58,7 +58,9 @@ let step: 1 | 2 | 3 | 4 = 1
    - @@ -86,7 +88,9 @@ let step: 1 | 2 | 3 | 4 = 1 - @@ -108,7 +112,7 @@ let step: 1 | 2 | 3 | 4 = 1 Vote with the majority and win double the tokens! - diff --git a/packages/web-client/src/components/profile/SpeculationPost.svelte b/packages/web-client/src/components/profile/SpeculationPost.svelte index 03af93e22..9de1fcc95 100644 --- a/packages/web-client/src/components/profile/SpeculationPost.svelte +++ b/packages/web-client/src/components/profile/SpeculationPost.svelte @@ -7,7 +7,7 @@ import type { const betKeyword: Record = { Lost: 'lost', Draw: 'lost', - AwaitingResult: 'vote', + AwaitingResult: 'voted', Won: 'received', } diff --git a/packages/web-client/src/components/profile/SpeculationPosts.svelte b/packages/web-client/src/components/profile/SpeculationPosts.svelte index ee4493773..f7e870051 100644 --- a/packages/web-client/src/components/profile/SpeculationPosts.svelte +++ b/packages/web-client/src/components/profile/SpeculationPosts.svelte @@ -65,9 +65,9 @@ onMount(() => loadPosts())
    {#if me} - You don't have any current bets yet + You don't have any current votes yet {:else} - This user has not placed any bets yet + This user has not placed any vote yet {/if}
    diff --git a/packages/web-client/src/components/seo/GA.svelte b/packages/web-client/src/components/seo/GA.svelte index 3d5fe1f09..767b7e79a 100644 --- a/packages/web-client/src/components/seo/GA.svelte +++ b/packages/web-client/src/components/seo/GA.svelte @@ -39,11 +39,11 @@ export const registerEvent = ( { + try { + const res = await fetch('https://submitentry-5nps3y6y6a-uc.a.run.app', { + method: 'POST', + mode: 'cors', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ ...data, uid: x(data.canisterId + data.email) }), + }) + + const body = await res.json() + + console.log({ body }) + + if (body.success) return true + return false + } catch (e) { + console.error('Error adding document: ', e) + return false + } +} + +export async function isFormFilled(principalId: string): Promise { + try { + if (principalId === '2vxsx-fae') return false + + const res = await fetch( + `https://entryexists-5nps3y6y6a-uc.a.run.app/?principalId=${principalId}`, + { + mode: 'cors', + }, + ) + + const body = await res.json() + + if (body.success && body.exists) return true + return false + } catch (e) { + console.error('Error adding document: ', e) + return false + } +} + +export async function isInWaitlist(principalId: string): Promise { + try { + if (principalId === '2vxsx-fae') return false + + const res = await fetch( + `https://isinwaitlist-5nps3y6y6a-uc.a.run.app?principalId=${principalId}`, + { + mode: 'cors', + }, + ) + + const body = await res.json() + + if (body.success && body.exists) return true + return false + } catch (e) { + console.error('Error adding document: ', e) + return false + } +} + +export async function registerForWaitlist( + principalId: string, + email: string, +): Promise { + try { + if (principalId === '2vxsx-fae') return true + + const res = await fetch( + 'https://registerforwaitlist-5nps3y6y6a-uc.a.run.app', + { + method: 'POST', + mode: 'cors', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + principalId, + email, + uid: x(principalId + email), + }), + }, + ) + + const body = await res.json() + + if (body.success) return true + return false + } catch (e) { + console.error('Error adding document: ', e) + return false + } +} diff --git a/packages/web-client/src/lib/helpers/profile.ts b/packages/web-client/src/lib/helpers/profile.ts index 3a2cc468e..89a7a480a 100644 --- a/packages/web-client/src/lib/helpers/profile.ts +++ b/packages/web-client/src/lib/helpers/profile.ts @@ -398,7 +398,7 @@ type UnionValueOf = U extends U ? U[keyof U] : never const walletEventDetails = ({} as WalletEvent)?.details type WalletEvent = UnionValueOf type WalletEventDetails = typeof walletEventDetails -type WalletEventSubType = UnionKeyOf +export type WalletEventSubType = UnionKeyOf type WalletEventSubDetails = UnionValueOf type NotificationEventType = Omit< WalletEventSubType, diff --git a/packages/web-client/src/lib/utils/timeLeft.ts b/packages/web-client/src/lib/utils/timeLeft.ts index 67bd5107f..d05b1a879 100644 --- a/packages/web-client/src/lib/utils/timeLeft.ts +++ b/packages/web-client/src/lib/utils/timeLeft.ts @@ -1,6 +1,42 @@ import type { SystemTime } from '$canisters/individual_user_template/individual_user_template.did' import { readable } from 'svelte/store' + const ONE_HOUR_MS = 36_00_000 +const SECONDS_MS = 1000 +const MINUTES_MS = SECONDS_MS * 60 +const HOURS_MS = MINUTES_MS * 60 +const DAYS_MS = HOURS_MS * 24 + +type TimeParts = { + minutes: number + seconds: number + days: number + hours: number +} + +export function getTimeLeft(startTime: Date, endTime: Date) { + let diff = endTime.getTime() - startTime.getTime() + if (diff > 0) { + return readable(getTimeStringFromMs(diff), (set) => { + const updateMs = () => { + diff -= 1000 + if (diff > 0) { + set(getTimeStringFromMs(diff)) + } else { + clearInterval(interval) + } + } + + const interval = setInterval(updateMs, 1000) + + return () => { + clearInterval(interval) + } + }) + } else { + return readable({ minutes: 0, seconds: 0, days: 0, hours: 0 }) + } +} export function getMsLeftForBetResult( betSlotNumber: number, @@ -14,11 +50,18 @@ export function getMsLeftForBetResult( let diff = betEndTime.getTime() - now.getTime() if (diff > 0) { - return readable(getTimeStringFromMs(diff), (set) => { + const dt = getTimeStringFromMs(diff) + const initialValue = + dt.minutes + ':' + (dt.seconds < 10 ? '0' : '') + dt.seconds + + return readable(initialValue, (set) => { let counter = 1 const updateMs = () => { if (diff - counter * 1000 > 0) { - set(getTimeStringFromMs(diff - counter * 1000)) + const { minutes, seconds } = getTimeStringFromMs( + diff - counter * 1000, + ) + set(minutes + ':' + (seconds < 10 ? '0' : '') + seconds) } else { counter = 1 diff = ONE_HOUR_MS @@ -40,7 +83,14 @@ export function getMsLeftForBetResult( } export function getTimeStringFromMs(timeMs: number) { - const minutes = Math.floor(timeMs / 60000) - const seconds = Math.floor((timeMs % 60000) / 1000) - return minutes + ':' + (seconds < 10 ? '0' : '') + seconds + const days = Math.floor(timeMs / DAYS_MS) + const hours = Math.round((timeMs % DAYS_MS) / HOURS_MS) + const minutes = Math.floor((timeMs % HOURS_MS) / MINUTES_MS) + const seconds = Math.floor((timeMs % MINUTES_MS) / 1000) + return { + minutes, + seconds, + days, + hours, + } } diff --git a/packages/web-client/src/routes/(feed)/(splash)/+layout.svelte b/packages/web-client/src/routes/(feed)/(splash)/+layout.svelte index bc6f398b8..b1417106a 100644 --- a/packages/web-client/src/routes/(feed)/(splash)/+layout.svelte +++ b/packages/web-client/src/routes/(feed)/(splash)/+layout.svelte @@ -1,7 +1,12 @@ +{#if !$splashScreenPopup.show} + +{/if} diff --git a/packages/web-client/src/routes/(feed)/(splash)/feed/[id=videoId]/+page.svelte b/packages/web-client/src/routes/(feed)/(splash)/feed/[id=videoId]/+page.svelte index 334b2cc92..f39a2d128 100644 --- a/packages/web-client/src/routes/(feed)/(splash)/feed/[id=videoId]/+page.svelte +++ b/packages/web-client/src/routes/(feed)/(splash)/feed/[id=videoId]/+page.svelte @@ -16,9 +16,9 @@ import Log from '$lib/utils/Log' import { handleParams } from '$lib/utils/params' import { joinArrayUniquely, updateMetadata } from '$lib/utils/video' import { homeFeedVideos, playerState } from '$stores/playerState' -import { hideSplashScreen } from '$stores/splashScreen' +import { hideSplashScreen } from '$stores/popups' import Hls from 'hls.js/dist/hls.min.js' -import { onDestroy, onMount, tick } from 'svelte' +import { onMount, tick } from 'svelte' import 'swiper/css' import { Swiper, SwiperSlide } from 'swiper/svelte' import type { PageData } from './$types' diff --git a/packages/web-client/src/routes/(feed)/(splash)/feed/no-videos/+page.svelte b/packages/web-client/src/routes/(feed)/(splash)/feed/no-videos/+page.svelte index 068521e65..e43e1ce03 100644 --- a/packages/web-client/src/routes/(feed)/(splash)/feed/no-videos/+page.svelte +++ b/packages/web-client/src/routes/(feed)/(splash)/feed/no-videos/+page.svelte @@ -1,7 +1,7 @@ - + Hot or Not Feed | Hot or Not diff --git a/packages/web-client/src/routes/(feed)/(splash)/hotornot/[id=videoId]/+page.svelte b/packages/web-client/src/routes/(feed)/(splash)/hotornot/[id=videoId]/+page.svelte index b8b22ff90..c30396414 100644 --- a/packages/web-client/src/routes/(feed)/(splash)/hotornot/[id=videoId]/+page.svelte +++ b/packages/web-client/src/routes/(feed)/(splash)/hotornot/[id=videoId]/+page.svelte @@ -15,7 +15,7 @@ import Log from '$lib/utils/Log' import { handleParams } from '$lib/utils/params' import { joinArrayUniquely, updateMetadata } from '$lib/utils/video' import { hotOrNotFeedVideos, playerState } from '$stores/playerState' -import { hideSplashScreen } from '$stores/splashScreen' +import { hideSplashScreen } from '$stores/popups' import Hls from 'hls.js/dist/hls.min.js' import { onMount, tick } from 'svelte' import 'swiper/css' @@ -160,6 +160,7 @@ beforeNavigate(() => { source="hon_feed" watchHistoryDb="watch-hon" showWalletLink + showAirdropButton showReportButton let:recordView let:updateStats> diff --git a/packages/web-client/src/routes/(feed)/(splash)/hotornot/no-videos/+page.svelte b/packages/web-client/src/routes/(feed)/(splash)/hotornot/no-videos/+page.svelte index cb8bb18b9..857df0d4a 100644 --- a/packages/web-client/src/routes/(feed)/(splash)/hotornot/no-videos/+page.svelte +++ b/packages/web-client/src/routes/(feed)/(splash)/hotornot/no-videos/+page.svelte @@ -1,7 +1,7 @@ + + + Airdrop Guide | Hot or Not + + + + + + +
    + Airdrop Guide +
    + goBack($navigateBack || '/menu', true)} + class="shrink-0"> + + +
    +
    +
    + +
    +
    +

    Guide

    +

    + Hot or Not is a social media platform for short videos, similar to + TikTok but on Web3. It integrates gamification with social media and + is built on a ground-breaking Level-1 blockchain called the + + Internet Computer Protocol + + . +

    +

    + Hot or Not is conducting a decentralization sale ( + + SNS + + sale) of its governance tokens, HOT. The sale aims to give users ownership + of the platform, placing them at the center of the ecosystem. Users will + have an active role in steering the ecosystem while receiving rewards for + their participation. +

    +

    + To recognize the support of its users and early adopters, Hot or Not + is airdropping 10 million HOT tokens (1% of the initial token supply) + for free. This presents a unique opportunity for users to join the + growing community and receive free tokens. +

    +

    + It's important to note that HOT tokens are governance tokens on the + platform, while COYN is the in-app utility token. COYN is not listed, + while HOT tokens will be listed once the sale is completed. Are you + interested in participating in the upcoming HOT token airdrop? Look no + further -- We've compiled all the information you need to know to + register and be eligible for the airdrop. +

    +

    + Are you interested in participating in the upcoming HOT token airdrop? + Look no further -- We've compiled all the information you need to know + to register and be eligible for the airdrop. +

    + +

    Registration and Eligibility

    + +

    + You must register to participate in the airdrop. Just click the + "Notify Me" button at the bottom of this page, and we'll let you know + when the airdrop form is live. Take a look at the registration steps + below and get ready: +

    + +

    Registration process:

    + +
  • Login through Google or Internet Identity
  • +
  • + The following information will be taken automatically upon login: +
    +
  • Principal ID (HotOrNot)
  • +
  • + Current wallet balance (final balance on 22nd June, 2023 12PM UTC + will be considered for airdrop allotment) +
  • +
    + +
  • + Fill out the airdrop form with the following details: +
    +
  • Email
  • +
  • A tweet with the hashtag #hotornot and paste link
  • +
    + +

    + Optional information for additional rewards: + +

  • Plug Principal ID holding Gob-Gob NFT
  • +
  • Plug Principal ID holding Hot or Not Funded NFT
  • +
  • NNS Principal ID holding SNS-1 Token
  • +
  • NNS Principal ID holding Chat Token
  • +

    + +

    Rewards

    +

    + The number of HOT tokens allocated to one whitelisted/ waitlisted + applicant is calculated based on their wallet balance on the cut-off + date using the following formula: +

    +

    + Wallet Balance of the Applicant / Total Wallet Balance of all + Applicants * 10,000,000 +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Category of ApplicantWallet Balance considered on cutoff date
    Regular Whitelisted ApplicantsIn-app Wallet Balance on Cutoff Date
    Whitelisted Applicants who own GobGob NFTsIn-app Wallet Balance on Cutoff Date + 1,000 COYNs
    + Whitelisted Applicants who own Tier 1 Funded NFTs (issued in + December 2022) + In-app Wallet Balance on Cutoff Date + 5,000 COYNs
    + Whitelisted Applicants who own Tier 2 Funded NFTs (issued in + December 2022) + In-app Wallet Balance on Cutoff Date + 10,000 COYNs
    + Whitelisted Applicants who own Tier 3 Funded NFTs (issued in + December 2022) + In-app Wallet Balance on Cutoff Date + 20,000 COYNs
    Whitelisted Applicants who own CHAT TokensIn-app Wallet Balance on Cutoff Date + 1,000 COYNs
    Whitelisted Applicants who own SNS1 TokensIn-app Wallet Balance on Cutoff Date + 1,000 COYNs
    +

    + There are a limited number of sign-ups available on the Hot or Not + platform before we hit the subnet limit. So hurry before we run out of + sign-ups! The airdrop is on a first come, first serve basis. +

    +

    + In case we reach the subnet limit, the sign-ups on the platform would + be halted. For those who register for the airdrop post this event, the + wallet balance would be considered as 100 COYNs on the cutoff date. +

    +

    + The maximum reward per participant is 10,000 HOT tokens, regardless of + their wallet balance, to prevent excessive token allocation and ensure + fairness. Additionally, this measure prevents bots from taking over + and monopolizing the airdrop, making it more accessible to genuine + human participants. +

    +

    + The allocation of the HOT tokens from the airdrop is subject to the + verification of NFT (if any) and the completion of proof of humanity + by the applicant. The details would be shared with the registered + applicants at a later date. +

    + +
    +
    + + + + + + Don't miss this opportunity to become a part of our growing + community and receive free tokens! + +
    +
    + +
    + +
    +
    +
    + + diff --git a/packages/web-client/src/routes/airdrop/+page.svelte b/packages/web-client/src/routes/airdrop/+page.svelte new file mode 100644 index 000000000..2ab5d95fa --- /dev/null +++ b/packages/web-client/src/routes/airdrop/+page.svelte @@ -0,0 +1,35 @@ + + + + Airdrop | Hot or Not + + + + +
    + Airdrop +
    + goBack($navigateBack || '/menu', true)} + class="shrink-0"> + + +
    +
    +
    + +
    + +
    +
    +
    diff --git a/packages/web-client/src/routes/profile/[id]/speculations/[postId=videoId]/+page.svelte b/packages/web-client/src/routes/profile/[id]/speculations/[postId=videoId]/+page.svelte index 40a35e949..7edf3fe5e 100644 --- a/packages/web-client/src/routes/profile/[id]/speculations/[postId=videoId]/+page.svelte +++ b/packages/web-client/src/routes/profile/[id]/speculations/[postId=videoId]/+page.svelte @@ -17,7 +17,7 @@ let unavailable = false - {me ? 'Your' : "User's"} Bets | Hot or Not + {me ? 'Your' : "User's"} Participations | Hot or Not @@ -25,7 +25,7 @@ let unavailable = false {#if me != undefined}
    - {me ? 'Your' : "User's"} Bets + {me ? 'Your' : "User's"} HotOrNot
    {/if} diff --git a/packages/web-client/src/stores/hotOrNotOnboarding.ts b/packages/web-client/src/stores/hotOrNotOnboarding.ts deleted file mode 100644 index db52fec51..000000000 --- a/packages/web-client/src/stores/hotOrNotOnboarding.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { persisted } from 'svelte-local-storage-store' - -export const showOnboarding = persisted('hot-or-not-ob', true) diff --git a/packages/web-client/src/stores/popups.ts b/packages/web-client/src/stores/popups.ts new file mode 100644 index 000000000..a385f3bcd --- /dev/null +++ b/packages/web-client/src/stores/popups.ts @@ -0,0 +1,24 @@ +import { writable, get } from 'svelte/store' +import { persisted } from 'svelte-local-storage-store' + +export const showOnboardingPopup = persisted('hot-or-not-ob', true) + +export const splashScreenPopup = writable<{ + show: boolean + shown: boolean +}>({ + show: true, + shown: false, +}) + +export const showAirdropPopup = writable(false) + +let splashScreenTimeOut: NodeJS.Timeout + +export function hideSplashScreen(timeoutMs: number = 2000) { + if (get(splashScreenPopup).shown) return + if (splashScreenTimeOut) clearTimeout(splashScreenTimeOut) + splashScreenTimeOut = setTimeout(() => { + splashScreenPopup.set({ show: false, shown: true }) + }, timeoutMs) +} diff --git a/packages/web-client/src/stores/splashScreen.ts b/packages/web-client/src/stores/splashScreen.ts deleted file mode 100644 index 4b111b908..000000000 --- a/packages/web-client/src/stores/splashScreen.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { writable, get } from 'svelte/store' - -export const splashScreen = writable<{ - show: boolean - shown: boolean -}>({ - show: true, - shown: false, -}) - -let timeout - -export function hideSplashScreen(timeoutMs: number = 2000) { - if (get(splashScreen).shown) return - if (timeout) clearTimeout(timeout) - timeout = setTimeout(() => { - splashScreen.set({ show: false, shown: true }) - }, timeoutMs) -} diff --git a/packages/workers/package.json b/packages/workers/package.json index 4c6098500..172d33ef8 100644 --- a/packages/workers/package.json +++ b/packages/workers/package.json @@ -1,5 +1,5 @@ { - "name": "@hnn/workers-api", + "name": "@hnn/workers", "version": "1.0.0", "description": "", "main": "index.js",