From 9eec477e0e746a0c2929f2cdc929fff6d05af6f6 Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Tue, 10 Nov 2020 11:41:19 +1000 Subject: [PATCH 1/4] hark-graph-hook: watch individual indices --- pkg/arvo/app/hark-graph-hook.hoon | 34 +++++++++++++++-------- pkg/arvo/lib/graph-store.hoon | 1 + pkg/arvo/lib/hark/graph-hook.hoon | 33 ++++++++++++---------- pkg/arvo/mar/graph/validator/link.hoon | 4 +-- pkg/arvo/mar/graph/validator/publish.hoon | 4 +-- pkg/arvo/sur/hark-graph-hook.hoon | 6 ++-- 6 files changed, 49 insertions(+), 33 deletions(-) diff --git a/pkg/arvo/app/hark-graph-hook.hoon b/pkg/arvo/app/hark-graph-hook.hoon index 1f0bf1d51d..9ba152630b 100644 --- a/pkg/arvo/app/hark-graph-hook.hoon +++ b/pkg/arvo/app/hark-graph-hook.hoon @@ -12,7 +12,7 @@ :: +$ state-0 $: %0 - watching=(set resource) + watching=(set [resource index:post]) mentions=_& watch-on-self=_& == @@ -83,16 +83,16 @@ %set-watch-on-self (set-watch-on-self +.action) == ++ listen - |= graph=resource + |= [graph=resource =index:post] ^- (quip card _state) - :- (give:ha ~[/updates] [%listen graph]) - state(watching (~(put in watching) graph)) + :- (give:ha ~[/updates] [%listen graph index]) + state(watching (~(put in watching) [graph index])) :: ++ ignore - |= graph=resource + |= [graph=resource =index:post] ^- (quip card _state) - :- (give:ha ~[/updates] [%ignore graph]) - state(watching (~(del in watching) graph)) + :- (give:ha ~[/updates] [%ignore graph index]) + state(watching (~(del in watching) [graph index])) :: ++ set-mentions |= ment=? @@ -127,10 +127,18 @@ (graph-update !<(update:graph-store q.cage.sign)) [cards this] == + ++ add-graph + |= rid=resource + ^- (quip card _state) + ?. &(watch-on-self =(our.bowl entity.rid)) + [~ state] + `state(watching (~(put in watching) [rid ~])) :: ++ graph-update |= =update:graph-store ^- (quip card _state) + ?: ?=(%add-graph -.q.update) + (add-graph resource.q.update) ?. ?=(%add-nodes -.q.update) [~ state] =/ group=resource @@ -187,15 +195,19 @@ (self-post node) :_ state (weld child-cards self-cards) - =+ !<(notif-kind=(unit @t) (tube !>([0 post.node]))) + =+ !< notif-kind=(unit [name=@t parent-lent=@ud]) + (tube !>([0 post.node])) ?~ notif-kind [child-cards state] =/ desc=@t ?: (is-mention contents.post.node) %mention - u.notif-kind + name.u.notif-kind + =/ parent=index:post + (scag parent-lent.u.notif-kind index.post.node) + ~& parent ?. ?| =(desc %mention) - (~(has in watching) rid) + (~(has in watching) [rid parent]) == [child-cards state] =/ notif-index=index:store @@ -222,7 +234,7 @@ ^- (quip card _state) ?. ?=(%.y watch-on-self) [~ state] - `state(watching (~(put in watching) rid)) + `state(watching (~(put in watching) [rid index.post.node])) :: ++ add-unread |= [=index:store =notification:store] diff --git a/pkg/arvo/lib/graph-store.hoon b/pkg/arvo/lib/graph-store.hoon index 98eaa8fc68..0b339bc769 100644 --- a/pkg/arvo/lib/graph-store.hoon +++ b/pkg/arvo/lib/graph-store.hoon @@ -52,6 +52,7 @@ ++ index |= i=^index ^- json + ?: =(~ i) s+'/' =/ j=^tape "" |- ?~ i [%s (crip j)] diff --git a/pkg/arvo/lib/hark/graph-hook.hoon b/pkg/arvo/lib/hark/graph-hook.hoon index 2607733404..06e20fcb61 100644 --- a/pkg/arvo/lib/hark/graph-hook.hoon +++ b/pkg/arvo/lib/hark/graph-hook.hoon @@ -1,4 +1,4 @@ -/- sur=hark-graph-hook +/- sur=hark-graph-hook, post /+ graph-store, resource ^? =< [. sur] @@ -9,20 +9,20 @@ =, dejs:format |% :: - ++ graph-indices - %- ot - :~ graph+dejs-path:resource - indices+(as graph-index) - == - :: - ++ graph-index + ++ index ^- $-(json index:graph-store) (su ;~(pfix net (more net dem))) :: + ++ graph-index + %- ot + :~ graph+dejs-path:resource + index+index + == + :: ++ action %- of - :~ listen+dejs-path:resource - ignore+dejs-path:resource + :~ listen+graph-index + ignore+graph-index set-mentions+bo set-watch-on-self+bo == @@ -31,11 +31,11 @@ =, enjs:format |% :: - ++ graph-indices - |= [graph=resource indices=(set index:graph-store)] + ++ graph-index + |= [graph=resource =index:post] %- pairs :~ graph+s+(enjs-path:resource graph) - indices+a+(turn ~(tap in indices) index:enjs:graph-store) + index+(index:enjs:graph-store index) == :: ++ action @@ -45,9 +45,11 @@ ?- -.act %set-watch-on-self b+watch-on-self.act %set-mentions b+mentions.act - ?(%listen %ignore) s+(enjs-path:resource graph.act) + ?(%listen %ignore) (graph-index graph.act index.act) == :: + :: + :: ++ update |= upd=^update ^- json @@ -57,7 +59,8 @@ %- pairs :~ 'watchOnSelf'^b+watch-on-self.upd 'mentions'^b+mentions.upd - watching+a+(turn ~(tap in watching.upd) |=(r=resource s+(enjs-path:resource r))) + :+ %watching %a + (turn ~(tap in watching.upd) graph-index) == -- -- diff --git a/pkg/arvo/mar/graph/validator/link.hoon b/pkg/arvo/mar/graph/validator/link.hoon index 69087ca1cd..2daeba3b3f 100644 --- a/pkg/arvo/mar/graph/validator/link.hoon +++ b/pkg/arvo/mar/graph/validator/link.hoon @@ -5,8 +5,8 @@ ++ noun i ++ notification-kind ?+ index.p.i ~ - [@ ~] `%link - [@ @ ~] `%comment + [@ ~] `[%link 0] + [@ @ ~] `[%comment 1] == -- ++ grab diff --git a/pkg/arvo/mar/graph/validator/publish.hoon b/pkg/arvo/mar/graph/validator/publish.hoon index 7c06e56f7f..c9237b3d91 100644 --- a/pkg/arvo/mar/graph/validator/publish.hoon +++ b/pkg/arvo/mar/graph/validator/publish.hoon @@ -8,8 +8,8 @@ :: ++ notification-kind ?+ index.p.i ~ - [@ %1 @ ~] `%note - [@ %2 @ ~] `%comment + [@ %1 @ ~] `[%note 0] + [@ %2 @ ~] `[%comment 1] == -- ++ grab diff --git a/pkg/arvo/sur/hark-graph-hook.hoon b/pkg/arvo/sur/hark-graph-hook.hoon index bad5e7c9ec..ff9edd2327 100644 --- a/pkg/arvo/sur/hark-graph-hook.hoon +++ b/pkg/arvo/sur/hark-graph-hook.hoon @@ -1,10 +1,10 @@ -/- *resource, graph-store +/- *resource, graph-store, post ^? |% :: +$ action $% - [?(%listen %ignore) graph=resource] + [?(%listen %ignore) graph=resource =index:post] [%set-mentions mentions=?] [%set-watch-on-self watch-on-self=?] == @@ -13,7 +13,7 @@ $% action $: %initial - watching=(set resource) + watching=(set [resource index:post]) mentions=_& watch-on-self=_& == From 39caa5730819e7c5b0cb7017530ec861405b844f Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Tue, 10 Nov 2020 12:15:16 +1000 Subject: [PATCH 2/4] hark: update FE for per-index granularity --- pkg/interface/src/logic/api/hark.ts | 56 ++++++++++++------- pkg/interface/src/logic/lib/notification.ts | 21 +++++++ .../src/logic/reducers/hark-update.ts | 2 +- pkg/interface/src/types/hark-update.ts | 11 +++- .../views/apps/notifications/notification.tsx | 30 ++++++---- .../landscape/components/ChannelMenu.tsx | 21 ++++--- 6 files changed, 96 insertions(+), 45 deletions(-) create mode 100644 pkg/interface/src/logic/lib/notification.ts diff --git a/pkg/interface/src/logic/api/hark.ts b/pkg/interface/src/logic/api/hark.ts index b4706e80da..c9899da0bd 100644 --- a/pkg/interface/src/logic/api/hark.ts +++ b/pkg/interface/src/logic/api/hark.ts @@ -1,8 +1,9 @@ import BaseApi from "./base"; import { StoreState } from "../store/type"; import { dateToDa, decToUd } from "../lib/util"; -import {NotifIndex} from "~/types"; +import {NotifIndex, IndexedNotification} from "~/types"; import { BigInteger } from 'big-integer'; +import {getParentIndex} from "../lib/notification"; export class HarkApi extends BaseApi { private harkAction(action: any): Promise { @@ -68,30 +69,39 @@ export class HarkApi extends BaseApi { return this.harkAction({ seen: null }); } - mute(index: NotifIndex) { - if('graph' in index) { - const { graph } = index.graph; - return this.ignoreGraph(graph); + mute(notif: IndexedNotification) { + if('graph' in notif.index && 'graph' in notif.notification.contents) { + const { index } = notif; + const parentIndex = getParentIndex(index.graph, notif.notification.contents.graph) + if(!parentIndex) { + return Promise.resolve(); + } + return this.ignoreGraph(index.graph.graph, parentIndex); } - if('group' in index) { - const { group } = index.group; + if('group' in notif.index) { + const { group } = notif.index.group; return this.ignoreGroup(group); } - if('chat' in index) { - return this.ignoreChat(index.chat); + if('chat' in notif.index) { + return this.ignoreChat(notif.index.chat.chat); } return Promise.resolve(); } - unmute(index: NotifIndex) { - if('graph' in index) { - return this.listenGraph(index.graph.graph); + unmute(notif: IndexedNotification) { + if('graph' in notif.index && 'graph' in notif.notification.contents) { + const { index } = notif; + const parentIndex = getParentIndex(index.graph, notif.notification.contents.graph) + if(!parentIndex) { + return Promise.resolve(); + } + return this.listenGraph(index.graph.graph, parentIndex); } - if('group' in index) { - return this.listenGroup(index.group.group); + if('group' in notif.index) { + return this.listenGroup(notif.index.group.group); } - if('chat' in index) { - return this.listenChat(index.chat); + if('chat' in notif.index) { + return this.listenChat(notif.index.chat.chat); } return Promise.resolve(); } @@ -102,9 +112,12 @@ export class HarkApi extends BaseApi { }) } - ignoreGraph(graph: string) { + ignoreGraph(graph: string, index: string) { return this.graphHookAction({ - ignore: graph + ignore: { + graph, + index + } }) } @@ -121,9 +134,12 @@ export class HarkApi extends BaseApi { }) } - listenGraph(graph: string) { + listenGraph(graph: string, index: string) { return this.graphHookAction({ - listen: graph + listen: { + graph, + index + } }) } diff --git a/pkg/interface/src/logic/lib/notification.ts b/pkg/interface/src/logic/lib/notification.ts new file mode 100644 index 0000000000..87288d83d2 --- /dev/null +++ b/pkg/interface/src/logic/lib/notification.ts @@ -0,0 +1,21 @@ +import { GraphNotifIndex, GraphNotificationContents } from "~/types"; + +export function getParentIndex( + idx: GraphNotifIndex, + contents: GraphNotificationContents +) { + const origIndex = contents[0].index.slice(1).split("/"); + const ret = (i: string[]) => `/${i.join("/")}`; + switch (idx.description) { + case "link": + return "/"; + case "comment": + return ret(origIndex.slice(0, 1)); + case "note": + return "/"; + case "mention": + return undefined; + default: + return undefined; + } +} diff --git a/pkg/interface/src/logic/reducers/hark-update.ts b/pkg/interface/src/logic/reducers/hark-update.ts index 401555a06a..7acadd8add 100644 --- a/pkg/interface/src/logic/reducers/hark-update.ts +++ b/pkg/interface/src/logic/reducers/hark-update.ts @@ -97,7 +97,7 @@ function graphIgnore(json: any, state: HarkState) { const data = _.get(json, "ignore", false); if (data) { state.notificationsGraphConfig.watching = state.notificationsGraphConfig.watching.filter( - (n) => n !== data + ({ graph, index }) => !(graph === data.graph && index === data.index) ); } } diff --git a/pkg/interface/src/types/hark-update.ts b/pkg/interface/src/types/hark-update.ts index d549ed6232..e43da4a55d 100644 --- a/pkg/interface/src/types/hark-update.ts +++ b/pkg/interface/src/types/hark-update.ts @@ -4,7 +4,7 @@ import { GroupUpdate } from "./group-update"; import { BigIntOrderedMap } from "~/logic/lib/BigIntOrderedMap"; import { Envelope } from './chat-update'; -type GraphNotifDescription = "link" | "comment"; +type GraphNotifDescription = "link" | "comment" | "note" | "mention"; export interface GraphNotifIndex { graph: string; @@ -39,7 +39,7 @@ export type NotificationContents = | { group: GroupNotificationContents } | { chat: ChatNotificationContents }; -interface Notification { +export interface Notification { read: boolean; time: number; contents: NotificationContents; @@ -57,7 +57,12 @@ export type Notifications = BigIntOrderedMap; export interface NotificationGraphConfig { watchOnSelf: boolean; mentions: boolean; - watching: string[]; + watching: WatchedIndex[] } + +interface WatchedIndex { + graph: string; + index: string; +} export type GroupNotificationsConfig = string[]; diff --git a/pkg/interface/src/views/apps/notifications/notification.tsx b/pkg/interface/src/views/apps/notifications/notification.tsx index e15de4c3e3..9a9f243e45 100644 --- a/pkg/interface/src/views/apps/notifications/notification.tsx +++ b/pkg/interface/src/views/apps/notifications/notification.tsx @@ -11,6 +11,7 @@ import { Associations, } from "~/types"; import GlobalApi from "~/logic/api/global"; +import { getParentIndex } from "~/logic/lib/notification"; import { StatelessAsyncAction } from "~/views/components/StatelessAsyncAction"; import { GroupNotification } from "./group"; import { GraphNotification } from "./graph"; @@ -29,20 +30,29 @@ interface NotificationProps { } function getMuted( - idx: NotifIndex, + idxNotif: IndexedNotification, groups: GroupNotificationsConfig, graphs: NotificationGraphConfig, chat: string[] ) { - if ("graph" in idx) { - const { graph } = idx.graph; - return _.findIndex(graphs?.watching || [], (g) => g === graph) === -1; + const { index, notification } = idxNotif; + if ("graph" in idxNotif.index) { + const { graph } = idxNotif.index.graph; + if(!('graph' in notification.contents)) { + throw new Error(); + } + const parent = getParentIndex(index.graph, notification.contents.graph); + + return _.findIndex( + graphs?.watching || [], + (g) => g.graph === graph && g.index === parent + ) === -1; } - if ("group" in idx) { - return _.findIndex(groups || [], (g) => g === idx.group.group) === -1; + if ("group" in index) { + return _.findIndex(groups || [], (g) => g === index.group.group) === -1; } - if ("chat" in idx) { - return _.findIndex(chat || [], (c) => c === idx.chat) === -1; + if ("chat" in index) { + return _.findIndex(chat || [], (c) => c === index.chat.chat) === -1; } return false; } @@ -64,7 +74,7 @@ function NotificationWrapper(props: { }, [time, notif]); const isMuted = getMuted( - notif.index, + notif, props.groupConfig, props.graphConfig, props.chatConfig @@ -72,7 +82,7 @@ function NotificationWrapper(props: { const onChangeMute = useCallback(async () => { const func = isMuted ? "unmute" : "mute"; - return api.hark[func](notif.index); + return api.hark[func](notif); }, [notif, api, isMuted]); const changeMuteDesc = isMuted ? "Unmute" : "Mute"; diff --git a/pkg/interface/src/views/landscape/components/ChannelMenu.tsx b/pkg/interface/src/views/landscape/components/ChannelMenu.tsx index 786619d691..22f7e4a6d0 100644 --- a/pkg/interface/src/views/landscape/components/ChannelMenu.tsx +++ b/pkg/interface/src/views/landscape/components/ChannelMenu.tsx @@ -51,19 +51,18 @@ export function ChannelMenu(props: ChannelMenuProps) { const isOurs = ship.slice(1) === window.ship; const isMuted = appIsGraph(app) - ? props.graphNotificationConfig.watching.findIndex((a) => a === appPath) === - -1 + ? props.graphNotificationConfig.watching.findIndex( + (a) => a.graph === appPath && a.index === "/" + ) === -1 : props.chatNotificationConfig.findIndex((a) => a === appPath) === -1; + const onChangeMute = async () => { - const func = - association["app-name"] === "chat" - ? isMuted - ? "listenChat" - : "ignoreChat" - : isMuted - ? "listenGraph" - : "ignoreGraph"; - await api.hark[func](appPath); + if (association["app-name"] === "chat") { + const func = isMuted ? "listenChat" : "ignoreChat"; + return api.hark[func](appPath); + } + const func = isMuted ? "listenGraph" : "ignoreGraph"; + await api.hark[func](appPath, "/"); }; const onUnsubscribe = useCallback(async () => { const app = metadata.module || association["app-name"]; From 35103ab3943d08431348c277e4ae43bf2d6de94f Mon Sep 17 00:00:00 2001 From: Matilde Park Date: Tue, 10 Nov 2020 14:24:47 -0500 Subject: [PATCH 3/4] hark-graph-hook: remove ~& --- pkg/arvo/app/hark-graph-hook.hoon | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/arvo/app/hark-graph-hook.hoon b/pkg/arvo/app/hark-graph-hook.hoon index ea003cbf66..a948c979d2 100644 --- a/pkg/arvo/app/hark-graph-hook.hoon +++ b/pkg/arvo/app/hark-graph-hook.hoon @@ -221,7 +221,6 @@ name.u.notif-kind =/ parent=index:post (scag parent-lent.u.notif-kind index.post.node) - ~& parent ?. ?| =(desc %mention) (~(has in watching) [rid parent]) == From a07f55b832f4f0f98dc8fd89471bf49a536445e0 Mon Sep 17 00:00:00 2001 From: Liam Fitzgerald Date: Wed, 11 Nov 2020 10:36:32 +1000 Subject: [PATCH 4/4] hark-graph-hook: fix conflict in merge --- pkg/arvo/app/hark-graph-hook.hoon | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/pkg/arvo/app/hark-graph-hook.hoon b/pkg/arvo/app/hark-graph-hook.hoon index a948c979d2..edf87a6f86 100644 --- a/pkg/arvo/app/hark-graph-hook.hoon +++ b/pkg/arvo/app/hark-graph-hook.hoon @@ -102,14 +102,12 @@ == ++ listen |= [graph=resource =index:post] - ^- (quip card _state) - :- (give:ha ~[/updates] [%listen graph index]) + ^+ state state(watching (~(put in watching) [graph index])) :: ++ ignore |= [graph=resource =index:post] - ^- (quip card _state) - :- (give:ha ~[/updates] [%ignore graph index]) + ^+ state state(watching (~(del in watching) [graph index])) :: ++ set-mentions