mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-12-29 01:44:08 +03:00
hark: rework unread tracking, again
This commit is contained in:
parent
b7b4000986
commit
9ee62a2e55
@ -707,7 +707,7 @@
|
||||
=/ older ?=(%older i.t.t.path)
|
||||
=/ =ship (slav %p i.t.t.t.path)
|
||||
=/ =term i.t.t.t.t.path
|
||||
=/ count=@ud (slav %ud i.t.t.t.t.t.path)
|
||||
=/ count=(unit @ud) (slaw %ud i.t.t.t.t.t.path)
|
||||
=/ =index:store
|
||||
(turn t.t.t.t.t.t.path (cury slav %ud))
|
||||
=/ parent=index:store
|
||||
@ -723,7 +723,9 @@
|
||||
[ship term]
|
||||
%- ~(gas by *(map index:store node:store))
|
||||
%+ turn
|
||||
%+ scag count
|
||||
%- ?~ count same
|
||||
|= =(list [atom node:store])
|
||||
(slag u.count list)
|
||||
%- ?:(older same flop)
|
||||
%- tap:orm
|
||||
%+ subset:orm u.graph
|
||||
@ -745,7 +747,6 @@
|
||||
=/ children
|
||||
(get-node-children ship term index)
|
||||
?~ children [~ ~]
|
||||
~& count
|
||||
:- ~ :- ~ :- %graph-update
|
||||
!> ^- update:store
|
||||
:+ %0
|
||||
|
@ -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
|
||||
/+ resource, metadata, default-agent, dbug, graph-store, graph
|
||||
::
|
||||
::
|
||||
~% %hark-graph-hook-top ..is ~
|
||||
@ -49,6 +49,7 @@
|
||||
ha ~(. +> bowl)
|
||||
def ~(. (default-agent this %|) bowl)
|
||||
met ~(. metadata bowl)
|
||||
gra ~(. graph bowl)
|
||||
::
|
||||
++ on-init
|
||||
:_ this
|
||||
@ -59,9 +60,21 @@
|
||||
|= old=vase
|
||||
^- (quip card _this)
|
||||
:_ this(state !<(state-0 old))
|
||||
?: (~(has by wex.bowl) [/graph our.bowl %graph-store])
|
||||
~
|
||||
~[watch-graph:ha]
|
||||
%+ welp
|
||||
?: (~(has by wex.bowl) [/graph our.bowl %graph-store])
|
||||
~
|
||||
~[watch-graph:ha]
|
||||
%+ turn
|
||||
^- (list mark)
|
||||
:~ %graph-validator-chat
|
||||
%graph-validator-link
|
||||
%graph-validator-publish
|
||||
==
|
||||
|= =mark
|
||||
^- card
|
||||
=/ =wire /validator/[mark]
|
||||
=/ =rave:clay [%sing %c [%da now.bowl] /[mark]/notification-kind]
|
||||
[%pass wire %arvo %c %warp our.bowl [%home `rave]]
|
||||
::
|
||||
++ on-watch
|
||||
|= =path
|
||||
@ -146,32 +159,39 @@
|
||||
[cards this]
|
||||
==
|
||||
++ add-graph
|
||||
|= rid=resource
|
||||
|= [rid=resource =graph:graph-store]
|
||||
^- (quip card _state)
|
||||
=^ cards state
|
||||
(check-nodes (tap-deep:gra graph) rid)
|
||||
:- cards
|
||||
?. &(watch-on-self =(our.bowl entity.rid))
|
||||
[~ state]
|
||||
`state(watching (~(put in watching) [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-graph resource.q.update graph.q.update)
|
||||
?. ?=(%add-nodes -.q.update)
|
||||
[~ state]
|
||||
=/ group=resource
|
||||
(need (group-from-app-resource:met %graph resource.q.update))
|
||||
=/ =metadata:metadata-store
|
||||
(need (peek-metadata:met %graph group resource.q.update))
|
||||
=* rid resource.q.update
|
||||
(check-nodes ~(tap by nodes.q.update) rid)
|
||||
::
|
||||
++ check-nodes
|
||||
|= $: nodes=(list [p=index:graph-store q=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
|
||||
=/ nodes=(list [p=index:graph-store q=node:graph-store])
|
||||
~(tap by nodes.q.update)
|
||||
=| cards=(list card)
|
||||
|^
|
||||
?~ nodes
|
||||
@ -208,7 +228,7 @@
|
||||
^- (quip card _state)
|
||||
=^ child-cards state
|
||||
(check-node-children node tube)
|
||||
=+ !< notif-kind=(unit [name=@t parent-lent=@ud mode=?(%each %since)])
|
||||
=+ !< notif-kind=(unit [name=@t parent-lent=@ud mode=?(%each %count)])
|
||||
(tube !>([0 post.node]))
|
||||
?~ notif-kind
|
||||
[child-cards state]
|
||||
@ -252,13 +272,13 @@
|
||||
++ self-post
|
||||
|= $: =node:graph-store
|
||||
=index:store
|
||||
mode=?(%since %each)
|
||||
mode=?(%count %each)
|
||||
==
|
||||
^- (quip card _state)
|
||||
=| cards=(list card)
|
||||
=? cards ?=(%since mode)
|
||||
=? cards ?=(%count mode)
|
||||
:_ cards
|
||||
(poke-hark %read-since index index.post.node)
|
||||
(poke-hark %read-count index)
|
||||
?. ?=(%.y watch-on-self)
|
||||
[cards state]
|
||||
:- cards
|
||||
@ -271,9 +291,9 @@
|
||||
hark-action+!>(action)
|
||||
::
|
||||
++ update-unread-count
|
||||
|= [mode=?(%since %each) =index:store time=@da ref=index:graph-store]
|
||||
?: ?=(%since mode)
|
||||
(poke-hark %unread-since index time)
|
||||
|= [mode=?(%count %each) =index:store time=@da ref=index:graph-store]
|
||||
?: ?=(%count mode)
|
||||
(poke-hark %unread-count index time)
|
||||
(poke-hark %unread-each index ref time)
|
||||
::
|
||||
++ add-unread
|
||||
@ -286,7 +306,17 @@
|
||||
++ on-peek on-peek:def
|
||||
::
|
||||
++ on-leave on-leave:def
|
||||
++ on-arvo on-arvo:def
|
||||
++ on-arvo
|
||||
|= [=wire =sign-arvo]
|
||||
^- (quip card _this)
|
||||
?+ wire (on-arvo:def wire sign-arvo)
|
||||
::
|
||||
[%validator @ ~]
|
||||
:_ this
|
||||
=* validator i.t.wire
|
||||
=/ =rave:clay [%next %c [%da now.bowl] /[validator]/notification-kind]
|
||||
[%pass wire %arvo %c %warp our.bowl [%home `rave]]~
|
||||
==
|
||||
++ on-fail on-fail:def
|
||||
--
|
||||
|
||||
|
@ -10,8 +10,8 @@
|
||||
:: Usefull for non-linear, low-volume applications, i.e. blogs,
|
||||
:: collections
|
||||
::
|
||||
/- store=hark-store, post, group-store, metadata-store
|
||||
/+ resource, metadata, default-agent, dbug, graph-store
|
||||
/- post, group-store, metadata-store
|
||||
/+ resource, metadata, default-agent, dbug, graph-store, graphl=graph, verb, store=hark-store
|
||||
::
|
||||
::
|
||||
~% %hark-store-top ..is ~
|
||||
@ -27,7 +27,7 @@
|
||||
+$ state-1
|
||||
$: %1
|
||||
unreads-each=(jug index:store index:graph-store)
|
||||
unreads-since=(map index:store index:graph-store)
|
||||
unreads-count=(map index:store @ud)
|
||||
last-seen=(map index:store @da)
|
||||
=notifications:store
|
||||
archive=notifications:store
|
||||
@ -52,6 +52,7 @@
|
||||
=* state -
|
||||
::
|
||||
=<
|
||||
%+ verb |
|
||||
%- agent:dbug
|
||||
^- agent:gall
|
||||
~% %hark-store-agent ..card ~
|
||||
@ -60,6 +61,7 @@
|
||||
ha ~(. +> bowl)
|
||||
def ~(. (default-agent this %|) bowl)
|
||||
met ~(. metadata bowl)
|
||||
gra ~(. graphl bowl)
|
||||
::
|
||||
++ on-init
|
||||
:_ this
|
||||
@ -101,6 +103,7 @@
|
||||
++ initial-updates
|
||||
^- update:store
|
||||
:- %more
|
||||
=- ~&(- -)
|
||||
^- (list update:store)
|
||||
:+ give-unreads
|
||||
[%set-dnd dnd]
|
||||
@ -115,11 +118,12 @@
|
||||
++ give-since-unreads
|
||||
^- (list [index:store index-stats:store])
|
||||
%+ turn
|
||||
~(tap by unreads-since)
|
||||
|= [=index:store since=index:graph-store]
|
||||
~(tap by unreads-count)
|
||||
|= [=index:store count=@ud]
|
||||
?> ?=(%graph -.index)
|
||||
:* index
|
||||
~(wyt in (~(gut by by-index) index ~))
|
||||
[%since since]
|
||||
[%count count]
|
||||
(~(gut by last-seen) index *time)
|
||||
==
|
||||
++ give-each-unreads
|
||||
@ -186,6 +190,7 @@
|
||||
::
|
||||
++ hark-action
|
||||
|= =action:store
|
||||
~& -.action
|
||||
^- (quip card _state)
|
||||
|^
|
||||
?- -.action
|
||||
@ -195,8 +200,8 @@
|
||||
%read-each (read-each +.action)
|
||||
%unread-each (unread-each +.action)
|
||||
::
|
||||
%read-since (read-since +.action)
|
||||
%unread-since (unread-since +.action)
|
||||
%read-count (read-count +.action)
|
||||
%unread-count (unread-count +.action)
|
||||
::
|
||||
%read-note (read-note +.action)
|
||||
%unread-note (unread-note +.action)
|
||||
@ -218,7 +223,7 @@
|
||||
?~ existing-notif
|
||||
notification
|
||||
(merge-notification:ha u.existing-notif notification)
|
||||
=. read.new %.y
|
||||
=. read.new %.n
|
||||
=/ new-timebox=timebox:store
|
||||
(~(put by timebox) index new)
|
||||
:- (give:ha [/updates]~ %added current-timebox index new)
|
||||
@ -316,15 +321,15 @@
|
||||
notifications (change-read-status:ha time index %.n)
|
||||
==
|
||||
::
|
||||
++ read-since
|
||||
|= [=index:store since=index:graph-store]
|
||||
++ read-count
|
||||
|= =index:store
|
||||
^- (quip card _state)
|
||||
=^ cards state
|
||||
(read-index index)
|
||||
:- %+ weld cards
|
||||
(give:ha [/updates]~ %read-since index since)
|
||||
(give:ha [/updates]~ %read-count index)
|
||||
%_ state
|
||||
unreads-since (~(put by unreads-since) index since)
|
||||
unreads-count (~(put by unreads-count) index 0)
|
||||
==
|
||||
::
|
||||
++ read-boxes
|
||||
@ -351,12 +356,15 @@
|
||||
^- (quip card _state)
|
||||
`state
|
||||
::
|
||||
++ unread-since
|
||||
++ unread-count
|
||||
|= [=index:store time=@da]
|
||||
^- (quip card _state)
|
||||
:- (give:ha [/updates]~ %unread-since index time)
|
||||
:- (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
|
||||
|
@ -17,6 +17,17 @@
|
||||
%+ scry-for update:store
|
||||
/graph/(scot %p entity.res)/[name.res]
|
||||
::
|
||||
++ gut-younger-node-siblings
|
||||
|= [res=resource =index:store]
|
||||
^- (map index:store node:store)
|
||||
=+ %+ scry-for ,=update:store
|
||||
%+ weld
|
||||
/node-siblings/younger/(scot %p entity.res)/[name.res]/all
|
||||
(turn index (cury scot %ud))
|
||||
?> ?=(%0 -.update)
|
||||
?> ?=(%add-nodes -.q.update)
|
||||
nodes.q.update
|
||||
::
|
||||
++ got-node
|
||||
|= [res=resource =index:store]
|
||||
^- node:store
|
||||
@ -53,4 +64,27 @@
|
||||
?> ?=(%0 -.update)
|
||||
?> ?=(%keys -.q.update)
|
||||
resources.q.update
|
||||
::
|
||||
++ tap-deep
|
||||
|= =graph:store
|
||||
^- (list [index:store node:store])
|
||||
=| =index:store
|
||||
=/ nodes=(list [atom node:store])
|
||||
(tap:orm:store graph)
|
||||
|- =* tap-nodes $
|
||||
^- (list [index:store node:store])
|
||||
%- zing
|
||||
%+ turn
|
||||
nodes
|
||||
|= [=atom =node:store]
|
||||
^- (list [index:store node:store])
|
||||
%+ welp
|
||||
^- (list [index:store node:store])
|
||||
[(snoc index atom) node]~
|
||||
?. ?=(%graph -.children.node)
|
||||
~
|
||||
%_ tap-nodes
|
||||
index (snoc index atom)
|
||||
nodes (tap:orm:store p.children.node)
|
||||
==
|
||||
--
|
||||
|
@ -69,7 +69,7 @@
|
||||
read-note+notif-ref
|
||||
add-note+add
|
||||
set-dnd+bo
|
||||
read-since+read-graph-index
|
||||
read-count+index
|
||||
read-each+read-graph-index
|
||||
==
|
||||
--
|
||||
@ -88,10 +88,10 @@
|
||||
%set-dnd b+dnd.upd
|
||||
%count (numb count.upd)
|
||||
%more (more +.upd)
|
||||
%read-each (read-graph +.upd)
|
||||
%read-since (read-graph +.upd)
|
||||
%read-each (read-each +.upd)
|
||||
%read-count (index +.upd)
|
||||
%unread-each (unread-each +.upd)
|
||||
%unread-since (unread-since +.upd)
|
||||
%unread-count (unread-count +.upd)
|
||||
%unreads (unreads +.upd)
|
||||
::
|
||||
?(%archive %read-note %unread-note)
|
||||
@ -106,7 +106,7 @@
|
||||
%+ turn l
|
||||
|= [idx=^index stats=^index-stats]
|
||||
%- pairs
|
||||
:~ unread+(numb unread)
|
||||
:~ stats+(index-stats stats)
|
||||
index+(index idx)
|
||||
==
|
||||
::
|
||||
@ -115,8 +115,10 @@
|
||||
%+ frond
|
||||
-.unreads
|
||||
?- -.unreads
|
||||
%since (index:enjs:graph-store index.unreads)
|
||||
%each a+(turn ~(tap by indices.unreads) index:enjs:graph-store)
|
||||
::
|
||||
%count
|
||||
(numb num.unreads)
|
||||
==
|
||||
::
|
||||
++ index-stats
|
||||
@ -257,7 +259,7 @@
|
||||
(indexed-notification index notification)
|
||||
==
|
||||
::
|
||||
++ read-graph
|
||||
++ read-each
|
||||
|= [=^index target=index:graph-store]
|
||||
%- pairs
|
||||
:~ index+(^index index)
|
||||
@ -272,7 +274,7 @@
|
||||
last+(time tim)
|
||||
==
|
||||
::
|
||||
++ unread-since
|
||||
++ unread-count
|
||||
|= [=^index tim=@da]
|
||||
%- pairs
|
||||
:~ index+(^index index)
|
||||
|
@ -5,7 +5,7 @@
|
||||
++ noun i
|
||||
++ notification-kind
|
||||
?+ index.p.i ~
|
||||
[@ ~] `[%message 0]
|
||||
[@ ~] `[%message 0 %count]
|
||||
==
|
||||
--
|
||||
++ grab
|
||||
|
@ -6,7 +6,7 @@
|
||||
++ notification-kind
|
||||
?+ index.p.i ~
|
||||
[@ ~] `[%link 0 %each]
|
||||
[@ @ @ ~] `[%comment 1 %since]
|
||||
[@ @ @ ~] `[%comment 1 %count]
|
||||
==
|
||||
--
|
||||
++ grab
|
||||
|
@ -9,7 +9,7 @@
|
||||
++ notification-kind
|
||||
?+ index.p.i ~
|
||||
[@ %1 @ ~] `[%note 0 %each]
|
||||
[@ %2 @ @ ~] `[%comment 1 %since]
|
||||
[@ %2 @ @ ~] `[%comment 1 %count]
|
||||
==
|
||||
--
|
||||
++ grab
|
||||
|
@ -61,8 +61,8 @@
|
||||
$% [%add-note =index =notification]
|
||||
[%archive time=@da index]
|
||||
::
|
||||
[%unread-since =index time=@da]
|
||||
[%read-since =index =index:graph-store]
|
||||
[%unread-count =index =time]
|
||||
[%read-count =index]
|
||||
::
|
||||
[%unread-each =index ref=index:graph-store time=@da]
|
||||
[%read-each index ref=index:graph-store]
|
||||
@ -82,7 +82,7 @@
|
||||
[notifications=@ud =unreads last-seen=@da]
|
||||
::
|
||||
+$ unreads
|
||||
$% [%since =index:graph-store]
|
||||
$% [%count num=@ud]
|
||||
[%each indices=(set index:graph-store)]
|
||||
==
|
||||
::
|
||||
|
@ -58,7 +58,7 @@ export class HarkApi extends BaseApi<StoreState> {
|
||||
}
|
||||
|
||||
read(time: BigInteger, index: NotifIndex) {
|
||||
return this.actOnNotification('read', time, index);
|
||||
return this.actOnNotification('read-note', time, index);
|
||||
}
|
||||
|
||||
readIndex(index: NotifIndex) {
|
||||
@ -68,21 +68,20 @@ export class HarkApi extends BaseApi<StoreState> {
|
||||
}
|
||||
|
||||
unread(time: BigInteger, index: NotifIndex) {
|
||||
return this.actOnNotification('unread', time, index);
|
||||
return this.actOnNotification('unread-note', time, index);
|
||||
}
|
||||
|
||||
markSinceAsRead(association: Association, parent: string, description: GraphNotifDescription, since: string) {
|
||||
markCountAsRead(association: Association, parent: string, description: GraphNotifDescription) {
|
||||
return this.harkAction(
|
||||
{ 'read-since': {
|
||||
index: { graph: {
|
||||
{ 'read-count': {
|
||||
graph: {
|
||||
graph: association['app-path'],
|
||||
group: association['group-path'],
|
||||
module: association.metadata.module,
|
||||
description,
|
||||
index: parent
|
||||
} },
|
||||
target: since
|
||||
}});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
@ -150,16 +150,18 @@ function readEach(json: any, state: HarkState) {
|
||||
}
|
||||
|
||||
function readSince(json: any, state: HarkState) {
|
||||
const data = _.get(json, 'read-since');
|
||||
const data = _.get(json, 'read-count');
|
||||
if(data) {
|
||||
updateUnreadSince(state, data.index, data.target)
|
||||
updateUnreadCount(state, data, () => 0)
|
||||
}
|
||||
}
|
||||
|
||||
function unreadSince(json: any, state: HarkState) {
|
||||
const data = _.get(json, 'unread-since');
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -174,12 +176,13 @@ function unreadEach(json: any, state: HarkState) {
|
||||
function unreads(json: any, state: HarkState) {
|
||||
const data = _.get(json, 'unreads');
|
||||
if(data) {
|
||||
console.log(data);
|
||||
data.forEach(({ index, stats }) => {
|
||||
const { unreads, notifications, last } = stats;
|
||||
updateNotificationStats(state, index, 'notifications', x => x + notifications);
|
||||
updateNotificationStats(state, index, 'last', () => last);
|
||||
if('since' in unreads) {
|
||||
updateUnreadSince(state, index, unreads.since);
|
||||
if('count' in unreads) {
|
||||
updateUnreadCount(state, index, () => unreads.count);
|
||||
} else {
|
||||
unreads.each.forEach((u: string) => {
|
||||
updateUnreads(state, index, s => s.add(u));
|
||||
@ -189,11 +192,13 @@ function unreads(json: any, state: HarkState) {
|
||||
}
|
||||
}
|
||||
|
||||
function updateUnreadSince(state: HarkState, index: NotifIndex, since: string) {
|
||||
function updateUnreadCount(state: HarkState, index: NotifIndex, count: (c: number) => number) {
|
||||
if(!('graph' in index)) {
|
||||
return;
|
||||
}
|
||||
_.set(state.unreads.graph, [index.graph.graph, index.graph.index, 'unreads'], since);
|
||||
const property = [index.graph.graph, index.graph.index, 'unreads'];
|
||||
const curr = _.get(state.unreads.graph, property, 0);
|
||||
_.set(state.unreads.graph, property, count(curr));
|
||||
}
|
||||
|
||||
function updateUnreads(state: HarkState, index: NotifIndex, f: (us: Set<string>) => void) {
|
||||
|
@ -7,7 +7,7 @@ import { Envelope } from './chat-update';
|
||||
export type GraphNotifDescription = "link" | "comment" | "note" | "mention";
|
||||
|
||||
export interface UnreadStats {
|
||||
unreads: Set<string>;
|
||||
unreads: Set<string> | { index: string; count: number; };
|
||||
notifications: number;
|
||||
last: number;
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ export function ChatResource(props: ChatResourceProps) {
|
||||
envelopes.length > 0) ||
|
||||
false;
|
||||
|
||||
const unreadCount = length - read;
|
||||
const unreadCount = props.unreads.graph?.[station]?.['/']?.unreads || 0;
|
||||
const unreadMsg = unreadCount > 0 && envelopes[unreadCount - 1];
|
||||
|
||||
const [,, owner, name] = station.split('/');
|
||||
@ -66,7 +66,7 @@ export function ChatResource(props: ChatResourceProps) {
|
||||
const chatInput = useRef<ChatInput>();
|
||||
|
||||
useEffect(() => {
|
||||
props.api.graph.getNewest(owner, name, 10);
|
||||
props.api.graph.getNewest(owner, name, 20);
|
||||
}, [station]);
|
||||
|
||||
const onFileDrag = useCallback(
|
||||
@ -121,7 +121,7 @@ export function ChatResource(props: ChatResourceProps) {
|
||||
isChatLoading={isChatLoading}
|
||||
isChatUnsynced={isChatUnsynced}
|
||||
graph={graph}
|
||||
unreadCount={0}
|
||||
unreadCount={unreadCount}
|
||||
unreadMsg={false}
|
||||
envelopes={[]}
|
||||
contacts={contacts}
|
||||
|
@ -51,7 +51,7 @@ interface ChatWindowState {
|
||||
fetchPending: boolean;
|
||||
idle: boolean;
|
||||
initialized: boolean;
|
||||
lastRead: number;
|
||||
unreadIndex: BigInteger;
|
||||
}
|
||||
|
||||
export default class ChatWindow extends Component<ChatWindowProps, ChatWindowState> {
|
||||
@ -60,19 +60,23 @@ export default class ChatWindow extends Component<ChatWindowProps, ChatWindowSta
|
||||
private prevSize = 0;
|
||||
private loadedNewest = false;
|
||||
private loadedOldest = false;
|
||||
private unreadIndex: BigInteger | null = null;
|
||||
|
||||
INITIALIZATION_MAX_TIME = 1500;
|
||||
|
||||
constructor(props) {
|
||||
constructor(props: ChatWindowProps) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
fetchPending: false,
|
||||
idle: true,
|
||||
initialized: false,
|
||||
lastRead: props.unreadCount ? props.mailboxSize - props.unreadCount : -1,
|
||||
unreadIndex: bigInt.zero
|
||||
};
|
||||
|
||||
this.calculateUnreadIndex();
|
||||
|
||||
|
||||
this.dismissUnread = this.dismissUnread.bind(this);
|
||||
this.scrollToUnread = this.scrollToUnread.bind(this);
|
||||
this.handleWindowBlur = this.handleWindowBlur.bind(this);
|
||||
@ -102,6 +106,17 @@ export default class ChatWindow extends Component<ChatWindowProps, ChatWindowSta
|
||||
window.removeEventListener('focus', this.handleWindowFocus);
|
||||
}
|
||||
|
||||
calculateUnreadIndex() {
|
||||
const { graph, unreadCount } = this.props;
|
||||
const unreadIndex = graph.keys()[unreadCount];
|
||||
if(!unreadIndex) {
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
unreadIndex
|
||||
})
|
||||
}
|
||||
|
||||
handleWindowBlur() {
|
||||
this.setState({ idle: true });
|
||||
}
|
||||
@ -127,13 +142,16 @@ export default class ChatWindow extends Component<ChatWindowProps, ChatWindowSta
|
||||
this.stayLockedIfActive();
|
||||
}*/
|
||||
|
||||
/*if (unreadCount > prevProps.unreadCount && this.state.idle) {
|
||||
this.setState({
|
||||
lastRead: unreadCount ? mailboxSize - unreadCount : -1,
|
||||
});
|
||||
}*/
|
||||
if (unreadCount > prevProps.unreadCount && this.state.idle) {
|
||||
this.calculateUnreadIndex();
|
||||
}
|
||||
|
||||
|
||||
if(this.prevSize !== graph.size) {
|
||||
if(this.state.unreadIndex.eq(bigInt.zero)) {
|
||||
this.calculateUnreadIndex();
|
||||
this.scrollToUnread();
|
||||
}
|
||||
this.prevSize = graph.size;
|
||||
this.virtualList?.calculateVisibleItems();
|
||||
}
|
||||
@ -145,15 +163,12 @@ export default class ChatWindow extends Component<ChatWindowProps, ChatWindowSta
|
||||
if (!this.state.fetchPending && prevState.fetchPending) {
|
||||
this.virtualList?.calculateVisibleItems();
|
||||
}
|
||||
*/
|
||||
|
||||
if (station !== prevProps.station) {
|
||||
this.virtualList?.resetScroll();
|
||||
this.scrollToUnread();
|
||||
this.setState({
|
||||
lastRead: unreadCount ? mailboxSize - unreadCount : -1,
|
||||
});
|
||||
this.calculateUnreadIndex();
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
stayLockedIfActive() {
|
||||
@ -164,16 +179,19 @@ export default class ChatWindow extends Component<ChatWindowProps, ChatWindowSta
|
||||
}
|
||||
|
||||
scrollToUnread() {
|
||||
/*
|
||||
const { mailboxSize, unreadCount, scrollTo } = this.props;
|
||||
const target = scrollTo || (mailboxSize - unreadCount);
|
||||
this.virtualList?.scrollToData(target);
|
||||
*/
|
||||
const { unreadIndex } = this.state;
|
||||
if(unreadIndex.eq(bigInt.zero)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.virtualList?.scrollToData(unreadIndex);
|
||||
}
|
||||
|
||||
dismissUnread() {
|
||||
const { association } = this.props;
|
||||
if (this.state.fetchPending) return;
|
||||
if (this.props.unreadCount === 0) return;
|
||||
//this.props.api.hark.markCountAsRead(association, '/', 'message');
|
||||
//this.props.api.chat.read(this.props.station);
|
||||
//this.props.api.hark.readIndex({ chat: { chat: this.props.station, mention: false }});
|
||||
}
|
||||
@ -234,7 +252,6 @@ export default class ChatWindow extends Component<ChatWindowProps, ChatWindowSta
|
||||
const {
|
||||
stationPendingMessages,
|
||||
unreadCount,
|
||||
unreadMsg,
|
||||
isChatLoading,
|
||||
isChatUnsynced,
|
||||
api,
|
||||
@ -258,12 +275,14 @@ export default class ChatWindow extends Component<ChatWindowProps, ChatWindowSta
|
||||
const messageProps = { association, group, contacts, hideAvatars, hideNicknames, remoteContentPolicy, unreadMarkerRef, history, api };
|
||||
|
||||
const keys = graph.keys().reverse();
|
||||
const unreadIndex = keys[this.props.unreadCount];
|
||||
const unreadMsg = unreadIndex && graph.get(unreadIndex);
|
||||
|
||||
return (
|
||||
<>
|
||||
<UnreadNotice
|
||||
unreadCount={unreadCount}
|
||||
unreadMsg={unreadCount === 1 && unreadMsg && unreadMsg.author === window.ship ? false : unreadMsg}
|
||||
unreadMsg={unreadCount === 1 && unreadMsg && unreadMsg?.post.author === window.ship ? false : unreadMsg}
|
||||
dismissUnread={this.dismissUnread}
|
||||
onClick={this.scrollToUnread}
|
||||
/>
|
||||
@ -281,19 +300,21 @@ export default class ChatWindow extends Component<ChatWindowProps, ChatWindowSta
|
||||
data={graph}
|
||||
size={graph.size}
|
||||
renderer={({ index, measure, scrollWindow }) => {
|
||||
const msg = graph.get(index)!.post;
|
||||
const msg = graph.get(index)?.post;
|
||||
if (!msg) return null;
|
||||
if (!this.state.initialized) {
|
||||
return <MessagePlaceholder key={index.toString()} height="64px" index={index} />;
|
||||
}
|
||||
const isPending: boolean = 'pending' in msg && Boolean(msg.pending);
|
||||
const isLastMessage: boolean = Boolean(index.eq(bigInt(lastMessage)));
|
||||
const isLastRead: boolean = Boolean(!isLastMessage && index.eq(bigInt(this.state.lastRead)));
|
||||
const highlighted = bigInt(this.props.scrollTo || -1).eq(index);
|
||||
const props = { measure, highlighted, scrollWindow, isPending, isLastRead, isLastMessage, msg, ...messageProps };
|
||||
const graphIdx = keys.findIndex(idx => idx.eq(index));
|
||||
const prevIdx = keys[graphIdx+1];
|
||||
const nextIdx = keys[graphIdx-1];
|
||||
|
||||
|
||||
const isLastRead: boolean = this.state.unreadIndex.eq(index);
|
||||
const props = { measure, highlighted, scrollWindow, isPending, isLastRead, isLastMessage, msg, ...messageProps };
|
||||
return (
|
||||
<ChatMessage
|
||||
key={index.toString()}
|
||||
|
@ -9,8 +9,8 @@ export const UnreadNotice = (props) => {
|
||||
return null;
|
||||
}
|
||||
|
||||
let datestamp = moment.unix(unreadMsg.when / 1000).format('YYYY.M.D');
|
||||
const timestamp = moment.unix(unreadMsg.when / 1000).format('HH:mm');
|
||||
let datestamp = moment.unix(unreadMsg.post['time-sent'] / 1000).format('YYYY.M.D');
|
||||
const timestamp = moment.unix(unreadMsg.post['time-sent'] / 1000).format('HH:mm');
|
||||
|
||||
if (datestamp === moment().format('YYYY.M.D')) {
|
||||
datestamp = null;
|
||||
@ -55,4 +55,4 @@ export const UnreadNotice = (props) => {
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -20,22 +20,13 @@ interface UnjoinedResourceProps {
|
||||
inbox: Inbox;
|
||||
}
|
||||
|
||||
function isJoined(app: string, path: string) {
|
||||
function isJoined(path: string) {
|
||||
return function (
|
||||
props: Pick<UnjoinedResourceProps, "inbox" | "graphKeys">
|
||||
props: Pick<UnjoinedResourceProps, "graphKeys">
|
||||
) {
|
||||
const graphKey = path.substr(7);
|
||||
switch (app) {
|
||||
case "link":
|
||||
case "publish":
|
||||
return props.graphKeys.has(graphKey);
|
||||
case "chat":
|
||||
return !!props.inbox[path];
|
||||
default:
|
||||
console.log("Bad app name");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
return props.graphKeys.has(graphKey);
|
||||
}
|
||||
}
|
||||
|
||||
export function UnjoinedResource(props: UnjoinedResourceProps) {
|
||||
@ -48,26 +39,14 @@ export function UnjoinedResource(props: UnjoinedResourceProps) {
|
||||
const app = useMemo(() => module || appName, [props.association]);
|
||||
|
||||
const onJoin = async () => {
|
||||
let ship, name;
|
||||
switch (app) {
|
||||
case "publish":
|
||||
case "link":
|
||||
[, , ship, name] = appPath.split("/");
|
||||
await api.graph.joinGraph(ship, name);
|
||||
break;
|
||||
case "chat":
|
||||
[, ship, name] = appPath.split("/");
|
||||
await api.chat.join(ship, appPath, true);
|
||||
break;
|
||||
default:
|
||||
throw new Error("Unknown resource type");
|
||||
}
|
||||
await waiter(isJoined(app, appPath));
|
||||
const [, , ship, name] = appPath.split("/");
|
||||
await api.graph.joinGraph(ship, name);
|
||||
await waiter(isJoined(appPath));
|
||||
history.push(`${props.baseUrl}/resource/${app}${appPath}`);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (isJoined(app, appPath)({ inbox, graphKeys })) {
|
||||
if (isJoined(appPath)({ graphKeys })) {
|
||||
history.push(`${props.baseUrl}/resource/${app}${appPath}`);
|
||||
}
|
||||
}, [props.association, inbox, graphKeys, notebooks]);
|
||||
|
@ -170,14 +170,17 @@ export default class VirtualScroller extends Component<VirtualScrollerProps, Vir
|
||||
|
||||
|
||||
const firstVisibleKey = visibleItems.peekSmallest()?.[0] ?? this.estimateIndexFromScrollTop(scrollTop)!;
|
||||
if (data.peekSmallest()![0].eq(firstVisibleKey)) {
|
||||
const smallest = data.peekSmallest();
|
||||
if (smallest && smallest[0].eq(firstVisibleKey)) {
|
||||
this.loadRows(false);
|
||||
}
|
||||
const lastVisibleKey =
|
||||
visibleItems.peekLargest()?.[0]
|
||||
?? bigInt(this.estimateIndexFromScrollTop(scrollTop + windowHeight)!);
|
||||
|
||||
if (data.peekLargest()![0].eq(lastVisibleKey)) {
|
||||
const largest = data.peekLargest();
|
||||
|
||||
if (largest && largest[0].eq(lastVisibleKey)) {
|
||||
this.loadRows(true);
|
||||
}
|
||||
onCalculateVisibleItems ? onCalculateVisibleItems(visibleItems) : null;
|
||||
|
Loading…
Reference in New Issue
Block a user