mirror of
https://github.com/urbit/shrub.git
synced 2025-01-01 17:16:47 +03:00
Merge pull request #3908 from urbit/lf/hark-graph-indices
hark: follow individual indices
This commit is contained in:
commit
e71ba741f4
@ -12,7 +12,7 @@
|
||||
::
|
||||
+$ state-0
|
||||
$: %0
|
||||
watching=(set resource)
|
||||
watching=(set [resource index:post])
|
||||
mentions=_&
|
||||
watch-on-self=_&
|
||||
==
|
||||
@ -59,13 +59,13 @@
|
||||
^- (quip card _this)
|
||||
`this(state !<(state-0 old))
|
||||
::
|
||||
++ on-watch
|
||||
++ on-watch
|
||||
|= =path
|
||||
^- (quip card _this)
|
||||
=^ cards state
|
||||
?+ path (on-watch:def path)
|
||||
::
|
||||
[%updates ~]
|
||||
[%updates ~]
|
||||
:_ state
|
||||
%+ give:ha ~
|
||||
:* %initial
|
||||
@ -101,14 +101,14 @@
|
||||
%set-watch-on-self (set-watch-on-self +.action)
|
||||
==
|
||||
++ listen
|
||||
|= graph=resource
|
||||
|= [graph=resource =index:post]
|
||||
^+ state
|
||||
state(watching (~(put in watching) graph))
|
||||
state(watching (~(put in watching) [graph index]))
|
||||
::
|
||||
++ ignore
|
||||
|= graph=resource
|
||||
|= [graph=resource =index:post]
|
||||
^+ state
|
||||
state(watching (~(del in watching) graph))
|
||||
state(watching (~(del in watching) [graph index]))
|
||||
::
|
||||
++ set-mentions
|
||||
|= ment=?
|
||||
@ -141,10 +141,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
|
||||
@ -153,7 +161,7 @@
|
||||
(need (peek-metadata:met %graph group resource.q.update))
|
||||
=* rid resource.q.update
|
||||
=+ %+ scry:ha
|
||||
,mark=(unit mark)
|
||||
,mark=(unit mark)
|
||||
/gx/graph-store/graph-mark/(scot %p entity.rid)/[name.rid]/noun
|
||||
=+ %+ scry:ha
|
||||
,=tube:clay
|
||||
@ -162,7 +170,7 @@
|
||||
~(tap by nodes.q.update)
|
||||
=| cards=(list card)
|
||||
|^
|
||||
?~ nodes
|
||||
?~ nodes
|
||||
[cards state]
|
||||
=* index p.i.nodes
|
||||
=* node q.i.nodes
|
||||
@ -187,7 +195,7 @@
|
||||
=^ new-cards state
|
||||
(check-node node.i.children tube)
|
||||
%_ $
|
||||
cards (weld cards new-cards)
|
||||
cards (weld cards new-cards)
|
||||
children t.children
|
||||
==
|
||||
::
|
||||
@ -201,15 +209,18 @@
|
||||
(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
|
||||
%mention
|
||||
name.u.notif-kind
|
||||
=/ parent=index:post
|
||||
(scag parent-lent.u.notif-kind index.post.node)
|
||||
?. ?| =(desc %mention)
|
||||
(~(has in watching) rid)
|
||||
(~(has in watching) [rid parent])
|
||||
==
|
||||
[child-cards state]
|
||||
=/ notif-index=index:store
|
||||
@ -236,11 +247,11 @@
|
||||
^- (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]
|
||||
^- card
|
||||
^- card
|
||||
=- [%pass / %agent [our.bowl %hark-store] %poke -]
|
||||
hark-action+!>([%add index notification])
|
||||
::
|
||||
|
@ -52,6 +52,7 @@
|
||||
++ index
|
||||
|= i=^index
|
||||
^- json
|
||||
?: =(~ i) s+'/'
|
||||
=/ j=^tape ""
|
||||
|-
|
||||
?~ i [%s (crip j)]
|
||||
|
@ -1,4 +1,4 @@
|
||||
/- sur=hark-graph-hook
|
||||
/- sur=hark-graph-hook, post
|
||||
/+ graph-store, resource
|
||||
^?
|
||||
=< [. sur]
|
||||
@ -7,20 +7,21 @@
|
||||
++ dejs
|
||||
=, 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
|
||||
==
|
||||
@ -29,23 +30,26 @@
|
||||
++ enjs
|
||||
=, 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
|
||||
|= act=^action
|
||||
^- json
|
||||
%+ frond -.act
|
||||
?- -.act
|
||||
?- -.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
|
||||
@ -55,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)
|
||||
==
|
||||
--
|
||||
--
|
||||
|
@ -5,8 +5,8 @@
|
||||
++ noun i
|
||||
++ notification-kind
|
||||
?+ index.p.i ~
|
||||
[@ ~] `%link
|
||||
[@ @ ~] `%comment
|
||||
[@ ~] `[%link 0]
|
||||
[@ @ ~] `[%comment 1]
|
||||
==
|
||||
--
|
||||
++ grab
|
||||
|
@ -8,8 +8,8 @@
|
||||
::
|
||||
++ notification-kind
|
||||
?+ index.p.i ~
|
||||
[@ %1 @ ~] `%note
|
||||
[@ %2 @ ~] `%comment
|
||||
[@ %1 @ ~] `[%note 0]
|
||||
[@ %2 @ ~] `[%comment 1]
|
||||
==
|
||||
--
|
||||
++ grab
|
||||
|
@ -1,9 +1,9 @@
|
||||
/- *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=?]
|
||||
==
|
||||
@ -12,7 +12,7 @@
|
||||
$%
|
||||
action
|
||||
$: %initial
|
||||
watching=(set resource)
|
||||
watching=(set [resource index:post])
|
||||
mentions=_&
|
||||
watch-on-self=_&
|
||||
==
|
||||
|
@ -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<StoreState> {
|
||||
private harkAction(action: any): Promise<any> {
|
||||
@ -68,30 +69,39 @@ export class HarkApi extends BaseApi<StoreState> {
|
||||
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<StoreState> {
|
||||
})
|
||||
}
|
||||
|
||||
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<StoreState> {
|
||||
})
|
||||
}
|
||||
|
||||
listenGraph(graph: string) {
|
||||
listenGraph(graph: string, index: string) {
|
||||
return this.graphHookAction({
|
||||
listen: graph
|
||||
listen: {
|
||||
graph,
|
||||
index
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
21
pkg/interface/src/logic/lib/notification.ts
Normal file
21
pkg/interface/src/logic/lib/notification.ts
Normal file
@ -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;
|
||||
}
|
||||
}
|
@ -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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -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<Timebox>;
|
||||
export interface NotificationGraphConfig {
|
||||
watchOnSelf: boolean;
|
||||
mentions: boolean;
|
||||
watching: string[];
|
||||
watching: WatchedIndex[]
|
||||
}
|
||||
|
||||
|
||||
interface WatchedIndex {
|
||||
graph: string;
|
||||
index: string;
|
||||
}
|
||||
export type GroupNotificationsConfig = string[];
|
||||
|
@ -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";
|
||||
|
@ -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"];
|
||||
|
Loading…
Reference in New Issue
Block a user