mirror of
https://github.com/ilyakooo0/urbit.git
synced 2024-11-29 12:15:43 +03:00
landscape: update notification reducing for new hark
This commit is contained in:
parent
36a9fceab3
commit
623303c893
@ -1,7 +1,9 @@
|
||||
import {
|
||||
HarkPlace,
|
||||
Timebox,
|
||||
HarkStats
|
||||
HarkStats,
|
||||
harkBinToId,
|
||||
makePatDa
|
||||
} from '@urbit/api';
|
||||
import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
|
||||
import _ from 'lodash';
|
||||
@ -12,7 +14,7 @@ import { HarkState as State } from '../state/hark';
|
||||
type HarkState = State & BaseState<State>;
|
||||
|
||||
function calculateCount(json: any, state: HarkState) {
|
||||
state.notificationsCount = Object.keys(state.unreadNotes).length;
|
||||
state.notificationsCount = Object.keys(state.unseen).length;
|
||||
return state;
|
||||
}
|
||||
|
||||
@ -170,7 +172,8 @@ function allStats(json: any, state: HarkState): HarkState {
|
||||
function clearState(state: HarkState): HarkState {
|
||||
const initialState = {
|
||||
notifications: new BigIntOrderedMap<Timebox>(),
|
||||
archivedNotifications: new BigIntOrderedMap<Timebox>(),
|
||||
unseen: {},
|
||||
seen: {},
|
||||
notificationsGroupConfig: [],
|
||||
notificationsGraphConfig: {
|
||||
watchOnSelf: false,
|
||||
@ -204,6 +207,87 @@ function more(json: any, state: HarkState): HarkState {
|
||||
return state;
|
||||
}
|
||||
|
||||
function added(json: any, state: HarkState): HarkState {
|
||||
if('added' in json) {
|
||||
const { bin } = json.added;
|
||||
const binId = harkBinToId(bin);
|
||||
state.unseen[binId] = json.added;
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
function archived(json: any, state: HarkState): HarkState {
|
||||
if('archived' in json) {
|
||||
const { lid, notification } = json.archived;
|
||||
const seen = 'seen' in lid ? 'seen' : 'unseen';
|
||||
const binId = harkBinToId(notification.bin);
|
||||
delete state[seen][binId];
|
||||
const time = makePatDa(json.archived.time);
|
||||
const timebox = state.archive?.get(time) || {};
|
||||
timebox[binId] = notification;
|
||||
state.archive = state.archive.set(time, timebox);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
function timebox(json: any, state: HarkState): HarkState {
|
||||
if('timebox' in json) {
|
||||
const { timebox } = json;
|
||||
const { lid, notifications } = timebox;
|
||||
if('archive' in lid) {
|
||||
const time = makePatDa(lid.archive);
|
||||
const old = state.archive.get(time) || {};
|
||||
notifications.forEach((note: any) => {
|
||||
const binId = harkBinToId(note.bin);
|
||||
old[binId] = note;
|
||||
});
|
||||
state.archive = state.archive.set(time, old);
|
||||
} else {
|
||||
const seen = 'seen' in lid ? 'seen' : 'unseen';
|
||||
notifications.forEach((note: any) => {
|
||||
const binId = harkBinToId(note.bin);
|
||||
state[seen][binId] = note;
|
||||
});
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
function opened(json: any, state: HarkState): HarkState {
|
||||
if('opened' in json) {
|
||||
const bins = Object.keys(state.unseen);
|
||||
bins.forEach((bin) => {
|
||||
const old = state.seen[bin];
|
||||
const curr = state.unseen[bin];
|
||||
curr.body = [...curr.body, ...(old?.body || [])];
|
||||
state.seen[bin] = curr;
|
||||
delete state.unseen[bin];
|
||||
});
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
function delPlace(json: any, state: HarkState): HarkState {
|
||||
if('del-place' in json) {
|
||||
const { path, desk } = json['del-place'];
|
||||
const pathId = `${desk}${path}`;
|
||||
const wipeBox = (t: Timebox) => {
|
||||
Object.keys(t).forEach((bin) => {
|
||||
if (bin.startsWith(pathId)) {
|
||||
delete t[bin];
|
||||
}
|
||||
});
|
||||
};
|
||||
wipeBox(state.unseen);
|
||||
wipeBox(state.seen);
|
||||
state.archive.keys().forEach((key) => {
|
||||
wipeBox(state.archive.get(key)!);
|
||||
});
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
export function reduce(data, state) {
|
||||
const reducers = [
|
||||
calculateCount,
|
||||
@ -215,7 +299,12 @@ export function reduce(data, state) {
|
||||
unreadSince,
|
||||
unreadEach,
|
||||
seenIndex,
|
||||
readAll
|
||||
readAll,
|
||||
added,
|
||||
timebox,
|
||||
archived,
|
||||
opened,
|
||||
delPlace
|
||||
];
|
||||
const reducer = compose(reducers.map(r => (s) => {
|
||||
return r(data, s);
|
||||
|
@ -2,9 +2,13 @@ import {
|
||||
archive,
|
||||
HarkBin,
|
||||
markCountAsRead,
|
||||
Notification,
|
||||
NotificationGraphConfig,
|
||||
Unreads
|
||||
Unreads,
|
||||
Timebox,
|
||||
HarkLid,
|
||||
harkBinToId,
|
||||
decToUd,
|
||||
unixToDa
|
||||
} from '@urbit/api';
|
||||
import { Poke } from '@urbit/http-api';
|
||||
import { patp2dec } from 'urbit-ob';
|
||||
@ -17,40 +21,31 @@ import {
|
||||
createState,
|
||||
createSubscription,
|
||||
pokeOptimisticallyN,
|
||||
reduceState,
|
||||
reduceStateN
|
||||
} from './base';
|
||||
import { reduce, reduceGraph, reduceGroup } from '../reducers/hark-update';
|
||||
import { BigInteger } from 'big-integer';
|
||||
|
||||
export const HARK_FETCH_MORE_COUNT = 3;
|
||||
|
||||
export interface HarkState {
|
||||
archivedNotifications: BigIntOrderedMap<Notification[]>;
|
||||
archive: BigIntOrderedMap<Timebox>;
|
||||
doNotDisturb: boolean;
|
||||
poke: (poke: Poke<any>) => Promise<void>;
|
||||
getMore: () => Promise<boolean>;
|
||||
getSubset: (
|
||||
offset: number,
|
||||
count: number,
|
||||
isArchive: boolean
|
||||
) => Promise<void>;
|
||||
// getTimeSubset: (start?: Date, end?: Date) => Promise<void>;
|
||||
notifications: BigIntOrderedMap<Notification[]>;
|
||||
unreadNotes: Notification[];
|
||||
unseen: Timebox;
|
||||
seen: Timebox;
|
||||
notificationsCount: number;
|
||||
notificationsGraphConfig: NotificationGraphConfig; // TODO unthread this everywhere
|
||||
notificationsGroupConfig: string[];
|
||||
unreads: Unreads;
|
||||
archive: (bin: HarkBin, time?: BigInteger) => Promise<void>;
|
||||
readNote: (bin: HarkBin) => Promise<void>;
|
||||
readCount: (path: string) => Promise<void>;
|
||||
archiveNote: (bin: HarkBin, lid: HarkLid) => Promise<void>;
|
||||
}
|
||||
|
||||
const useHarkState = createState<HarkState>(
|
||||
'Hark',
|
||||
(set, get) => ({
|
||||
archivedNotifications: new BigIntOrderedMap<Notification[]>(),
|
||||
archive: new BigIntOrderedMap<Timebox>(),
|
||||
doNotDisturb: false,
|
||||
unreadNotes: [],
|
||||
poke: async (poke: Poke<any>) => {
|
||||
@ -60,29 +55,31 @@ const useHarkState = createState<HarkState>(
|
||||
const poke = markCountAsRead({ desk: (window as any).desk, path });
|
||||
await pokeOptimisticallyN(useHarkState, poke, [reduce]);
|
||||
},
|
||||
archive: async (bin: HarkBin, time?: BigInteger) => {
|
||||
const poke = archive(bin, time);
|
||||
await pokeOptimisticallyN(useHarkState, poke, [reduce]);
|
||||
},
|
||||
readNote: async (bin) => {
|
||||
await pokeOptimisticallyN(useHarkState, readNote(bin), [reduce]);
|
||||
archiveNote: async (bin: HarkBin, lid: HarkLid) => {
|
||||
const poke = archive(bin, lid);
|
||||
get().set((draft) => {
|
||||
const key = 'seen' in lid ? 'seen' : 'unseen';
|
||||
const binId = harkBinToId(bin);
|
||||
delete draft[key][binId];
|
||||
});
|
||||
await api.poke(poke);
|
||||
},
|
||||
getMore: async (): Promise<boolean> => {
|
||||
const state = get();
|
||||
const offset = state.notifications.size || 0;
|
||||
await state.getSubset(offset, HARK_FETCH_MORE_COUNT, false);
|
||||
const newState = get();
|
||||
return offset === (newState?.notifications?.size || 0);
|
||||
},
|
||||
getSubset: async (offset, count, isArchive): Promise<void> => {
|
||||
const where = isArchive ? 'archive' : 'inbox';
|
||||
const { harkUpdate } = await api.scry({
|
||||
const oldSize = state.archive?.size || 0;
|
||||
const offset = decToUd(
|
||||
state.archive?.peekSmallest()?.[0].toString()
|
||||
|| unixToDa(Date.now() * 1000).toString()
|
||||
);
|
||||
const update = await api.scry({
|
||||
app: 'hark-store',
|
||||
path: `/recent/${where}/${offset}/${count}`
|
||||
path: `/recent/inbox/${offset}/5`
|
||||
});
|
||||
reduceState(useHarkState, harkUpdate, [reduce]);
|
||||
reduceStateN(useHarkState.getState(), update, [reduce]);
|
||||
return get().archive?.size === oldSize;
|
||||
},
|
||||
notifications: new BigIntOrderedMap<Notification[]>(),
|
||||
unseen: {},
|
||||
seen: {},
|
||||
notificationsCount: 0,
|
||||
notificationsGraphConfig: {
|
||||
watchOnSelf: false,
|
||||
@ -93,9 +90,9 @@ const useHarkState = createState<HarkState>(
|
||||
unreads: {}
|
||||
}),
|
||||
[
|
||||
'unreadNotes',
|
||||
'notifications',
|
||||
'archivedNotifications',
|
||||
'seen',
|
||||
'unseen',
|
||||
'archive',
|
||||
'unreads',
|
||||
'notificationsCount'
|
||||
],
|
||||
|
@ -39,6 +39,7 @@ interface OmniboxResultProps {
|
||||
shiftLink?: string;
|
||||
shiftDescription?: string;
|
||||
description?: string;
|
||||
hasNotifications?: boolean;
|
||||
}
|
||||
|
||||
interface OmniboxResultState {
|
||||
@ -142,14 +143,20 @@ export class OmniboxResult extends Component<OmniboxResultProps, OmniboxResultSt
|
||||
);
|
||||
} else if (icon === 'notifications') {
|
||||
graphic = (
|
||||
<Box mr="2" height="18px" width="18px" position="relative" display="inline-block">
|
||||
<Icon
|
||||
display='inline-block'
|
||||
verticalAlign='middle'
|
||||
icon='Notifications'
|
||||
mr={2}
|
||||
size='18px'
|
||||
color={iconFill}
|
||||
/>
|
||||
{this.props.hasNotifications ? (
|
||||
<Box position="absolute" right="-6px" top="-4px">
|
||||
<Icon icon="Bullet" color={(this.state.hovered || selected === link) ? 'white' : 'blue'} />
|
||||
</Box>
|
||||
) : null}
|
||||
</Box>
|
||||
);
|
||||
} else if (icon === 'messages') {
|
||||
graphic = (
|
||||
|
@ -70,8 +70,6 @@ export const opened = harkAction({
|
||||
opened: null
|
||||
});
|
||||
|
||||
|
||||
|
||||
export const markCountAsRead = (place: HarkPlace): Poke<unknown> =>
|
||||
harkAction({
|
||||
'read-count': place
|
||||
@ -147,3 +145,10 @@ export function harkBinEq(a: HarkBin, b: HarkBin): boolean {
|
||||
a.path === b.path
|
||||
);
|
||||
}
|
||||
|
||||
export function harkLidToId(lid: HarkLid): string {
|
||||
if('time' in lid) {
|
||||
return `archive-${lid.time}`;
|
||||
}
|
||||
return Object.keys(lid)[0];
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user