feat: task list (nip5 task)
This commit is contained in:
parent
d4c1651f8f
commit
b3cc84a0b1
@ -345,5 +345,14 @@
|
|||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
/>
|
/>
|
||||||
</symbol>
|
</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>
|
</defs>
|
||||||
</svg>
|
</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 { markNotificationsRead } from "State/Login";
|
||||||
import { RootState } from "State/Store";
|
import { RootState } from "State/Store";
|
||||||
import Timeline from "Element/Timeline";
|
import Timeline from "Element/Timeline";
|
||||||
|
import { TaskList } from "Tasks/TaskList";
|
||||||
|
|
||||||
export default function NotificationsPage() {
|
export default function NotificationsPage() {
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
@ -15,6 +16,9 @@ export default function NotificationsPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
<div className="main-content">
|
||||||
|
<TaskList />
|
||||||
|
</div>
|
||||||
{pubkey && (
|
{pubkey && (
|
||||||
<Timeline
|
<Timeline
|
||||||
subject={{
|
subject={{
|
||||||
|
@ -9,9 +9,9 @@ import { RootState } from "State/Store";
|
|||||||
import Timeline from "Element/Timeline";
|
import Timeline from "Element/Timeline";
|
||||||
import { System } from "System";
|
import { System } from "System";
|
||||||
import { TimelineSubject } from "Feed/TimelineFeed";
|
import { TimelineSubject } from "Feed/TimelineFeed";
|
||||||
|
import { debounce, unwrap } from "Util";
|
||||||
|
|
||||||
import messages from "./messages";
|
import messages from "./messages";
|
||||||
import { debounce, unwrap } from "Util";
|
|
||||||
|
|
||||||
interface RelayOption {
|
interface RelayOption {
|
||||||
url: string;
|
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…
Reference in New Issue
Block a user