notifications: revive optimistic updates

This commit is contained in:
Liam Fitzgerald 2021-06-14 10:54:44 +10:00
parent 71ca208829
commit 2d40d0655b
No known key found for this signature in database
GPG Key ID: D390E12C61D1CFFB
4 changed files with 37 additions and 6 deletions

View File

@ -4,6 +4,8 @@ import _ from 'lodash';
import create, { GetState, SetState, UseStore } from 'zustand';
import { persist } from 'zustand/middleware';
import Urbit, { SubscriptionRequestInterface } from '@urbit/http-api';
import { Poke } from '@urbit/api';
import airlock from '~/logic/api';
setAutoFreeze(false);
enablePatches();
@ -155,3 +157,17 @@ export async function doOptimistically<A, S extends {}>(state: UseStore<S & Base
}
}
}
export async function pokeOptimisticallyN<A, S extends {}>(state: UseStore<S & BaseState<S>>, poke: Poke<any>, reduce: ((a: A, fn: S & BaseState<S>) => S & BaseState<S>)[]) {
let num: string | undefined = undefined;
try {
num = optReduceState(state, poke.json, reduce);
await airlock.poke(poke);
state.getState().removePatch(num);
} catch (e) {
console.error(e);
if(num) {
state.getState().rollback(num);
}
}
}

View File

@ -1,5 +1,8 @@
import {
archive,
NotificationGraphConfig,
NotifIndex,
readNote,
Timebox,
Unreads
} from '@urbit/api';
@ -9,8 +12,9 @@ import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
import api from '~/logic/api';
import { useCallback } from 'react';
import { createState, createSubscription, reduceState, reduceStateN } from './base';
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;
@ -26,6 +30,8 @@ export interface HarkState {
notificationsGraphConfig: NotificationGraphConfig; // TODO unthread this everywhere
notificationsGroupConfig: string[];
unreads: Unreads;
archive: (index: NotifIndex, time?: BigInteger) => Promise<void>;
readNote: (index: NotifIndex) => Promise<void>;
}
const useHarkState = createState<HarkState>(
@ -34,6 +40,13 @@ const useHarkState = createState<HarkState>(
archivedNotifications: new BigIntOrderedMap<Timebox>(),
doNotDisturb: false,
unreadNotes: [],
archive: async (index: NotifIndex, time?: BigInteger) => {
const poke = archive(index, time);
await pokeOptimisticallyN(useHarkState, poke, [reduce]);
},
readNote: async (index) => {
await pokeOptimisticallyN(useHarkState, readNote(index), [reduce]);
},
getMore: async (): Promise<boolean> => {
const state = get();
const offset = state.notifications.size || 0;
@ -49,6 +62,7 @@ const useHarkState = createState<HarkState>(
});
reduceState(useHarkState, harkUpdate, [reduce]);
},
notifications: new BigIntOrderedMap<Timebox>(),
notificationsCount: 0,
notificationsGraphConfig: {

View File

@ -1,10 +1,8 @@
import { Box, Button, Icon, Row } from '@tlon/indigo-react';
import {
archive,
GraphNotificationContents,
GroupNotificationContents,
IndexedNotification,
readNote
IndexedNotification
} from '@urbit/api';
import { BigInteger } from 'big-integer';
import React, { ReactNode, useCallback } from 'react';
@ -16,6 +14,8 @@ import { SwipeMenu } from '~/views/components/SwipeMenu';
import { GraphNotification } from './graph';
import { GroupNotification } from './group';
import airlock from '~/logic/api';
import useHarkState from '~/logic/state/hark';
import shallow from 'zustand/shallow';
export interface NotificationProps {
notification: IndexedNotification;
@ -33,12 +33,14 @@ export function NotificationWrapper(props: {
const isMobile = useLocalState(s => s.mobile);
const [archive, readNote] = useHarkState(s => [s.archive, s.readNote], shallow);
const onArchive = useCallback(async (e) => {
e.stopPropagation();
if (!notification) {
return;
}
await airlock.poke(archive(notification.index, time));
await archive(notification.index, time);
}, [time, notification]);
const onClick = (e: any) => {

View File

@ -187,7 +187,6 @@ export class Urbit {
return; // everything's good
} else {
reject();
this.onError && this.onError(response?.statusText || 'Unknown Error');
throw new Error();
}
},