diff --git a/packages/app/public/icons.svg b/packages/app/public/icons.svg index 9c77efe..6ef0b3c 100644 --- a/packages/app/public/icons.svg +++ b/packages/app/public/icons.svg @@ -345,5 +345,14 @@ stroke-linejoin="round" /> + + + \ No newline at end of file diff --git a/packages/app/src/Pages/Notifications.tsx b/packages/app/src/Pages/Notifications.tsx index b711098..1af84d5 100644 --- a/packages/app/src/Pages/Notifications.tsx +++ b/packages/app/src/Pages/Notifications.tsx @@ -4,6 +4,7 @@ import { HexKey } from "@snort/nostr"; import { markNotificationsRead } from "State/Login"; import { RootState } from "State/Store"; import Timeline from "Element/Timeline"; +import { TaskList } from "Tasks/TaskList"; export default function NotificationsPage() { const dispatch = useDispatch(); @@ -15,6 +16,9 @@ export default function NotificationsPage() { return ( <> +
+ +
{pubkey && ( + + + + ), + }} + /> +

+ ); + } +} diff --git a/packages/app/src/Tasks/TaskList.tsx b/packages/app/src/Tasks/TaskList.tsx new file mode 100644 index 0000000..d4e2449 --- /dev/null +++ b/packages/app/src/Tasks/TaskList.tsx @@ -0,0 +1,39 @@ +import { useUserProfile } from "Feed/ProfileFeed"; +import Icon from "Icons/Icon"; +import { useState } from "react"; +import { useSelector } from "react-redux"; +import { RootState } from "State/Store"; +import { UITask } from "Tasks"; +import { Nip5Task } from "./Nip5Task"; + +const AllTasks: Array = [new Nip5Task()]; +AllTasks.forEach(a => a.load()); + +export const TaskList = () => { + const publicKey = useSelector((s: RootState) => s.login.publicKey); + const user = useUserProfile(publicKey); + const [, setTick] = useState(0); + + function muteTask(t: UITask) { + t.mute(); + setTick(x => (x += 1)); + } + + return ( + <> + {AllTasks.filter(a => (user ? a.check(user) : false)).map(a => { + return ( +
+
+ +
muteTask(a)}> + +
+
+ {a.render()} +
+ ); + })} + + ); +}; diff --git a/packages/app/src/Tasks/index.ts b/packages/app/src/Tasks/index.ts new file mode 100644 index 0000000..86be170 --- /dev/null +++ b/packages/app/src/Tasks/index.ts @@ -0,0 +1,46 @@ +import { MetadataCache } from "State/Users"; + +export interface UITask { + id: string; + /** + * Run checks to determine if this Task should be triggered for this user + */ + check(user: MetadataCache): boolean; + mute(): void; + load(): void; + render(): JSX.Element; +} + +export interface UITaskState { + id: string; + muted: boolean; + completed: boolean; +} + +export abstract class BaseUITask implements UITask { + protected state: UITaskState; + + abstract id: string; + abstract check(user: MetadataCache): boolean; + abstract render(): JSX.Element; + + constructor() { + this.state = {} as UITaskState; + } + + mute(): void { + this.state.muted = true; + this.#save(); + } + + load() { + const state = window.localStorage.getItem(`task:${this.id}`); + if (state) { + this.state = JSON.parse(state); + } + } + + #save() { + window.localStorage.setItem(`task:${this.id}`, JSON.stringify(this.state)); + } +}