feat: task list (nip5 task)
This commit is contained in:
parent
d4c1651f8f
commit
b3cc84a0b1
@ -345,5 +345,14 @@
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</symbol>
|
||||
<symbol id="lightbulb" viewBox="0 0 22 22" fill="none">
|
||||
<path
|
||||
d="M9 16.6586V19C9 20.1046 9.89543 21 11 21C12.1046 21 13 20.1046 13 19V16.6586M11 1V2M2 11H1M4.5 4.5L3.8999 3.8999M17.5 4.5L18.1002 3.8999M21 11H20M17 11C17 14.3137 14.3137 17 11 17C7.68629 17 5 14.3137 5 11C5 7.68629 7.68629 5 11 5C14.3137 5 17 7.68629 17 11Z"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</symbol>
|
||||
</defs>
|
||||
</svg>
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 32 KiB |
@ -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 (
|
||||
<>
|
||||
<div className="main-content">
|
||||
<TaskList />
|
||||
</div>
|
||||
{pubkey && (
|
||||
<Timeline
|
||||
subject={{
|
||||
|
@ -9,9 +9,9 @@ import { RootState } from "State/Store";
|
||||
import Timeline from "Element/Timeline";
|
||||
import { System } from "System";
|
||||
import { TimelineSubject } from "Feed/TimelineFeed";
|
||||
import { debounce, unwrap } from "Util";
|
||||
|
||||
import messages from "./messages";
|
||||
import { debounce, unwrap } from "Util";
|
||||
|
||||
interface RelayOption {
|
||||
url: string;
|
||||
|
29
packages/app/src/Tasks/Nip5Task.tsx
Normal file
29
packages/app/src/Tasks/Nip5Task.tsx
Normal file
@ -0,0 +1,29 @@
|
||||
import { FormattedMessage } from "react-intl";
|
||||
import { Link } from "react-router-dom";
|
||||
import { MetadataCache } from "State/Users";
|
||||
import { BaseUITask } from "Tasks";
|
||||
|
||||
export class Nip5Task extends BaseUITask {
|
||||
id = "buy-nip5";
|
||||
|
||||
check(user: MetadataCache): boolean {
|
||||
return !this.state.muted && !user.nip05;
|
||||
}
|
||||
|
||||
render(): JSX.Element {
|
||||
return (
|
||||
<p>
|
||||
<FormattedMessage
|
||||
defaultMessage="Hey, it looks like you dont have a NIP-05 handle yet, you should get one! Check out {link}"
|
||||
values={{
|
||||
link: (
|
||||
<Link to="/verification">
|
||||
<FormattedMessage defaultMessage="NIP-05 Shop" />
|
||||
</Link>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</p>
|
||||
);
|
||||
}
|
||||
}
|
39
packages/app/src/Tasks/TaskList.tsx
Normal file
39
packages/app/src/Tasks/TaskList.tsx
Normal file
@ -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<UITask> = [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<number>(0);
|
||||
|
||||
function muteTask(t: UITask) {
|
||||
t.mute();
|
||||
setTick(x => (x += 1));
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{AllTasks.filter(a => (user ? a.check(user) : false)).map(a => {
|
||||
return (
|
||||
<div key={a.id} className="card">
|
||||
<div className="header">
|
||||
<Icon name="lightbulb" />
|
||||
<div className="close" onClick={() => muteTask(a)}>
|
||||
<Icon name="close" size={14} />
|
||||
</div>
|
||||
</div>
|
||||
{a.render()}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
};
|
46
packages/app/src/Tasks/index.ts
Normal file
46
packages/app/src/Tasks/index.ts
Normal file
@ -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));
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user