Merge remote-tracking branch 'origin/master' into release/next-sys

This commit is contained in:
Philip Monk 2020-12-18 12:46:13 -08:00
commit bb29b7c749
No known key found for this signature in database
GPG Key ID: B66E1F02604E44EC
23 changed files with 9740 additions and 2426 deletions

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9e169f1822997ece960527045b17790caf1490a79fd7bec86b0fb4c1eaf2cfc7
size 8319616
oid sha256:55ccddf886ad063cdd0e3e3f3cc5c49abdae1feef1980ed6e3c98bb17e822c6e
size 8317553

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5,7 +5,7 @@
/- glob
/+ default-agent, verb, dbug
|%
++ hash 0v5.bo337.25di9.mg5d5.i9vun.5qaqe
++ hash 0v7.p2egb.1l8lk.11asn.n1bkb.71bkt
+$ state-0 [%0 hash=@uv glob=(unit (each glob:glob tid=@ta))]
+$ all-states
$% state-0

View File

@ -1,7 +1,7 @@
:: hark-graph-hook: notifications for graph-store [landscape]
::
/- store=hark-store, post, group-store, metadata-store, hook=hark-graph-hook
/+ resource, metadata, default-agent, dbug, graph-store, graph, grouplib=group
/- post, group-store, metadata-store, hook=hark-graph-hook, store=hark-store
/+ resource, metadata, default-agent, dbug, graph-store, graph, grouplib=group, store=hark-store
::
::
~% %hark-graph-hook-top ..part ~
@ -19,31 +19,27 @@
==
::
+$ notif-kind
[name=@t parent-lent=@ud mode=?(%each %count) watch=?]
[name=@t parent-lent=@ud mode=?(%each %count %none) watch=?]
::
++ scry
|* [[our=@p now=@da] =mold p=path]
?> ?=(^ p)
?> ?=(^ t.p)
.^(mold i.p (scot %p our) i.t.p (scot %da now) t.t.p)
::
++ scry-conversion
|= [[our=@p now=@da] desk=term =mark]
~+
%^ scry [our now]
tube:clay
/cc/[desk]/[mark]/notification-kind
::
--
::
=| state-0
=* state -
::
=>
|_ =bowl:gall
::
++ scry
|* [=mold p=path]
?> ?=(^ p)
?> ?=(^ t.p)
.^(mold i.p (scot %p our.bowl) i.t.p (scot %da now.bowl) t.t.p)
::
++ give
|= [paths=(list path) =update:hook]
^- (list card)
[%give %fact paths hark-graph-hook-update+!>(update)]~
::
++ watch-graph
^- card
[%pass /graph %agent [our.bowl %graph-store] %watch /updates]
--
=<
%- agent:dbug
^- agent:gall
~% %hark-graph-hook-agent ..card ~
@ -162,8 +158,38 @@
(graph-update !<(update:graph-store q.cage.sign))
[cards this]
==
::
++ graph-update
|= =update:graph-store
^- (quip card _state)
?+ -.q.update `state
%add-graph (add-graph resource.q.update)
::
?(%remove-graph %archive-graph)
(remove-graph resource.q.update)
::
%add-nodes
=* rid resource.q.update
(check-nodes ~(val by nodes.q.update) rid)
==
::
++ remove-graph
|= rid=resource
=/ unwatched
%- ~(gas in *_watching)
%+ skim ~(tap in watching)
|= [r=resource idx=index:graph-store]
=(r rid)
:_ state(watching (~(dif in watching) unwatched))
^- (list card)
:- (poke-hark:ha %remove-graph rid)
%- zing
%+ turn ~(tap in unwatched)
|= [r=resource =index:graph-store]
(give:ha ~[/updates] %ignore r index)
::
++ add-graph
|= [rid=resource =graph:graph-store]
|= rid=resource
^- (quip card _state)
=/ group-rid=(unit resource)
(group-from-app-resource:met %graph rid)
@ -176,146 +202,29 @@
|(is-hidden &(watch-on-self =(our.bowl entity.rid)))
?. should-watch
`state
:- (give:ha ~[/updates] %listen [rid ~])
state(watching (~(put in watching) [rid ~]))
=/ graph=graph:graph-store :: graph in subscription is bunted
(get-graph-mop:gra rid)
=/ node=(unit node:graph-store)
(bind (peek:orm:graph-store graph) |=([@ =node:graph-store] node))
=^ cards state
(check-nodes (drop node) rid)
:_ state(watching (~(put in watching) [rid ~]))
(weld cards (give:ha ~[/updates] %listen [rid ~]))
::
++ graph-update
|= =update:graph-store
^- (quip card _state)
?: ?=(%add-graph -.q.update)
(add-graph resource.q.update graph.q.update)
?. ?=(%add-nodes -.q.update)
[~ state]
=* rid resource.q.update
(check-nodes ~(tap by nodes.q.update) rid)
::
++ check-nodes
|= $: nodes=(list [p=index:graph-store q=node:graph-store])
|= $: nodes=(list node:graph-store)
rid=resource
==
=/ group=resource
(need (group-from-app-resource:met %graph rid))
=/ =metadata:metadata-store
(need (peek-metadata:met %graph group rid))
=+ %+ scry:ha
,mark=(unit mark)
/gx/graph-store/graph-mark/(scot %p entity.rid)/[name.rid]/noun
=+ %+ scry:ha
,=tube:clay
/cc/[q.byk.bowl]/[(fall mark %graph-validator-link)]/notification-kind
=| cards=(list card)
|^
?~ nodes
[cards state]
=* index p.i.nodes
=* node q.i.nodes
=^ node-cards state
(check-node node tube)
%_ $
nodes t.nodes
cards (weld node-cards cards)
==
::
++ check-node-children
|= [=node:graph-store =tube:clay]
^- (quip card _state)
?: ?=(%empty -.children.node)
[~ state]
=/ children=(list [=atom =node:graph-store])
(tap:orm:graph-store p.children.node)
=| cards=(list card)
|- ^- (quip card _state)
?~ children
[cards state]
=^ new-cards state
(check-node node.i.children tube)
%_ $
cards (weld cards new-cards)
children t.children
==
::
++ check-node
|= [=node:graph-store =tube:clay]
^- (quip card _state)
=^ child-cards state
(check-node-children node tube)
=+ !< notif-kind=(unit notif-kind)
(tube !>([0 post.node]))
?~ notif-kind
[child-cards state]
=/ desc=@t
?: (is-mention contents.post.node)
%mention
name.u.notif-kind
=/ parent=index:post
(scag parent-lent.u.notif-kind index.post.node)
=/ notif-index=index:store
[%graph group rid module.metadata desc parent]
?: =(our.bowl author.post.node)
=^ self-cards state
(self-post node notif-index [mode watch]:u.notif-kind)
:_ state
(weld child-cards self-cards)
:_ state
%+ weld child-cards
%+ weld
%^ update-unread-count
mode.u.notif-kind notif-index
[time-sent index]:post.node
?. ?| =(desc %mention)
(~(has in watching) [rid parent])
==
~
=/ =contents:store
[%graph (limo post.node ~)]
~[(add-unread notif-index [time-sent.post.node %.n contents])]
::
++ is-mention
|= contents=(list content:post)
^- ?
?. mentions %.n
?~ contents %.n
?. ?=(%mention -.i.contents)
$(contents t.contents)
?: =(our.bowl ship.i.contents)
%.y
$(contents t.contents)
::
++ self-post
|= $: =node:graph-store
=index:store
mode=?(%count %each)
watch=?
==
^- (quip card _state)
=| cards=(list card)
=? cards ?=(%count mode)
:_ cards
(poke-hark %read-count index)
?. &(watch watch-on-self)
[cards state]
:- cards
state(watching (~(put in watching) [rid index.post.node]))
::
++ poke-hark
|= =action:store
^- card
=- [%pass / %agent [our.bowl %hark-store] %poke -]
hark-action+!>(action)
::
++ update-unread-count
|= [mode=?(%count %each %none) =index:store time=@da ref=index:graph-store]
?- mode
%count ~[(poke-hark %unread-count index time)]
%each ~[(poke-hark %unread-each index ref time)]
%none ~
==
::
++ add-unread
|= [=index:store =notification:store]
(poke-hark %add-note index notification)
::
--
=/ group=(unit resource)
(group-from-app-resource:met %graph rid)
?~ group
~& no-group+rid
`state
=/ metadata=(unit metadata:metadata-store)
(peek-metadata:met %graph u.group rid)
?~ metadata `state
abet:check:(abed:handle-update:ha rid nodes u.group module.u.metadata)
--
::
++ on-peek on-peek:def
@ -334,4 +243,160 @@
==
++ on-fail on-fail:def
--
::
|_ =bowl:gall
::
::
++ give
|= [paths=(list path) =update:hook]
^- (list card)
[%give %fact paths hark-graph-hook-update+!>(update)]~
::
++ watch-graph
^- card
[%pass /graph %agent [our.bowl %graph-store] %watch /updates]
::
++ poke-hark
|= =action:store
^- card
=- [%pass / %agent [our.bowl %hark-store] %poke -]
hark-action+!>(action)
::
++ is-mention
|= contents=(list content:post)
^- ?
?. mentions %.n
?~ contents %.n
?. ?=(%mention -.i.contents)
$(contents t.contents)
?: =(our.bowl ship.i.contents)
%.y
$(contents t.contents)
::
++ handle-update
|_ $: rid=resource :: input
updates=(list node:graph-store)
group=resource
module=term
hark-pokes=(list action:store) :: output
new-watches=(list index:graph-store)
==
++ update-core .
::
++ abed
|= [r=resource upds=(list node:graph-store) grp=resource mod=term]
update-core(rid r, updates upds, group grp, module mod)
::
++ get-conversion
^- tube:clay
=+ %^ scry [our now]:bowl
,mark=(unit mark)
/gx/graph-store/graph-mark/(scot %p entity.rid)/[name.rid]/noun
?~ mark
|=(v=vase !>(~))
(scry-conversion [our now]:bowl q.byk.bowl u.mark)
::
++ abet
^- (quip card _state)
:_ state(watching (~(uni in watching) (silt (turn new-watches (lead rid)))))
^- (list card)
%+ welp (turn (flop hark-pokes) poke-hark)
%- zing
%+ turn (flop new-watches)
|=(=index:graph-store (give ~[/updates] [%listen rid index]))
::
++ hark
|= =action:store
^+ update-core
update-core(hark-pokes [action hark-pokes])
::
++ new-watch
|= =index:graph-store
update-core(new-watches [index new-watches])
::
++ check
|- ^+ update-core
?~ updates
update-core
=/ core=_update-core
(check-node i.updates)
=. updates.core t.updates
$(update-core core)
::
++ check-node-children
|= =node:graph-store
^+ update-core
?: ?=(%empty -.children.node)
update-core
=/ children=(list [=atom =node:graph-store])
(tap:orm:graph-store p.children.node)
|- ^+ update-core
?~ children
update-core
=. update-core (check-node node.i.children)
$(children t.children)
::
++ check-node
|= =node:graph-store
^+ update-core
=. update-core (check-node-children node)
=+ !< notif-kind=(unit notif-kind)
(get-conversion !>([0 post.node]))
?~ notif-kind
update-core
=/ desc=@t
?: (is-mention contents.post.node)
%mention
name.u.notif-kind
=* not-kind u.notif-kind
=/ parent=index:post
(scag parent-lent.not-kind index.post.node)
=/ notif-index=index:store
[%graph group rid module desc parent]
?: =(our.bowl author.post.node)
(self-post node notif-index [mode watch]:not-kind)
=. update-core
(update-unread-count not-kind notif-index [time-sent index]:post.node)
=? update-core
?| =(desc %mention)
(~(has in watching) [rid parent])
==
=/ =contents:store
[%graph (limo post.node ~)]
(add-unread notif-index [time-sent.post.node %.n contents])
update-core
::
++ update-unread-count
|= [=notif-kind =index:store time=@da ref=index:graph-store]
=/ =stats-index:store
(to-stats-index:store index)
?- mode.notif-kind
%count (hark %unread-count stats-index time)
%each (hark %unread-each stats-index ref time)
%none update-core
==
::
++ self-post
|= $: =node:graph-store
=index:store
mode=?(%count %each %none)
watch=?
==
^+ update-core
?: ?=(%none mode) update-core
=/ =stats-index:store
(to-stats-index:store index)
=. update-core
(hark %seen-index time-sent.post.node stats-index)
=? update-core ?=(%count mode)
(hark %read-count stats-index)
=? update-core &(watch watch-on-self)
(new-watch index.post.node)
update-core
::
++ add-unread
|= [=index:store =notification:store]
(hark %add-note index notification)
::
--
--

View File

@ -10,7 +10,7 @@
:: Usefull for non-linear, low-volume applications, i.e. blogs,
:: collections
::
/- post, group-store, metadata-store
/- post, group-store, metadata-store, store=hark-store
/+ resource, metadata, default-agent, dbug, graph-store, graphl=graph, verb, store=hark-store
::
::
@ -19,29 +19,31 @@
+$ card card:agent:gall
+$ versioned-state
$% state:state-zero:store
state-1
state:state-one:store
state-2
==
+$ unread-stats
[indices=(set index:graph-store) last=@da]
::
+$ state-1
$: %1
unreads-each=(jug index:store index:graph-store)
unreads-count=(map index:store @ud)
last-seen=(map index:store @da)
+$ state-2
$: %2
unreads-each=(jug stats-index:store index:graph-store)
unreads-count=(map stats-index:store @ud)
last-seen=(map stats-index:store @da)
=notifications:store
archive=notifications:store
current-timebox=@da
dnd=_|
==
::
+$ inflated-state
$: state-1
$: state-2
cache
==
:: $cache: useful to have precalculated, but can be derived from state
:: albeit expensively
+$ cache
$: by-index=(jug index:store @da)
$: by-index=(jug stats-index:store @da)
~
==
::
@ -76,15 +78,30 @@
=| cards=(list card)
|^
?- -.old
%2
:- cards
this(-.state old, +.state (inflate-cache:ha old))
::
%1
[cards this(+.state (inflate-cache:ha old), -.state old)]
%_ $
::
old
%* . *state-2
unreads-each ((convert-unread ,(set index:graph-store)) uni-by unreads-each.old)
unreads-count ((convert-unread ,@ud) add unreads-count.old)
last-seen ((convert-unread ,@da) max last-seen.old)
notifications notifications.old
archive archive.old
current-timebox current-timebox.old
dnd dnd.old
==
==
::
%0
%_ $
::
old
%* . *state-1
%* . *state:state-one:store
notifications (convert-notifications-1 notifications.old)
archive (convert-notifications-1 archive.old)
current-timebox current-timebox.old
@ -92,6 +109,28 @@
==
==
==
:: discard publish edits
++ uni-by
|= [a=(set index:graph-store) b=(set index:graph-store)]
=/ merged
(~(uni in a) b)
%- ~(gas in *(set index:graph-store))
%+ skip ~(tap in merged)
|=(=index:graph-store &(=((lent index) 3) !=(-:(flop index) 1)))
::
++ convert-unread
|* value=mold
|= [combine=$-([value value] value) unreads=(map index:store value)]
^- (map stats-index:store value)
%+ roll
~(tap in unreads)
|= [[=index:store val=value] out=(map stats-index:store value)]
=/ old=value
(~(gut by unreads) index (combine))
=/ =stats-index:store
(to-stats-index:store index)
(~(put by out) stats-index (combine old val))
::
++ convert-notifications-1
|= old=notifications:state-zero:store
%+ gas:orm *notifications:store
@ -159,48 +198,35 @@
^- update:store
:- %more
^- (list update:store)
:+ give-unreads
[%set-dnd dnd]
%+ weld
%+ turn
(tap-nonempty:ha archive)
(timebox-update &)
%+ turn
(tap-nonempty:ha notifications)
(timebox-update |)
:- give-unreads
[%set-dnd dnd]~
::
++ give-since-unreads
^- (list [index:store index-stats:store])
^- (list [stats-index:store stats:store])
%+ turn
~(tap by unreads-count)
|= [=index:store count=@ud]
?> ?=(%graph -.index)
:* index
~(wyt in (~(gut by by-index) index ~))
|= [=stats-index:store count=@ud]
?> ?=(%graph -.stats-index)
:* stats-index
~(wyt in (~(gut by by-index) stats-index ~))
[%count count]
(~(gut by last-seen) index *time)
(~(gut by last-seen) stats-index *time)
==
++ give-each-unreads
^- (list [index:store index-stats:store])
^- (list [stats-index:store stats:store])
%+ turn
~(tap by unreads-each)
|= [=index:store indices=(set index:graph-store)]
:* index
~(wyt in (~(gut by by-index) index ~))
|= [=stats-index:store indices=(set index:graph-store)]
:* stats-index
~(wyt in (~(gut by by-index) stats-index ~))
[%each indices]
(~(gut by last-seen) index *time)
(~(gut by last-seen) stats-index *time)
==
::
++ give-unreads
^- update:store
:- %unreads
(weld give-each-unreads give-since-unreads)
::
++ timebox-update
|= archived=?
|= [time=@da =timebox:store]
^- update:store
[%timebox time archived ~(tap by timebox)]
--
::
++ on-peek
@ -238,209 +264,14 @@
=^ cards state
?+ mark (on-poke:def mark vase)
%hark-action (hark-action !<(action:store vase))
%noun ~& +.state [~ state]
%noun ~& +.state [~ state]
==
[cards this]
::
++ hark-action
|= =action:store
^- (quip card _state)
|^
?- -.action
%add-note (add-note +.action)
%archive (do-archive +.action)
::
%read-each (read-each +.action)
%unread-each (unread-each +.action)
::
%read-count (read-count +.action)
%unread-count (unread-count +.action)
::
%read-note (read-note +.action)
%unread-note (unread-note +.action)
::
%read-all read-all
::
%set-dnd (set-dnd +.action)
%seen seen
==
::
++ add-note
|= [=index:store =notification:store]
^- (quip card _state)
=/ =timebox:store
(gut-orm:ha notifications current-timebox)
=/ existing-notif
(~(get by timebox) index)
=/ new=notification:store
?~ existing-notif
notification
(merge-notification:ha u.existing-notif notification)
=/ new-read=?
?~ existing-notif
%.y
read.u.existing-notif
=. read.new %.n
=/ new-timebox=timebox:store
(~(put by timebox) index new)
:- (give:ha [/updates]~ %added current-timebox index new)
%_ state
+ ?.(new-read +.state (upd-unreads:ha index current-timebox %.n))
notifications (put:orm notifications current-timebox new-timebox)
==
::
++ do-archive
|= [time=@da =index:store]
^- (quip card _state)
=/ =timebox:store
(gut-orm:ha notifications time)
=/ =notification:store
(~(got by timebox) index)
=/ new-timebox=timebox:store
(~(del by timebox) index)
:- (give:ha [/updates]~ %archive time index)
%_ state
+ ?.(read.notification (upd-unreads:ha index time %.y) +.state)
::
notifications
(put:orm notifications time new-timebox)
::
archive
%^ jub-orm:ha archive time
|= archive-box=timebox:store
^- timebox:store
(~(put by archive-box) index notification(read %.y))
==
::
++ unread-each
|= [=index:store unread=index:graph-store time=@da]
:- (give:ha ~[/updates] %unread-each index unread time)
%_ state
unreads-each
%+ jub index
|= indices=(set index:graph-store)
(~(put in indices) unread)
::
last-seen
(~(put by last-seen) index time)
==
::
++ jub
|= [=index:store f=$-((set index:graph-store) (set index:graph-store))]
^- (jug index:store index:graph-store)
=/ val=(set index:graph-store)
(~(gut by unreads-each) index ~)
(~(put by unreads-each) index (f val))
::
++ read-each
|= [=index:store ref=index:graph-store]
=/ to-dismiss=(list @da)
%+ skim
~(tap in (~(get ju by-index) index))
|= time=@da
=/ =timebox:store
(gut-orm notifications time)
=/ not=(unit notification:store)
(~(get by timebox) index)
?~ not %.n
?> ?=(%graph -.contents.u.not)
(lien list.contents.u.not |=(p=post:post =(index.p ref)))
=| cards=(list card)
|-
?^ to-dismiss
=^ crds state
(read-note i.to-dismiss index)
$(cards (weld cards crds), to-dismiss t.to-dismiss)
:- (weld cards (give:ha ~[/updates] %read-each index ref))
%_ state
::
unreads-each
%+ jub index
|= indices=(set index:graph-store)
(~(del in indices) ref)
==
::
++ read-note
|= [time=@da =index:store]
^- (quip card _state)
:- (give:ha [/updates]~ %read-note time index)
%_ state
+ (upd-unreads:ha index time %.y)
notifications (change-read-status:ha time index %.y)
==
::
++ unread-note
|= [time=@da =index:store]
^- (quip card _state)
:- (give:ha [/updates]~ %unread-note time index)
%_ state
+ (upd-unreads:ha index time %.n)
notifications (change-read-status:ha time index %.n)
==
::
++ read-count
|= =index:store
^- (quip card _state)
=^ cards state
(read-index index)
:- %+ weld cards
(give:ha [/updates]~ %read-count index)
%_ state
unreads-count (~(put by unreads-count) index 0)
==
::
++ read-boxes
|= [boxes=(set @da) =index:store]
^- (quip card _state)
=/ boxes=(list @da)
~(tap in boxes)
=| crds=(list card)
|-
?~ boxes [crds state]
=* box i.boxes
=^ cards state
(read-note box index)
$(boxes t.boxes, crds (welp crds cards))
::
++ read-index
|= =index:store
^- (quip card _state)
=/ boxes=(set @da)
(~(get ju by-index) index)
=^ cards state
(read-boxes boxes index)
:_ state
%+ welp cards
(give:ha ~[/updates] %read-index index)
::
++ read-all
^- (quip card _state)
`state
::
++ unread-count
|= [=index:store time=@da]
^- (quip card _state)
:- (give:ha [/updates]~ %unread-count index time)
=/ curr=@ud
(~(gut by unreads-count) index 0)
%_ state
last-seen (~(put by last-seen) index time)
unreads-count (~(put by unreads-count) index +(curr))
==
::
++ seen
^- (quip card _state)
:_ state(current-timebox now.bowl)
:~ cancel-autoseen:ha
autoseen-timer:ha
==
::
++ set-dnd
|= d=?
^- (quip card _state)
:_ state(dnd d)
(give:ha [/updates]~ %set-dnd d)
--
abet:translate:(abed:poke-engine:ha action)
--
::
++ on-agent on-agent:def
@ -459,35 +290,291 @@
--
|_ =bowl:gall
+* met ~(. metadata bowl)
++ poke-engine
|_ [in=action:store out=(list update:store) cards=(list card)]
++ poke-core .
::
++ abed
|= =action:store poke-core(in action)
::
++ abet
^- (quip card _state)
:_ state
%+ snoc (flop cards)
[%give %fact ~[/updates] %hark-update !>([%more (flop out)])]
::
++ give
|= =update:store poke-core(out [update out])
::
++ emit
|= =card poke-core(cards [card cards])
::
++ translate
^+ poke-core
?+ -.in poke-core
::
%add-note (add-note +.in)
%archive (do-archive +.in)
::
%unread-count (unread-count +.in)
%read-count (read-count +.in)
::
%read-each (read-each +.in)
%unread-each (unread-each +.in)
::
%read-note (read-note +.in)
%unread-note (unread-note +.in)
::
%seen-index (seen-index +.in)
%remove-graph (remove-graph +.in)
%set-dnd (set-dnd +.in)
%seen seen
==
::
:: +| %note
::
:: notification tracking
++ upd-cache
|= [read=? time=@da =index:store]
poke-core(+.state (^upd-cache read time index))
::
++ put-notifs
|= [time=@da =timebox:store]
poke-core(notifications (put:orm notifications time timebox))
::
++ add-note
|= [=index:store =notification:store]
^+ poke-core
=/ =timebox:store
(gut-orm notifications current-timebox)
=/ existing-notif
(~(get by timebox) index)
=/ new=notification:store
(merge-notification existing-notif notification)
=/ new-read=?
?~ existing-notif %.y
read.u.existing-notif
=/ new-timebox=timebox:store
(~(put by timebox) index new)
=. poke-core (put-notifs current-timebox new-timebox)
=? poke-core new-read
(upd-cache %.n current-timebox index)
(give %added current-timebox index new)
::
++ do-archive
|= [time=@da =index:store]
^+ poke-core
=/ =timebox:store
(gut-orm notifications time)
=/ =notification:store
(~(got by timebox) index)
=/ new-timebox=timebox:store
(~(del by timebox) index)
=? poke-core !read.notification
(upd-cache %.y time index)
=. poke-core
(put-notifs time new-timebox)
=. archive
%^ jub-orm archive time
|= archive-box=timebox:store
(~(put by archive-box) index notification(read %.y))
(give %archive time index)
::
++ change-read-status
|= [time=@da =index:store read=?]
=. poke-core (upd-cache read time index)
%_ poke-core
notifications
%^ jub-orm notifications time
|= =timebox:store
%+ ~(jab by timebox) index
|= n=notification:store
?>(!=(read read.n) n(read read))
==
::
++ read-note
|= [time=@da =index:store]
%. [%read-note time index]
give:(change-read-status time index %.y)
::
++ unread-note
|= [time=@da =index:store]
%. [%unread-note time index]
give:(change-read-status time index %.n)
::
:: +| %each
::
:: each unread tracking
::
++ unread-each
|= [=stats-index:store unread=index:graph-store time=@da]
=. poke-core (seen-index time stats-index)
%+ jub-unreads-each:(give %unread-each stats-index unread time)
stats-index
|= indices=(set index:graph-store)
(~(put ^in indices) unread)
::
++ read-index-each
|= [=stats-index:store ref=index:graph-store]
%+ read-index stats-index
%+ skim
~(tap ^in (~(get ju by-index) stats-index))
|= time=@da
=/ =timebox:store
(gut-orm notifications time)
%+ roll
~(tap ^in timebox)
|= [[=index:store not=notification:store] out=?]
?: out out
?. (stats-index-is-index:store stats-index index) out
?. ?=(%graph -.index) out
?. ?=(%graph -.contents.not) out
(lien list.contents.not |=(p=post:post =(index.p ref)))
::
++ read-each
|= [=stats-index:store ref=index:graph-store]
=. poke-core (read-index-each stats-index ref)
%+ jub-unreads-each:(give %read-each stats-index ref)
stats-index
|= indices=(set index:graph-store)
(~(del ^in indices) ref)
::
++ jub-unreads-each
|= $: =stats-index:store
f=$-((set index:graph-store) (set index:graph-store))
==
poke-core(unreads-each (jub stats-index f))
::
++ unread-count
|= [=stats-index:store time=@da]
=/ new-count
+((~(gut by unreads-count) stats-index 0))
=. unreads-count
(~(put by unreads-count) stats-index new-count)
(seen-index:(give %unread-count stats-index time) time stats-index)
::
++ read-count
|= =stats-index:store
=. unreads-count (~(put by unreads-count) stats-index 0)
=/ times=(list @da)
~(tap ^in (~(get ju by-index) stats-index))
(give:(read-index stats-index times) %read-count stats-index)
::
++ read-index
|= [=stats-index:store times=(list @da)]
|-
?~ times poke-core
=/ core
(read-stats-index i.times stats-index)
$(poke-core core, times t.times)
::
++ read-stats-index
|= [time=@da =stats-index:store]
=/ keys
~(tap ^in ~(key by (gut-orm notifications time)))
|- ^+ poke-core
?~ keys
poke-core
?. (stats-index-is-index:store stats-index i.keys)
$(keys t.keys)
=/ core
(read-note time i.keys)
$(poke-core core, keys t.keys)
::
++ seen-index
|= [time=@da =stats-index:store]
=/ new-time=@da
(max time (~(gut by last-seen) stats-index 0))
=. last-seen
(~(put by last-seen) stats-index new-time)
(give %seen-index new-time stats-index)
::
++ remove-graph
|= rid=resource
|^
=/ indices get-stats-indices
=. poke-core
(give %remove-graph rid)
=. poke-core
(remove-notifications indices)
=. unreads-count
((dif-map-by-key ,@ud) unreads-count indices)
=. unreads-each
%+ (dif-map-by-key ,(set index:graph-store))
unreads-each indices
=. last-seen
((dif-map-by-key ,@da) last-seen indices)
=. by-index
((dif-map-by-key ,(set @da)) by-index indices)
poke-core
::
++ get-stats-indices
%- ~(gas ^in *(set stats-index:store))
%+ skim
;: weld
~(tap ^in ~(key by unreads-count))
~(tap ^in ~(key by last-seen))
~(tap ^in ~(key by unreads-each))
~(tap ^in ~(key by by-index))
==
|= =stats-index:store
?. ?=(%graph -.stats-index) %.n
=(graph.stats-index rid)
::
++ dif-map-by-key
|* value=mold
|= [=(map stats-index:store value) =(set stats-index:store)]
=/ to-remove ~(tap ^in set)
|-
?~ to-remove map
=. map
(~(del by map) i.to-remove)
$(to-remove t.to-remove)
::
++ remove-notifications
|= =(set stats-index:store)
^+ poke-core
=/ indices
~(tap ^in set)
|-
?~ indices poke-core
=/ times=(list @da)
~(tap ^in (~(get ju by-index) i.indices))
=. poke-core
(read-index i.indices times)
$(indices t.indices)
--
::
++ seen
=> (emit cancel-autoseen)
=> (emit autoseen-timer)
poke-core(current-timebox now.bowl)
::
++ set-dnd
|= d=?
(give:poke-core(dnd d) %set-dnd d)
--
::
++ merge-notification
|= [existing=notification:store new=notification:store]
|= [existing=(unit notification:store) new=notification:store]
^- notification:store
?- -.contents.existing
?~ existing new
?- -.contents.u.existing
::
%graph
?> ?=(%graph -.contents.new)
existing(read %.n, list.contents (weld list.contents.existing list.contents.new))
u.existing(read %.n, list.contents (weld list.contents.u.existing list.contents.new))
::
%group
?> ?=(%group -.contents.new)
existing(read %.n, list.contents (weld list.contents.existing list.contents.new))
u.existing(read %.n, list.contents (weld list.contents.u.existing list.contents.new))
==
::
++ change-read-status
|= [time=@da =index:store read=?]
^+ notifications
%^ jub-orm notifications time
|= =timebox:store
%+ ~(jab by timebox) index
|= =notification:store
?> !=(read read.notification)
notification(read read)
:: +key-orm: +key:by for ordered maps
++ key-orm
|= =notifications:store
^- (list @da)
(turn (tap:orm notifications) |=([key=@da =timebox:store] key))
(turn (tap:orm notifications) |=([@da *] +<-))
:: +jub-orm: combo +jab/+gut for ordered maps
:: TODO: move to zuse.hoon
++ jub-orm
@ -496,6 +583,12 @@
=/ =timebox:store
(fun (gut-orm notifications time))
(put:orm notifications time timebox)
++ jub
|= [=stats-index:store f=$-((set index:graph-store) (set index:graph-store))]
^- (jug stats-index:store index:graph-store)
=/ val=(set index:graph-store)
(~(gut by unreads-each) stats-index ~)
(~(put by unreads-each) stats-index (f val))
:: +gut-orm: +gut:by for ordered maps
:: TODO: move to zuse.hoon
++ gut-orm
@ -523,47 +616,32 @@
^- (list card)
[%give %fact paths [%hark-update !>(update)]]~
::
++ upd-unreads
|= [=index:store time=@da read=?]
^+ +.state
%_ +.state
::
by-index
%. [index time]
?: read
~(del ju by-index)
~(put ju by-index)
==
::
++ group-for-index
|= =index:store
^- (unit resource)
?. ?=(%graph -.index)
~
`group.index
::
++ give-dirtied-unreads
|= [=index:store =update:store]
^- (list card)
=/ group
(group-for-index index)
?~ group ~
(give ~[group+(en-path:resource u.group)] update)
::
++ tap-nonempty
|= =notifications:store
^- (list [@da timebox:store])
%+ skim (tap:orm notifications)
|=([@da =timebox:store] !=(~(wyt by timebox) 0))
::
++ upd-cache
|= [read=? time=@da =index:store]
^+ +.state
%_ +.state
::
by-index
%. [(to-stats-index:store index) time]
?: read
~(del ju by-index)
~(put ju by-index)
==
::
++ inflate-cache
|= state-1
|= state-2
^+ +.state
=/ nots=(list [p=@da =timebox:store])
(tap:orm notifications)
|- =* outer $
?~ nots
+.state
?~ nots +.state
=/ unreads ~(tap by timebox.i.nots)
|- =* inner $
?~ unreads
@ -573,6 +651,6 @@
?: read.notification
inner(unreads t.unreads)
=. +.state
(upd-unreads index p.i.nots %.n)
(upd-cache %.n p.i.nots index)
inner(unreads t.unreads)
--

View File

@ -24,6 +24,6 @@
<div id="portal-root"></div>
<script src="/~landscape/js/channel.js"></script>
<script src="/~landscape/js/session.js"></script>
<script src="/~landscape/js/bundle/index.794cd750ed8a20a02046.js"></script>
<script src="/~landscape/js/bundle/index.8dba1503a67a4c02e6c5.js"></script>
</body>
</html>

View File

@ -17,6 +17,15 @@
%+ scry-for update:store
/graph/(scot %p entity.res)/[name.res]
::
++ get-graph-mop
|= res=resource
^- graph:store
=/ =update:store
(get-graph res)
?> ?=(%0 -.update)
?> ?=(%add-graph -.q.update)
graph.q.update
::
++ gut-younger-node-siblings
|= [res=resource =index:store]
^- (map index:store node:store)

View File

@ -27,6 +27,17 @@
description+so
index+(su ;~(pfix fas (more fas dem)))
==
::
++ stats-index
%- of
:~ graph+graph-stats-index
group+dejs-path:resource
==
++ graph-stats-index
%- ot
:~ graph+dejs-path:resource
index+graph-store-index
==
:: parse date as @ud
:: TODO: move to zuse
++ sd
@ -41,6 +52,8 @@
:~ time+sd
index+index
==
++ graph-store-index
(su ;~(pfix fas (more fas dem)))
::
++ add
|= jon=json
@ -48,8 +61,8 @@
::
++ read-graph-index
%- ot
:~ index+index
target+(su ;~(pfix fas (more fas dem)))
:~ index+stats-index
target+graph-store-index
==
::
++ action
@ -61,7 +74,7 @@
read-note+notif-ref
add-note+add
set-dnd+bo
read-count+index
read-count+stats-index
read-each+read-graph-index
==
--
@ -81,25 +94,44 @@
%count (numb count.upd)
%more (more +.upd)
%read-each (read-each +.upd)
%read-count (index +.upd)
%read-count (stats-index +.upd)
%unread-each (unread-each +.upd)
%unread-count (unread-count +.upd)
%remove-graph s+(enjs-path:resource +.upd)
%seen-index (seen-index +.upd)
%unreads (unreads +.upd)
::
?(%archive %read-note %unread-note)
(notif-ref +.upd)
==
::
++ stats-index
|= s=^stats-index
%+ frond -.s
|^
?- -.s
%graph (graph-stats-index +.s)
%group s+(enjs-path:resource +.s)
==
::
++ graph-stats-index
|= [graph=resource =index:graph-store]
%- pairs
:~ graph+s+(enjs-path:resource graph)
index+(index:enjs:graph-store index)
==
--
::
++ unreads
|= l=(list [^index ^index-stats])
|= l=(list [^stats-index ^stats])
^- json
:- %a
^- (list json)
%+ turn l
|= [idx=^index stats=^index-stats]
|= [idx=^stats-index s=^stats]
%- pairs
:~ stats+(index-stats stats)
index+(index idx)
:~ stats+(stats s)
index+(stats-index idx)
==
::
++ unread
@ -113,13 +145,13 @@
(numb num.unreads)
==
::
++ index-stats
|= stats=^index-stats
++ stats
|= s=^stats
^- json
%- pairs
:~ unreads+(unread unreads.stats)
notifications+(numb notifications.stats)
last+(time last-seen.stats)
:~ unreads+(unread unreads.s)
notifications+(numb notifications.s)
last+(time last-seen.s)
==
++ added
|= [tim=@da idx=^index not=^notification]
@ -137,6 +169,13 @@
:~ time+s+(scot %ud tim)
index+(index idx)
==
++ seen-index
|= [tim=@da idx=^stats-index]
^- json
%- pairs
:~ time+(time tim)
index+(stats-index idx)
==
::
++ more
|= upds=(list ^update)
@ -236,26 +275,45 @@
==
::
++ read-each
|= [=^index target=index:graph-store]
|= [s=^stats-index target=index:graph-store]
%- pairs
:~ index+(^index index)
:~ index+(stats-index s)
target+(index:enjs:graph-store target)
==
::
++ unread-each
|= [=^index target=index:graph-store tim=@da]
|= [s=^stats-index target=index:graph-store tim=@da]
%- pairs
:~ index+(^index index)
:~ index+(stats-index s)
target+(index:enjs:graph-store target)
last+(time tim)
==
::
++ unread-count
|= [=^index tim=@da]
|= [s=^stats-index tim=@da]
%- pairs
:~ index+(^index index)
:~ index+(stats-index s)
last+(time tim)
==
--
--
::
++ to-stats-index
|= =index
^- stats-index
?- -.index
%graph [%graph graph.index index.index]
%group [%group group.index]
==
++ stats-index-is-index
|= [=stats-index =index]
?- -.index
%graph
?. ?=(%graph -.stats-index) %.n
=([graph index]:index [graph index]:stats-index)
::
%group
?. ?=(%group -.stats-index) %.n
=(group:index group:stats-index)
==
--

View File

@ -564,7 +564,12 @@
::
++ se-klin :: disconnect app
|= gyl=gill:gall
+>(eel (~(del in eel) gyl))
=/ gil=(unit gill:gall) se-agon
=. eel (~(del in eel) gyl)
?~ gil +>.$
?: =(gyl u.gil)
+>.$(inx 0)
(se-alas u.gil)
::
++ se-link :: connect to app
|= gyl=gill:gall
@ -788,6 +793,7 @@
?- fec
[%bel *] ta-bel
[%blk *] +>
[%bye *] +>(..ta (se-klin gyl))
[%clr *] +>(..ta (se-blit fec))
[%det *] (ta-got +.fec)
[%err *] (ta-err p.fec)

View File

@ -7,7 +7,7 @@
?+ index.p.i ~
[@ ~] `[%link 0 %each %.y]
[@ @ %1 ~] `[%comment 1 %count %.n]
[@ @ @ ~] `[%edit-comment 1 %count %.n]
[@ @ @ ~] `[%edit-comment 1 %none %.n]
==
--
++ grab

View File

@ -9,9 +9,9 @@
++ notification-kind
?+ index.p.i ~
[@ %1 %1 ~] `[%note 0 %each %.n]
[@ %1 @ ~] `[%edit-note 0 %each %.n]
[@ %1 @ ~] `[%edit-note 0 %none %.n]
[@ %2 @ %1 ~] `[%comment 1 %count %.n]
[@ %2 @ @ ~] `[%edit-comment 1 %count %.n]
[@ %2 @ @ ~] `[%edit-comment 1 %none %.n]
==
--
++ grab

View File

@ -75,7 +75,7 @@
info+(tape ~(ram re tank))
==
::
?(%bel %clr %nex)
?(%bel %clr %nex %bye)
(frond %act %s -.sef)
==
--

View File

@ -35,6 +35,20 @@
[date=@da read=? =contents]
--
::
++ state-one
|%
+$ state
$: %1
unreads-each=(jug index index:graph-store)
unreads-count=(map index @ud)
last-seen=(map index @da)
=notifications
archive=notifications
current-timebox=@da
dnd=_|
==
--
::
+$ index
$% $: %graph
group=resource
@ -70,24 +84,33 @@
$% [%add-note =index =notification]
[%archive time=@da index]
::
[%unread-count =index =time]
[%read-count =index]
[%unread-count =stats-index =time]
[%read-count =stats-index]
::
[%unread-each =index ref=index:graph-store time=@da]
[%read-each index ref=index:graph-store]
::
[%unread-each =stats-index ref=index:graph-store time=@da]
[%read-each =stats-index ref=index:graph-store]
::
[%read-note time=@da index]
[%unread-note time=@da index]
::
[%seen-index time=@da =stats-index]
[%remove-graph =resource]
::
[%read-all ~]
[%set-dnd dnd=?]
[%seen ~]
==
::
++ stats-index
$% [%graph graph=resource =index:graph-store]
[%group group=resource]
==
::
+$ indexed-notification
[index notification]
::
+$ index-stats
+$ stats
[notifications=@ud =unreads last-seen=@da]
::
+$ unreads
@ -99,10 +122,9 @@
$% action
[%more more=(list update)]
[%added time=@da =index =notification]
[%read-index =index]
[%read time=@da =index]
[%timebox time=@da archived=? =(list [index notification])]
[%count count=@ud]
[%unreads unreads=(list [index index-stats])]
[%clear =stats-index]
[%unreads unreads=(list [stats-index stats])]
==
--

View File

@ -30,6 +30,7 @@
+$ sole-effect :: app to sole
$% [%bel ~] :: beep
[%blk p=@ud q=@c] :: blink+match char at
[%bye ~] :: close session
[%clr ~] :: clear screen
[%det sole-change] :: edit command
[%err p=@ud] :: error point

File diff suppressed because it is too large Load Diff

View File

@ -121,7 +121,7 @@ export class Eyre extends Component {
</>);
const subscriptionItems = c.subscriptions.map(s => {
//NOTE jsx sorta copied from /components/subscriptions
return {key: `${s.id} ${s.app} ${s.ship} ${s.path}`, jsx: (
return {key: `${s.id} ${s.ship} ${s.app} ${s.path}`, jsx: (
<div class="flex">
<div class="flex-auto" style={{maxWidth: '15%'}}>
{s.id}
@ -144,7 +144,7 @@ export class Eyre extends Component {
return {key: c.session, jsx: (
<Summary summary={summary} details={(
<SearchableList
placeholder="id, app, ship, path"
placeholder="id, ship, app, path"
items={subscriptionItems}
/>
)} />

View File

@ -1693,9 +1693,9 @@
"integrity": "sha512-3OPSdf9cejP/TSzWXuBaYbzLtAfBzQnc75SlPLkoPfwpxnv1Bvy9hiWngLY0WnKRR6lMOldnkYQCCuNWeDibYQ=="
},
"@tlon/indigo-react": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/@tlon/indigo-react/-/indigo-react-1.2.5.tgz",
"integrity": "sha512-NOQTwH74l/XXMIfQ4ZzymvZuk1WK1nmO552TmXrQxBUSb7HmdlA8anG5oRrvnLJTkajLCY59McLkDca+lCcvwg==",
"version": "1.2.15",
"resolved": "https://registry.npmjs.org/@tlon/indigo-react/-/indigo-react-1.2.15.tgz",
"integrity": "sha512-h9umWEzYZwyb53ujWoCQCJQwY9RUuoDaf6189+0LH3C7y9fybJe6vzbW6g2cUVH8dXA2EZkedS5nriYR0IpQbw==",
"requires": {
"@reach/menu-button": "^0.10.5",
"react": "^16.13.1",

View File

@ -199,7 +199,7 @@ export class HarkApi extends BaseApi<StoreState> {
getMore(archive = false) {
const offset = this.store.state[
archive ? 'archivedNotifications' : 'notifications'
].size;
]?.size || 0;
const count = 3;
return this.getSubset(offset,count, archive);
}

View File

@ -128,6 +128,7 @@ function graphWatchSelf(json: any, state: HarkState) {
}
function reduce(data: any, state: HarkState) {
console.log(data);
unread(data, state);
read(data, state);
archive(data, state);
@ -140,6 +141,22 @@ function reduce(data: any, state: HarkState) {
readSince(data, state);
unreadSince(data, state);
unreadEach(data, state);
seenIndex(data, state);
removeGraph(data, state);
}
function removeGraph(json: any, state: HarkState) {
const data = _.get(json, 'remove-graph');
if(data) {
delete state.unreads.graph[data];
}
}
function seenIndex(json: any, state: HarkState) {
const data = _.get(json, 'seen-index');
if(data) {
updateNotificationStats(state, data.index, 'last', () => data.time);
}
}
function readEach(json: any, state: HarkState) {
@ -152,16 +169,13 @@ function readEach(json: any, state: HarkState) {
function readSince(json: any, state: HarkState) {
const data = _.get(json, 'read-count');
if(data) {
console.log(data);
updateUnreadCount(state, data, () => 0)
}
}
function unreadSince(json: any, state: HarkState) {
const data = _.get(json, 'unread-count');
console.log(data);
if(data) {
updateNotificationStats(state, data.index, 'last', () => data.last)
updateUnreadCount(state, data.index, u => u + 1);
}
}
@ -169,7 +183,6 @@ function unreadSince(json: any, state: HarkState) {
function unreadEach(json: any, state: HarkState) {
const data = _.get(json, 'unread-each');
if(data) {
updateNotificationStats(state, data.index, 'last', () => data.last);
updateUnreads(state, data.index, us => us.add(data.target))
}
}
@ -199,7 +212,8 @@ function updateUnreadCount(state: HarkState, index: NotifIndex, count: (c: numbe
}
const property = [index.graph.graph, index.graph.index, 'unreads'];
const curr = _.get(state.unreads.graph, property, 0);
_.set(state.unreads.graph, property, count(curr));
const newCount = count(curr)
_.set(state.unreads.graph, property, newCount);
}
function updateUnreads(state: HarkState, index: NotifIndex, f: (us: Set<string>) => void) {
@ -207,7 +221,9 @@ function updateUnreads(state: HarkState, index: NotifIndex, f: (us: Set<string>)
return;
}
const unreads = _.get(state.unreads.graph, [index.graph.graph, index.graph.index, 'unreads'], new Set<string>());
const oldSize = unreads.size;
f(unreads);
const newSize = unreads.size;
_.set(state.unreads.graph, [index.graph.graph, index.graph.index, 'unreads'], unreads);
}
@ -222,9 +238,6 @@ function updateNotificationStats(state: HarkState, index: NotifIndex, statField:
} else if('group' in index) {
const curr = _.get(state.unreads.group, [index.group.group, statField], 0);
_.set(state.unreads.group, [index.group.group, statField], f(curr));
} else if('chat' in index) {
const curr = _.get(state.unreads.chat, [index.chat.chat, statField], 0);
_.set(state.unreads.chat, [index.chat.chat, statField], f(curr));
}
}
@ -350,11 +363,6 @@ function archive(json: any, state: HarkState) {
notifIdxEqual(index, idxNotif.index)
);
state.notifications.set(time, unarchived);
const archiveBox = state.archivedNotifications.get(time) || [];
const readCount = archived.filter(
({ notification }) => !notification.read
).length;
updateNotificationStats(state, index, 'notifications', x => x - readCount);
state.archivedNotifications.set(time, [
...archiveBox,
...archived.map(({ notification, index }) => ({

View File

@ -76,7 +76,6 @@ export const LinkItem = (props: LinkItemProps) => {
const markRead = () => {
api.hark.markEachAsRead(props.association, '/', `/${index}`, 'link', 'link');
console.log('mark read');
}
return (
<Box width="100%" {...rest}>

View File

@ -45,12 +45,14 @@ export function Note(props: NoteProps & RouteComponentProps) {
const comments = getComments(note);
const [revNum, title, body, post] = getLatestRevision(note);
const index = note.post.index.split('/');
const noteId = bigInt(index[1]);
useEffect(() => {
api.hark.markEachAsRead(props.association, '/', post.index, 'note', 'publish');
api.hark.markEachAsRead(props.association, '/',`/${index[1]}/1/1`, 'note', 'publish');
}, [props.association]);
const noteId = bigInt(note.post.index.split('/')[1]);
let adminLinks: JSX.Element | null = null;
if (window.ship === note?.post?.author) {

View File

@ -45,7 +45,7 @@ export function NotePreview(props: NotePreviewProps) {
const [rev, title, body, content] = getLatestRevision(node);
const appPath = `/ship/${props.host}/${props.book}`;
const isUnread = props.unreads.graph?.[appPath]?.['/']?.unreads?.has(content.index);
const isUnread = props.unreads.graph?.[appPath]?.['/']?.unreads?.has(`/${noteId}/1/1`);
const snippet = getSnippet(body);