feat: task list (nip5 task)

This commit is contained in:
Kieran 2023-03-03 11:45:47 +00:00
parent d4c1651f8f
commit b3cc84a0b1
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
6 changed files with 128 additions and 1 deletions

View File

@ -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

View File

@ -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={{

View File

@ -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;

View 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>
);
}
}

View 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>
);
})}
</>
);
};

View 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));
}
}