From 93879ecdaa48ed4749f5dae94e62d27b107a7387 Mon Sep 17 00:00:00 2001 From: Andrei O Date: Thu, 13 Apr 2023 03:32:37 +0300 Subject: [PATCH] add: support for new notifs --- CHANGELOG.MD | 6 + manifest.json | 2 +- src/components/Notification.svelte | 275 ++++++++++++++++++++--------- src/pages/Notifications.svelte | 16 +- src/utils/notifications.ts | 43 +++-- src/utils/types.ts | 7 + src/utils/votes.ts | 6 +- 7 files changed, 235 insertions(+), 120 deletions(-) diff --git a/CHANGELOG.MD b/CHANGELOG.MD index 2d165d6..b445a6c 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -1,5 +1,11 @@ # Change Log +## [Version 1.0.6] + +- refactored notifications +- added support for aggregated notifications +- added support for follow notification + ## [Version 1.0.5] - added: `setting` to enable right click page context like at user suggestion diff --git a/manifest.json b/manifest.json index 510c26d..1ddd43d 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "name": "yup live", "description": "Light alternative extension for yup protocol", - "version": "1.0.5", + "version": "1.0.6", "manifest_version": 3, "icons": { "16": "src/assets/icons/yup_ext_16.png", diff --git a/src/components/Notification.svelte b/src/components/Notification.svelte index e9afa62..5f4fa1a 100644 --- a/src/components/Notification.svelte +++ b/src/components/Notification.svelte @@ -1,93 +1,202 @@ -{#if notif.action === 'vote'} -{@const url = notif.post.url } -{@const length = url.length} -{@const shortUrl = url.slice(0, 10) + '...' + url.slice(length - 10, length) } -{@const finalUrl = length > 24 ? shortUrl : url } -
- - loader.onError()} style="{ $mainStore.settings.theme === 'light'? 'filter: invert(0.9);' : '' }" slot="img" src="{notif.image}" alt="preview"> - - - -
-

- {#if notif.like} - - {:else} - - {/if} - by {notif.voter.length > 12 ? notif.voter.slice(0, 12) + '...' : notif.voter} -

-

- extrenalNavigate(`https://yup-live.pages.dev/post/${notif.postid}`)} - aria-hidden - class="text-blue-200 interactive-svg">{finalUrl} -

-

- - {timeSince(new Date(notif.createdAt))}

-
-
- {:else if notif.action === 'reward'} -
- reward -
-

You were alocated a future reward of {notif?.quantity ?? 'unknown'} amount of YUP. -

-

- - {timeSince(new Date(notif.createdAt))}

-
-
- {:else } -
-
-

{notif?.message ?? 'unknown notification type'}

-

- - {timeSince(new Date(notif.createdAt))}

-
-
+{#if notif.action === "vote"} + {@const url = notif.post.url} + {@const length = url.length} + {@const shortUrl = url.slice(0, 10) + "..." + url.slice(length - 10, length)} + {@const finalUrl = length > 24 ? shortUrl : url} +
+ + loader.onLoad()} + on:error={() => loader.onError()} + style={$mainStore.settings.theme === "light" ? "filter: invert(0.9);" : ""} + slot="img" + src={notif.image} + alt="preview" + /> + + + +
+

+ {#if notif.like} + + {:else} + {/if} - - + by + {#if notif?.notifications?.length > 1} + {notif?.notifications[0].VoterHandle} + {#if notif.notifications.length - 1 > 0} + and {notif.notifications.length - 1} more + {/if} + {:else} + {notif.voter.length > 12 ? notif.voter.slice(0, 12) + "..." : notif.voter} + {/if} +

+

+ extrenalNavigate(`https://yup-live.pages.dev/post/${notif.postid}`)} + aria-hidden + class="text-blue-200 interactive-svg">{finalUrl} +

+

+ + {timeSince(new Date(notif.createdAt))} +

+
+
+{:else if notif.action === "reward"} +
+ reward +
+

+ You were alocated a future reward of {notif?.quantity ?? "unknown"} amount of YUP. +

+

+ + {timeSince(new Date(notif.createdAt))} +

+
+
+{:else if ["follow", "unfollow"].includes(notif.action)} +
+ + loader.onLoad()} + on:error={() => loader.onError()} + style={$mainStore.settings.theme === "light" ? "filter: invert(0.9);" : ""} + slot="img" + src={notif.image} + alt="preview" + /> + + + +
+

extrenalNavigate(`https://yup-live.pages.dev/web3-profile/${notif.EVMRecipient?.address}`)} + > + {notif?.EVMRecipient?.handle || `${notif.EVMRecipient?.address?.slice(0, 6)}...`} + {notif.action === "follow" ? "followed" : "unfollowed"} you. +

+

+ + {timeSince(new Date(notif.createdAt))} +

+
+
+{:else} +
+
+

{notif?.message ?? "unknown notification type"}

+

+ + {timeSince(new Date(notif.createdAt))} +

+
+
+{/if} \ No newline at end of file + .like-dislike { + position: relative; + top: 0.2rem; + } + diff --git a/src/pages/Notifications.svelte b/src/pages/Notifications.svelte index 1e6f844..1fcfca0 100644 --- a/src/pages/Notifications.svelte +++ b/src/pages/Notifications.svelte @@ -12,7 +12,7 @@ let loading = true; let noNotifications = false; let notifs = []; let pastNotifsPromise -let type = 'all' +let type = null onMount(async () => { notifs = await getNotifications({ @@ -35,13 +35,9 @@ onMount(async () => { }); -const changeNotifsType = async (t :string) => { - if(type === t) return; - if(!['all', 'rewards'].includes(t)){ - console.error('Invalid type'); - return; - } - type = t; +const changeNotifsType = async (t : string[] | null) => { + if(String(type) === String(t)) return; + type = t loading = true; notifs = await getNotifications({ userId: $mainStore.user.auth.userId, @@ -71,8 +67,8 @@ const changeNotifsType = async (t :string) => { {/await} {:else}
- changeNotifsType('all')} aria-hidden class="inline-block mr-2 interactive-svg text-blue-200 interactive-svg" >All - changeNotifsType('rewards')} aria-hidden class="text-blue-200 interactive-svg interactive-svg text-blue-200 interactive-svg">Rewards + changeNotifsType(null)} aria-hidden class="inline-block mr-2 interactive-svg text-blue-200 interactive-svg" >All + changeNotifsType(['reward'])} aria-hidden class="text-blue-200 interactive-svg interactive-svg text-blue-200 interactive-svg">Rewards
{#each notifs.reverse() as notif} diff --git a/src/utils/notifications.ts b/src/utils/notifications.ts index 18b5494..cf8efb5 100644 --- a/src/utils/notifications.ts +++ b/src/utils/notifications.ts @@ -3,33 +3,30 @@ import type { StorageType } from '@/utils/storage' import { fetchWAuth } from '@/utils/auth' import { wait } from '@/utils/time' +export const notificationTypes = ['vote', 'reward', 'all-followers', 'follow', 'unfollow'] + export const getNotifications = async ( - { type, limit, skip, userId } = { type: 'all', limit: '10', skip: '0' } as { userId: string, type: string; limit?: string; skip?: string } + { type, limit, skip, userId } = { type: null, limit: '10', skip: '0' } as { userId: string, type: null | string[]; limit?: string; skip?: string } ) => { let req - - if (type === 'all') { - req = await fetch(`${API_BASE}/notifications/${userId}?skip=${skip}&limit=${limit}`, { - method: 'GET', - headers: { - 'Content-Type': 'application/json;charset=utf-8' - } - }) - } else if (type === 'vote') { - req = await fetch(`${API_BASE}/notifications/${userId}?skip=${skip}&limit=${limit}&type=vote`, { - method: 'GET', - headers: { - 'Content-Type': 'application/json;charset=utf-8' - } - }) - } else { - req = await fetch(`${API_BASE}/notifications/${userId}?skip=${skip}&limit=${limit}&type=reward`, { - method: 'GET', - headers: { - 'Content-Type': 'application/json;charset=utf-8' - } - }) + let queryType = '' + if (type) { + queryType = `&inType=${type.join(',')}` } + if (!limit) { + limit = '10' + } + + if (!skip) { + skip = '0' + } + + req = await fetch(`${API_BASE}/notifications/${userId}?skip=${skip}&limit=${limit}${queryType}`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json;charset=utf-8' + } + }) if (!req.ok) { return false diff --git a/src/utils/types.ts b/src/utils/types.ts index e1b1b9c..e5b940c 100644 --- a/src/utils/types.ts +++ b/src/utils/types.ts @@ -27,6 +27,12 @@ export interface Vote { title: string tag: string } + EVMRecipient: { + handle: string + address: string + avatar: string + } + notifications: Notification[] seen: boolean postid: string rating: number @@ -35,4 +41,5 @@ export interface Vote { createdAt: string quantity?: string message?: string + VoterHandle: string } \ No newline at end of file diff --git a/src/utils/votes.ts b/src/utils/votes.ts index f861c1a..9efd759 100644 --- a/src/utils/votes.ts +++ b/src/utils/votes.ts @@ -67,7 +67,7 @@ export const executeVote = async ({ body: JSON.stringify(body) }) if (req.ok) { - noVoteAlert || $alertStore?.show('Rating submited!') + noVoteAlert || $alertStore?.show('Rating submitted!') return await req.json() } else { const err = await req.text() @@ -76,9 +76,9 @@ export const executeVote = async ({ } else if(err.includes('requests')) { $alertStore?.show('You have made too many request try again after 24h', 'warning') } else if(err.toLocaleLowerCase().includes('unauthorized')) { - $alertStore?.show('Seems your auth token is not valid anymore re-login!!', 'error') + $alertStore?.show('Seems your auth token has expired re-login!!', 'error') } else { - $alertStore?.show('Vote not submited due to error try to re-login!', 'error') + $alertStore?.show('Rating not submitted due to error try to re-login!', 'error') } return null }