Merge branch 'lf/hark-final-fix'

This commit is contained in:
Liam Fitzgerald 2021-03-24 12:17:27 +10:00
commit dfb313dba3
No known key found for this signature in database
GPG Key ID: D390E12C61D1CFFB
6 changed files with 93 additions and 33 deletions

View File

@ -293,7 +293,7 @@
~(tap by unreads-count) ~(tap by unreads-count)
|= [=stats-index:store count=@ud] |= [=stats-index:store count=@ud]
:* stats-index :* stats-index
~(wyt in (~(gut by by-index) stats-index ~)) (~(gut by by-index) stats-index ~)
[%count count] [%count count]
(~(gut by last-seen) stats-index *time) (~(gut by last-seen) stats-index *time)
== ==
@ -304,7 +304,7 @@
~(tap by unreads-each) ~(tap by unreads-each)
|= [=stats-index:store indices=(set index:graph-store)] |= [=stats-index:store indices=(set index:graph-store)]
:* stats-index :* stats-index
~(wyt in (~(gut by by-index) stats-index ~)) (~(gut by by-index) stats-index ~)
[%each indices] [%each indices]
(~(gut by last-seen) stats-index *time) (~(gut by last-seen) stats-index *time)
== ==
@ -317,7 +317,7 @@
~ ~
:- ~ :- ~
:* stats-index :* stats-index
~(wyt in nots) nots
[%count 0] [%count 0]
*time *time
== ==

View File

@ -151,7 +151,7 @@
^- json ^- json
%- pairs %- pairs
:~ unreads+(unread unreads.s) :~ unreads+(unread unreads.s)
notifications+(numb notifications.s) notifications+a+(turn ~(tap in notifications.s) notif-ref)
last+(time last-seen.s) last+(time last-seen.s)
== ==
++ added ++ added

View File

@ -150,7 +150,7 @@
[index notification] [index notification]
:: ::
+$ stats +$ stats
[notifications=@ud =unreads last-seen=@da] [notifications=(set [time index]) =unreads last-seen=@da]
:: ::
+$ unreads +$ unreads
$% [%count num=@ud] $% [%count num=@ud]

View File

@ -1783,30 +1783,36 @@
"dependencies": { "dependencies": {
"@babel/runtime": { "@babel/runtime": {
"version": "7.12.5", "version": "7.12.5",
"bundled": true, "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz",
"integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==",
"requires": { "requires": {
"regenerator-runtime": "^0.13.4" "regenerator-runtime": "^0.13.4"
} }
}, },
"@types/lodash": { "@types/lodash": {
"version": "4.14.168", "version": "4.14.168",
"bundled": true "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.168.tgz",
"integrity": "sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q=="
}, },
"@urbit/eslint-config": { "@urbit/eslint-config": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true "resolved": "https://registry.npmjs.org/@urbit/eslint-config/-/eslint-config-1.0.0.tgz",
"integrity": "sha512-Xmzb6MvM7KorlPJEq/hURZZ4BHSVy/7CoQXWogsBSTv5MOZnMqwNKw6yt24k2AO/2UpHwjGptimaNLqFfesJbw=="
}, },
"big-integer": { "big-integer": {
"version": "1.6.48", "version": "1.6.48",
"bundled": true "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz",
"integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w=="
}, },
"lodash": { "lodash": {
"version": "4.17.20", "version": "4.17.20",
"bundled": true "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA=="
}, },
"regenerator-runtime": { "regenerator-runtime": {
"version": "0.13.7", "version": "0.13.7",
"bundled": true "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz",
"integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew=="
} }
} }
}, },

View File

@ -8,11 +8,11 @@ import {
} from '@urbit/api'; } from '@urbit/api';
import { makePatDa } from '~/logic/lib/util'; import { makePatDa } from '~/logic/lib/util';
import _ from 'lodash'; import _ from 'lodash';
import { StoreState } from '../store/type';
import { BigIntOrderedMap } from '../lib/BigIntOrderedMap'; import { BigIntOrderedMap } from '../lib/BigIntOrderedMap';
import useHarkState, { HarkState } from '../state/hark'; import useHarkState, { HarkState } from '../state/hark';
import { compose } from 'lodash/fp'; import { compose } from 'lodash/fp';
import { reduceState } from '../state/base'; import { reduceState } from '../state/base';
import bigInt, {BigInteger} from 'big-integer';
export const HarkReducer = (json: any) => { export const HarkReducer = (json: any) => {
const data = _.get(json, 'harkUpdate', false); const data = _.get(json, 'harkUpdate', false);
@ -56,9 +56,24 @@ function reduce(data) {
seenIndex, seenIndex,
removeGraph, removeGraph,
readAll, readAll,
calculateCount
]); ]);
} }
function calculateCount(state: HarkState) {
let count = 0;
_.forEach(state.unreads.graph, (graphs) => {
_.forEach(graphs, graph => {
count += (graph?.notifications || []).length;
});
});
_.forEach(state.unreads.group, group => {
count += (group?.notifications || []).length;
})
state.notificationsCount = count;
return state;
}
function groupInitial(json: any, state: HarkState): HarkState { function groupInitial(json: any, state: HarkState): HarkState {
const data = _.get(json, 'initial', false); const data = _.get(json, 'initial', false);
if (data) { if (data) {
@ -191,8 +206,10 @@ function unreads(json: any, state: HarkState): HarkState {
if(data) { if(data) {
data.forEach(({ index, stats }) => { data.forEach(({ index, stats }) => {
const { unreads, notifications, last } = stats; const { unreads, notifications, last } = stats;
state = updateNotificationStats(state, index, 'notifications', x => x + notifications); updateNotificationStats(state, index, 'last', () => last);
state = updateNotificationStats(state, index, 'last', () => last); _.each(notifications, ({ time, index }) => {
addNotificationToUnread(state, index, makePatDa(time));
});
if('count' in unreads) { if('count' in unreads) {
state = updateUnreadCount(state, index, (u = 0) => u + unreads.count); state = updateUnreadCount(state, index, (u = 0) => u + unreads.count);
} else { } else {
@ -251,18 +268,53 @@ function updateUnreads(state: HarkState, index: NotifIndex, f: (us: Set<string>)
return state; return state;
} }
function updateNotificationStats(state: HarkState, index: NotifIndex, statField: 'notifications' | 'unreads' | 'last', f: (x: number) => number): HarkState { function addNotificationToUnread(state: HarkState, index: NotifIndex, time: BigInteger) {
if(statField === 'notifications') { if('graph' in index) {
state.notificationsCount = f(state.notificationsCount); const path = [index.graph.graph, index.graph.index, 'notifications'];
const curr = _.get(state.unreads.graph, path, []);
_.set(state.unreads.graph, path,
[
...curr.filter(c => !(c.time.eq(time) && notifIdxEqual(c.index, index))),
{ time, index}
]
);
} else if ('group' in index) {
const path = [index.group.group, 'notifications'];
const curr = _.get(state.unreads.group, path, []);
_.set(state.unreads.group, path,
[
...curr.filter(c => !(c.time.eq(time) && notifIdxEqual(c.index, index))),
{ time, index}
]
);
} }
if ('graph' in index) { }
const curr = _.get(state.unreads.graph, [index.graph.graph, index.graph.index, statField], 0);
_.set(state.unreads.graph, [index.graph.graph, index.graph.index, statField], f(curr)); function removeNotificationFromUnread(state: HarkState, index: NotifIndex, time: BigInteger) {
} else if('group' in index) { if('graph' in index) {
const curr = _.get(state.unreads.group, [index.group, statField], 0); const path = [index.graph.graph, index.graph.index, 'notifications'];
_.set(state.unreads.group, [index.group, statField], f(curr)); const curr = _.get(state.unreads.graph, path, []);
_.set(state.unreads.graph, path,
curr.filter(c => !(c.time.eq(time) && notifIdxEqual(c.index, index))),
);
} else if ('group' in index) {
const path = [index.group.group, 'notifications'];
const curr = _.get(state.unreads.group, path, []);
_.set(state.unreads.group, path,
curr.filter(c => !(c.time.eq(time) && notifIdxEqual(c.index, index))),
);
} }
return state; }
function updateNotificationStats(state: HarkState, index: NotifIndex, statField: 'unreads' | 'last', f: (x: number) => number) {
if('graph' in index) {
const curr = _.get(state.unreads.graph, [index.graph.graph, index.graph.index, statField], 0);
_.set(state.unreads.graph, [index.graph.graph, index.graph.index, statField], f(curr));
} 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));
}
} }
function added(json: any, state: HarkState): HarkState { function added(json: any, state: HarkState): HarkState {
@ -271,18 +323,15 @@ function added(json: any, state: HarkState): HarkState {
const { index, notification } = data; const { index, notification } = data;
const time = makePatDa(data.time); const time = makePatDa(data.time);
const timebox = state.notifications.get(time) || []; const timebox = state.notifications.get(time) || [];
addNotificationToUnread(state, index, time);
const arrIdx = timebox.findIndex(idxNotif => const arrIdx = timebox.findIndex(idxNotif =>
notifIdxEqual(index, idxNotif.index) notifIdxEqual(index, idxNotif.index)
); );
if (arrIdx !== -1) { if (arrIdx !== -1) {
if (timebox[arrIdx]?.notification?.read) {
state = updateNotificationStats(state, index, 'notifications', x => x+1);
}
timebox[arrIdx] = { index, notification }; timebox[arrIdx] = { index, notification };
state.notifications.set(time, timebox); state.notifications.set(time, timebox);
} else { } else {
state = updateNotificationStats(state, index, 'notifications', x => x+1);
state.notifications.set(time, [...timebox, { index, notification }]); state.notifications.set(time, [...timebox, { index, notification }]);
} }
} }
@ -361,7 +410,7 @@ function read(json: any, state: HarkState): HarkState {
const data = _.get(json, 'read-note', false); const data = _.get(json, 'read-note', false);
if (data) { if (data) {
const { time, index } = data; const { time, index } = data;
state = updateNotificationStats(state, index, 'notifications', x => x-1); removeNotificationFromUnread(state, index, makePatDa(time));
setRead(time, index, true, state); setRead(time, index, true, state);
} }
return state; return state;
@ -371,7 +420,7 @@ function unread(json: any, state: HarkState): HarkState {
const data = _.get(json, 'unread-note', false); const data = _.get(json, 'unread-note', false);
if (data) { if (data) {
const { time, index } = data; const { time, index } = data;
state = updateNotificationStats(state, index, 'notifications', x => x+1); addNotificationToUnread(state, index, makePatDa(time));
setRead(time, index, false, state); setRead(time, index, false, state);
} }
return state; return state;
@ -381,6 +430,7 @@ function archive(json: any, state: HarkState): HarkState {
const data = _.get(json, 'archive', false); const data = _.get(json, 'archive', false);
if (data) { if (data) {
const { index } = data; const { index } = data;
removeNotificationFromUnread(state, index, makePatDa(data.time))
const time = makePatDa(data.time); const time = makePatDa(data.time);
const timebox = state.notifications.get(time); const timebox = state.notifications.get(time);
if (!timebox) { if (!timebox) {
@ -396,8 +446,6 @@ function archive(json: any, state: HarkState): HarkState {
} else { } else {
state.notifications.set(time, unarchived); state.notifications.set(time, unarchived);
} }
const newlyRead = archived.filter(x => !x.notification.read).length;
state = updateNotificationStats(state, index, 'notifications', x => x - newlyRead);
} }
return state; return state;
} }

View File

@ -1,15 +1,21 @@
import { Post } from "../graph/types"; import { Post } from "../graph/types";
import { GroupUpdate } from "../groups/types"; import { GroupUpdate } from "../groups/types";
import BigIntOrderedMap from "../lib/BigIntOrderedMap"; import BigIntOrderedMap from "../lib/BigIntOrderedMap";
import {BigInteger} from "big-integer";
export type GraphNotifDescription = "link" | "comment" | "note" | "mention" | "message"; export type GraphNotifDescription = "link" | "comment" | "note" | "mention" | "message";
export interface UnreadStats { export interface UnreadStats {
unreads: Set<string> | number; unreads: Set<string> | number;
notifications: number; notifications: NotifRef[];
last: number; last: number;
} }
interface NotifRef {
time: BigInteger;
index: NotifIndex;
}
export interface GraphNotifIndex { export interface GraphNotifIndex {
graph: string; graph: string;
group: string; group: string;