Merge pull request #3908 from urbit/lf/hark-graph-indices

hark: follow individual indices
This commit is contained in:
Liam Fitzgerald 2020-11-11 10:37:19 +10:00 committed by GitHub
commit e71ba741f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 151 additions and 83 deletions

View File

@ -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])
::

View File

@ -52,6 +52,7 @@
++ index
|= i=^index
^- json
?: =(~ i) s+'/'
=/ j=^tape ""
|-
?~ i [%s (crip j)]

View File

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

View File

@ -5,8 +5,8 @@
++ noun i
++ notification-kind
?+ index.p.i ~
[@ ~] `%link
[@ @ ~] `%comment
[@ ~] `[%link 0]
[@ @ ~] `[%comment 1]
==
--
++ grab

View File

@ -8,8 +8,8 @@
::
++ notification-kind
?+ index.p.i ~
[@ %1 @ ~] `%note
[@ %2 @ ~] `%comment
[@ %1 @ ~] `[%note 0]
[@ %2 @ ~] `[%comment 1]
==
--
++ grab

View File

@ -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=_&
==

View File

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

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

View File

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

View File

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

View File

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

View File

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