mirror of
https://github.com/urbit/shrub.git
synced 2024-12-19 16:51:42 +03:00
interface: abstracted stores, unified naming
This commit is contained in:
parent
b4fc43a752
commit
bd3e00886c
@ -60,7 +60,6 @@ export default class BaseApi<S extends object = {}> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
scry<T>(app: string, path: Path): Promise<T> {
|
scry<T>(app: string, path: Path): Promise<T> {
|
||||||
console.log(path);
|
|
||||||
return fetch(`/~/scry/${app}${path}.json`).then(r => r.json() as Promise<T>);
|
return fetch(`/~/scry/${app}${path}.json`).then(r => r.json() as Promise<T>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,16 @@
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import f, { memoize } from 'lodash/fp';
|
import f, { compose, memoize } from 'lodash/fp';
|
||||||
import bigInt, { BigInteger } from 'big-integer';
|
import bigInt, { BigInteger } from 'big-integer';
|
||||||
import { Association, Contact } from '@urbit/api';
|
import { Association, Contact } from '@urbit/api';
|
||||||
import useLocalState from '../state/local';
|
import useLocalState from '../state/local';
|
||||||
import produce from 'immer';
|
import produce, { enableMapSet } from 'immer';
|
||||||
import useSettingsState from '../state/settings';
|
import useSettingsState from '../state/settings';
|
||||||
|
import { State, UseStore } from 'zustand';
|
||||||
|
import { Cage } from '~/types/cage';
|
||||||
|
import { BaseState } from '../state/base';
|
||||||
|
|
||||||
|
enableMapSet();
|
||||||
|
|
||||||
export const MOBILE_BROWSER_REGEX = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i;
|
export const MOBILE_BROWSER_REGEX = /Android|webOS|iPhone|iPad|iPod|BlackBerry/i;
|
||||||
|
|
||||||
@ -411,7 +416,43 @@ export function getItemTitle(association: Association) {
|
|||||||
return association.metadata.title || association.resource;
|
return association.metadata.title || association.resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const stateSetter = <StateType>(fn: (state: StateType) => void, set): void => {
|
export const stateSetter = <StateType>(
|
||||||
// TODO this is a stub for the store debugging
|
fn: (state: StateType) => void,
|
||||||
|
set
|
||||||
|
): void => {
|
||||||
|
// fn = (state: StateType) => {
|
||||||
|
// // TODO this is a stub for the store debugging
|
||||||
|
// fn(state);
|
||||||
|
// }
|
||||||
|
return set(fn);
|
||||||
|
// TODO we want to use the below, but it makes everything read-only
|
||||||
return set(produce(fn));
|
return set(produce(fn));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const reduceState = <
|
||||||
|
StateType extends BaseState<StateType>,
|
||||||
|
UpdateType
|
||||||
|
>(
|
||||||
|
state: UseStore<StateType>,
|
||||||
|
data: UpdateType,
|
||||||
|
reducers: ((data: UpdateType, state: StateType) => StateType)[]
|
||||||
|
): void => {
|
||||||
|
const oldState = state.getState();
|
||||||
|
const reducer = compose(reducers.map(reducer => reducer.bind(reducer, data)));
|
||||||
|
const newState = reducer(oldState);
|
||||||
|
state.getState().set(state => state = newState);
|
||||||
|
};
|
||||||
|
|
||||||
|
export let stateStorageKeys: string[] = [];
|
||||||
|
|
||||||
|
export const stateStorageKey = (stateName: string) => {
|
||||||
|
stateName = `Landcape${stateName}State`;
|
||||||
|
stateStorageKeys = [...new Set([...stateStorageKeys, stateName])];
|
||||||
|
return stateName;
|
||||||
|
};
|
||||||
|
|
||||||
|
(window as any).clearStates = () => {
|
||||||
|
stateStorageKeys.forEach(key => {
|
||||||
|
localStorage.removeItem(key);
|
||||||
|
});
|
||||||
|
}
|
23
pkg/interface/src/logic/lib/withState.tsx
Normal file
23
pkg/interface/src/logic/lib/withState.tsx
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { ReactElement } from "react";
|
||||||
|
import { UseStore } from "zustand";
|
||||||
|
import { BaseState } from "../state/base";
|
||||||
|
|
||||||
|
const withState = <
|
||||||
|
StateType extends BaseState<any>
|
||||||
|
>(
|
||||||
|
useState: UseStore<StateType>,
|
||||||
|
Component: any,
|
||||||
|
stateMemberKeys?: (keyof StateType)[]
|
||||||
|
) => {
|
||||||
|
return React.forwardRef((props, ref) => {
|
||||||
|
const state = stateMemberKeys ? useState(
|
||||||
|
state => stateMemberKeys.reduce(
|
||||||
|
(object, key) => ({ ...object, [key]: state[key] }), {}
|
||||||
|
)
|
||||||
|
) : useState();
|
||||||
|
return <Component ref={ref} {...state} {...props} />
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
export default withState;
|
@ -3,22 +3,20 @@ import { compose } from 'lodash/fp';
|
|||||||
|
|
||||||
import { ContactUpdate } from '@urbit/api';
|
import { ContactUpdate } from '@urbit/api';
|
||||||
|
|
||||||
import useContactState, { ContactState } from '../state/contacts';
|
import useContactState, { ContactState } from '../state/contact';
|
||||||
|
import { reduceState } from '../lib/util';
|
||||||
|
|
||||||
|
|
||||||
export const ContactReducer = (json) => {
|
export const ContactReducer = (json) => {
|
||||||
const data: ContactUpdate = _.get(json, 'contact-update', false);
|
const data: ContactUpdate = _.get(json, 'contact-update', false);
|
||||||
if (data) {
|
if (data) {
|
||||||
useContactState.setState(
|
reduceState<ContactState, ContactUpdate>(useContactState, data, [
|
||||||
compose([
|
initial,
|
||||||
initial,
|
add,
|
||||||
add,
|
remove,
|
||||||
remove,
|
edit,
|
||||||
edit,
|
setPublic
|
||||||
setPublic
|
]);
|
||||||
].map(reducer => reducer.bind(reducer, data))
|
|
||||||
)(useContactState.getState())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: better isolation
|
// TODO: better isolation
|
||||||
|
@ -3,20 +3,18 @@ import { BigIntOrderedMap } from "~/logic/lib/BigIntOrderedMap";
|
|||||||
import bigInt, { BigInteger } from "big-integer";
|
import bigInt, { BigInteger } from "big-integer";
|
||||||
import useGraphState, { GraphState } from '../state/graph';
|
import useGraphState, { GraphState } from '../state/graph';
|
||||||
import { compose } from 'lodash/fp';
|
import { compose } from 'lodash/fp';
|
||||||
|
import { reduceState } from '../lib/util';
|
||||||
|
|
||||||
export const GraphReducer = (json) => {
|
export const GraphReducer = (json) => {
|
||||||
const data = _.get(json, 'graph-update', false);
|
const data = _.get(json, 'graph-update', false);
|
||||||
if (data) {
|
if (data) {
|
||||||
useGraphState.setState(
|
reduceState<GraphState, any>(useGraphState, data, [
|
||||||
compose([
|
keys,
|
||||||
keys,
|
addGraph,
|
||||||
addGraph,
|
removeGraph,
|
||||||
removeGraph,
|
addNodes,
|
||||||
addNodes,
|
removeNodes
|
||||||
removeNodes
|
]);
|
||||||
].map(reducer => reducer.bind(reducer, data))
|
|
||||||
)(useGraphState.getState())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -13,8 +13,8 @@ import {
|
|||||||
InvitePolicy
|
InvitePolicy
|
||||||
} from '@urbit/api/groups';
|
} from '@urbit/api/groups';
|
||||||
import { Enc, PatpNoSig } from '@urbit/api';
|
import { Enc, PatpNoSig } from '@urbit/api';
|
||||||
import { resourceAsPath } from '../lib/util';
|
import { reduceState, resourceAsPath } from '../lib/util';
|
||||||
import useGroupState, { GroupState } from '../state/groups';
|
import useGroupState, { GroupState } from '../state/group';
|
||||||
import { compose } from 'lodash/fp';
|
import { compose } from 'lodash/fp';
|
||||||
|
|
||||||
function decodeGroup(group: Enc<Group>): Group {
|
function decodeGroup(group: Enc<Group>): Group {
|
||||||
@ -61,22 +61,18 @@ export default class GroupReducer {
|
|||||||
reduce(json: Cage) {
|
reduce(json: Cage) {
|
||||||
const data = json.groupUpdate;
|
const data = json.groupUpdate;
|
||||||
if (data) {
|
if (data) {
|
||||||
useGroupState.setState(
|
reduceState<GroupState, GroupUpdate>(useGroupState, data, [
|
||||||
compose([
|
initial,
|
||||||
initial,
|
addMembers,
|
||||||
addMembers,
|
addTag,
|
||||||
addTag,
|
removeMembers,
|
||||||
removeMembers,
|
initialGroup,
|
||||||
initialGroup,
|
removeTag,
|
||||||
removeTag,
|
addGroup,
|
||||||
initial,
|
removeGroup,
|
||||||
addGroup,
|
changePolicy,
|
||||||
removeGroup,
|
expose,
|
||||||
changePolicy,
|
]);
|
||||||
expose,
|
|
||||||
].map(reducer => reducer.bind(reducer, data))
|
|
||||||
)(useGroupState.getState())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,9 +80,7 @@ export default class GroupReducer {
|
|||||||
const initial = (json: GroupUpdate, state: GroupState): GroupState => {
|
const initial = (json: GroupUpdate, state: GroupState): GroupState => {
|
||||||
const data = json['initial'];
|
const data = json['initial'];
|
||||||
if (data) {
|
if (data) {
|
||||||
state.set(st => {
|
state.groups = _.mapValues(data, decodeGroup);
|
||||||
st.groups = _.mapValues(data, decodeGroup);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
@ -148,6 +142,7 @@ const removeMembers = (json: GroupUpdate, state: GroupState): GroupState => {
|
|||||||
state.groups[resourcePath].members.delete(member);
|
state.groups[resourcePath].members.delete(member);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
const addTag = (json: GroupUpdate, state: GroupState): GroupState => {
|
const addTag = (json: GroupUpdate, state: GroupState): GroupState => {
|
||||||
|
@ -6,7 +6,7 @@ import {
|
|||||||
UnreadStats,
|
UnreadStats,
|
||||||
Timebox
|
Timebox
|
||||||
} from '@urbit/api';
|
} from '@urbit/api';
|
||||||
import { makePatDa } from '~/logic/lib/util';
|
import { makePatDa, reduceState } from '~/logic/lib/util';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { StoreState } from '../store/type';
|
import { StoreState } from '../store/type';
|
||||||
import { BigIntOrderedMap } from '../lib/BigIntOrderedMap';
|
import { BigIntOrderedMap } from '../lib/BigIntOrderedMap';
|
||||||
@ -20,30 +20,44 @@ export const HarkReducer = (json: any) => {
|
|||||||
}
|
}
|
||||||
const graphHookData = _.get(json, 'hark-graph-hook-update', false);
|
const graphHookData = _.get(json, 'hark-graph-hook-update', false);
|
||||||
if (graphHookData) {
|
if (graphHookData) {
|
||||||
useHarkState.setState(
|
reduceState<HarkState, any>(useHarkState, graphHookData, [
|
||||||
compose([
|
graphInitial,
|
||||||
graphInitial,
|
graphIgnore,
|
||||||
graphIgnore,
|
graphListen,
|
||||||
graphListen,
|
graphWatchSelf,
|
||||||
graphWatchSelf,
|
graphMentions,
|
||||||
graphMentions,
|
]);
|
||||||
].map(reducer => reducer.bind(reducer, graphHookData))
|
|
||||||
)(useHarkState.getState())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
const groupHookData = _.get(json, 'hark-group-hook-update', false);
|
const groupHookData = _.get(json, 'hark-group-hook-update', false);
|
||||||
if (groupHookData) {
|
if (groupHookData) {
|
||||||
useHarkState.setState(
|
reduceState<HarkState, any>(useHarkState, groupHookData, [
|
||||||
compose([
|
groupInitial,
|
||||||
groupInitial,
|
groupListen,
|
||||||
groupListen,
|
groupIgnore,
|
||||||
groupIgnore,
|
]);
|
||||||
].map(reducer => reducer.bind(reducer, groupHookData))
|
|
||||||
)(useHarkState.getState())
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function reduce(data) {
|
||||||
|
reduceState<HarkState, any>(useHarkState, data, [
|
||||||
|
unread,
|
||||||
|
read,
|
||||||
|
archive,
|
||||||
|
timebox,
|
||||||
|
more,
|
||||||
|
dnd,
|
||||||
|
added,
|
||||||
|
unreads,
|
||||||
|
readEach,
|
||||||
|
readSince,
|
||||||
|
unreadSince,
|
||||||
|
unreadEach,
|
||||||
|
seenIndex,
|
||||||
|
removeGraph,
|
||||||
|
readAll,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
||||||
@ -115,29 +129,6 @@ function graphWatchSelf(json: any, state: HarkState): HarkState {
|
|||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
function reduce(data: any) {
|
|
||||||
useHarkState.setState(
|
|
||||||
compose([
|
|
||||||
unread,
|
|
||||||
read,
|
|
||||||
archive,
|
|
||||||
timebox,
|
|
||||||
more,
|
|
||||||
dnd,
|
|
||||||
added,
|
|
||||||
unreads,
|
|
||||||
readEach,
|
|
||||||
readSince,
|
|
||||||
unreadSince,
|
|
||||||
unreadEach,
|
|
||||||
seenIndex,
|
|
||||||
removeGraph,
|
|
||||||
readAll,
|
|
||||||
].map(reducer => reducer.bind(reducer, data))
|
|
||||||
)(useHarkState.getState())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function readAll(json: any, state: HarkState): HarkState {
|
function readAll(json: any, state: HarkState): HarkState {
|
||||||
const data = _.get(json, 'read-all');
|
const data = _.get(json, 'read-all');
|
||||||
if(data) {
|
if(data) {
|
||||||
@ -197,7 +188,6 @@ function unreadEach(json: any, state: HarkState): HarkState {
|
|||||||
function unreads(json: any, state: HarkState): HarkState {
|
function unreads(json: any, state: HarkState): HarkState {
|
||||||
const data = _.get(json, 'unreads');
|
const data = _.get(json, 'unreads');
|
||||||
if(data) {
|
if(data) {
|
||||||
clearState(state);
|
|
||||||
data.forEach(({ index, stats }) => {
|
data.forEach(({ index, stats }) => {
|
||||||
const { unreads, notifications, last } = stats;
|
const { unreads, notifications, last } = stats;
|
||||||
updateNotificationStats(state, index, 'notifications', x => x + notifications);
|
updateNotificationStats(state, index, 'notifications', x => x + notifications);
|
||||||
@ -236,38 +226,41 @@ function clearState(state: HarkState) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateUnreadCount(state: HarkState, index: NotifIndex, count: (c: number) => number) {
|
function updateUnreadCount(state: HarkState, index: NotifIndex, count: (c: number) => number): HarkState {
|
||||||
if(!('graph' in index)) {
|
if(!('graph' in index)) {
|
||||||
return;
|
return state;
|
||||||
}
|
}
|
||||||
const property = [index.graph.graph, index.graph.index, 'unreads'];
|
const property = [index.graph.graph, index.graph.index, 'unreads'];
|
||||||
const curr = _.get(state.unreads.graph, property, 0);
|
const curr = _.get(state.unreads.graph, property, 0);
|
||||||
const newCount = count(curr);
|
const newCount = count(curr);
|
||||||
_.set(state.unreads.graph, property, newCount);
|
_.set(state.unreads.graph, property, newCount);
|
||||||
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateUnreads(state: HarkState, index: NotifIndex, f: (us: Set<string>) => void) {
|
function updateUnreads(state: HarkState, index: NotifIndex, f: (us: Set<string>) => void): HarkState {
|
||||||
if(!('graph' in index)) {
|
if(!('graph' in index)) {
|
||||||
return;
|
return state;
|
||||||
}
|
}
|
||||||
const unreads = _.get(state.unreads.graph, [index.graph.graph, index.graph.index, 'unreads'], new Set<string>());
|
const unreads = _.get(state.unreads.graph, [index.graph.graph, index.graph.index, 'unreads'], new Set<string>());
|
||||||
const oldSize = unreads.size;
|
const oldSize = unreads.size;
|
||||||
f(unreads);
|
f(unreads);
|
||||||
const newSize = unreads.size;
|
const newSize = unreads.size;
|
||||||
_.set(state.unreads.graph, [index.graph.graph, index.graph.index, 'unreads'], unreads);
|
_.set(state.unreads.graph, [index.graph.graph, index.graph.index, 'unreads'], unreads);
|
||||||
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateNotificationStats(state: HarkState, index: NotifIndex, statField: 'notifications' | 'unreads' | 'last', f: (x: number) => number) {
|
function updateNotificationStats(state: HarkState, index: NotifIndex, statField: 'notifications' | 'unreads' | 'last', f: (x: number) => number): HarkState {
|
||||||
if(statField === 'notifications') {
|
if(statField === 'notifications') {
|
||||||
state.notificationsCount = f(state.notificationsCount);
|
state.notificationsCount = f(state.notificationsCount);
|
||||||
}
|
}
|
||||||
if('graph' in index) {
|
if('graph' in index) {
|
||||||
const curr = _.get(state.unreads.graph, [index.graph.graph, index.graph.index, statField], 0);
|
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));
|
_.set(state.unreads.graph, [index.graph.graph, index.graph.index, statField], f(curr));
|
||||||
} else if('group' in index) {
|
} else if('group' in index) {
|
||||||
const curr = _.get(state.unreads.group, [index.group, statField], 0);
|
const curr = _.get(state.unreads.group, [index.group, statField], 0);
|
||||||
_.set(state.unreads.group, [index.group, statField], f(curr));
|
_.set(state.unreads.group, [index.group, statField], f(curr));
|
||||||
}
|
}
|
||||||
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
function added(json: any, state: HarkState): HarkState {
|
function added(json: any, state: HarkState): HarkState {
|
||||||
@ -281,13 +274,14 @@ function added(json: any, state: HarkState): HarkState {
|
|||||||
notifIdxEqual(index, idxNotif.index)
|
notifIdxEqual(index, idxNotif.index)
|
||||||
);
|
);
|
||||||
if (arrIdx !== -1) {
|
if (arrIdx !== -1) {
|
||||||
if(timebox[arrIdx]?.notification?.read) {
|
if (timebox[arrIdx]?.notification?.read) {
|
||||||
updateNotificationStats(state, index, 'notifications', x => x+1);
|
// TODO this is additive, and with a persistent state it keeps incrementing
|
||||||
|
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 {
|
||||||
updateNotificationStats(state, index, 'notifications', x => x+1);
|
state = updateNotificationStats(state, index, 'notifications', x => x+1);
|
||||||
state.notifications.set(time, [...timebox, { index, notification }]);
|
state.notifications.set(time, [...timebox, { index, notification }]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -316,7 +310,7 @@ const timebox = (json: any, state: HarkState): HarkState => {
|
|||||||
function more(json: any, state: HarkState): HarkState {
|
function more(json: any, state: HarkState): HarkState {
|
||||||
const data = _.get(json, 'more', false);
|
const data = _.get(json, 'more', false);
|
||||||
if (data) {
|
if (data) {
|
||||||
_.forEach(data, d => reduce(d, state));
|
_.forEach(data, d => reduce(d));
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
@ -5,22 +5,20 @@ import { InviteUpdate } from '@urbit/api/invite';
|
|||||||
|
|
||||||
import { Cage } from '~/types/cage';
|
import { Cage } from '~/types/cage';
|
||||||
import useInviteState, { InviteState } from '../state/invite';
|
import useInviteState, { InviteState } from '../state/invite';
|
||||||
|
import { reduceState } from '../lib/util';
|
||||||
|
|
||||||
export default class InviteReducer {
|
export default class InviteReducer {
|
||||||
reduce(json: Cage) {
|
reduce(json: Cage) {
|
||||||
const data = json['invite-update'];
|
const data = json['invite-update'];
|
||||||
if (data) {
|
if (data) {
|
||||||
useInviteState.setState(
|
reduceState<InviteState, InviteUpdate>(useInviteState, data, [
|
||||||
compose([
|
initial,
|
||||||
initial,
|
create,
|
||||||
create,
|
deleteInvite,
|
||||||
deleteInvite,
|
invite,
|
||||||
invite,
|
accepted,
|
||||||
accepted,
|
decline,
|
||||||
decline,
|
]);
|
||||||
].map(reducer => reducer.bind(reducer, data))
|
|
||||||
)(useInviteState.getState())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,31 +3,33 @@ import { LaunchState, LaunchUpdate, WeatherState } from '~/types/launch-update';
|
|||||||
import { Cage } from '~/types/cage';
|
import { Cage } from '~/types/cage';
|
||||||
import useLaunchState from '../state/launch';
|
import useLaunchState from '../state/launch';
|
||||||
import { compose } from 'lodash/fp';
|
import { compose } from 'lodash/fp';
|
||||||
|
import { reduceState } from '../lib/util';
|
||||||
|
|
||||||
export default class LaunchReducer {
|
export default class LaunchReducer {
|
||||||
reduce(json: Cage) {
|
reduce(json: Cage) {
|
||||||
const data = _.get(json, 'launch-update', false);
|
const data = _.get(json, 'launch-update', false);
|
||||||
if (data) {
|
if (data) {
|
||||||
useLaunchState.setState(
|
reduceState<LaunchState, LaunchUpdate>(useLaunchState, data, [
|
||||||
compose([
|
initial,
|
||||||
initial,
|
changeFirstTime,
|
||||||
changeFirstTime,
|
changeOrder,
|
||||||
changeOrder,
|
changeFirstTime,
|
||||||
changeFirstTime,
|
changeIsShown,
|
||||||
changeIsShown,
|
]);
|
||||||
].map(reducer => reducer.bind(reducer, data))
|
|
||||||
)(useLaunchState.getState())
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const weatherData: WeatherState = _.get(json, 'weather', false);
|
const weatherData: WeatherState = _.get(json, 'weather', false);
|
||||||
if (weatherData) {
|
if (weatherData) {
|
||||||
useLaunchState.setState({ weather: weatherData });
|
useLaunchState.getState().set(state => {
|
||||||
|
state.weather = weatherData;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const locationData = _.get(json, 'location', false);
|
const locationData = _.get(json, 'location', false);
|
||||||
if (locationData) {
|
if (locationData) {
|
||||||
useLaunchState.setState({ userLocation: locationData });
|
useLaunchState.getState().set(state => {
|
||||||
|
state.userLocation = locationData;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,28 +5,25 @@ import { MetadataUpdate } from '@urbit/api/metadata';
|
|||||||
|
|
||||||
import { Cage } from '~/types/cage';
|
import { Cage } from '~/types/cage';
|
||||||
import useMetadataState, { MetadataState } from '../state/metadata';
|
import useMetadataState, { MetadataState } from '../state/metadata';
|
||||||
|
import { reduceState } from '../lib/util';
|
||||||
|
|
||||||
export default class MetadataReducer {
|
export default class MetadataReducer {
|
||||||
reduce(json: Cage) {
|
reduce(json: Cage) {
|
||||||
const data = json['metadata-update'];
|
const data = json['metadata-update'];
|
||||||
if (data) {
|
if (data) {
|
||||||
useMetadataState.setState(
|
reduceState<MetadataState, MetadataUpdate>(useMetadataState, data, [
|
||||||
compose([
|
associations,
|
||||||
associations,
|
add,
|
||||||
add,
|
update,
|
||||||
update,
|
remove,
|
||||||
remove,
|
groupInitial,
|
||||||
groupInitial,
|
]);
|
||||||
].map(reducer => reducer.bind(reducer, data))
|
|
||||||
)(useMetadataState.getState())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const groupInitial = (json: MetadataUpdate, state: MetadataState): MetadataState => {
|
const groupInitial = (json: MetadataUpdate, state: MetadataState): MetadataState => {
|
||||||
const data = _.get(json, 'initial-group', false);
|
const data = _.get(json, 'initial-group', false);
|
||||||
console.log(data);
|
|
||||||
if(data) {
|
if(data) {
|
||||||
state = associations(data, state);
|
state = associations(data, state);
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ import _ from 'lodash';
|
|||||||
import { compose } from 'lodash/fp';
|
import { compose } from 'lodash/fp';
|
||||||
import { Cage } from '~/types/cage';
|
import { Cage } from '~/types/cage';
|
||||||
import { S3Update } from '~/types/s3-update';
|
import { S3Update } from '~/types/s3-update';
|
||||||
|
import { reduceState } from '../lib/util';
|
||||||
import useS3State, { S3State } from '../state/s3';
|
import useS3State, { S3State } from '../state/s3';
|
||||||
|
|
||||||
|
|
||||||
@ -9,19 +10,16 @@ export default class S3Reducer {
|
|||||||
reduce(json: Cage) {
|
reduce(json: Cage) {
|
||||||
const data = _.get(json, 's3-update', false);
|
const data = _.get(json, 's3-update', false);
|
||||||
if (data) {
|
if (data) {
|
||||||
useS3State.setState(
|
reduceState<S3State, S3Update>(useS3State, data, [
|
||||||
compose([
|
credentials,
|
||||||
credentials,
|
configuration,
|
||||||
configuration,
|
currentBucket,
|
||||||
currentBucket,
|
addBucket,
|
||||||
addBucket,
|
removeBucket,
|
||||||
removeBucket,
|
endpoint,
|
||||||
endpoint,
|
accessKeyId,
|
||||||
accessKeyId,
|
secretAccessKey,
|
||||||
secretAccessKey,
|
]);
|
||||||
].map(reducer => reducer.bind(reducer, data))
|
|
||||||
)(useS3State.getState())
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
21
pkg/interface/src/logic/state/base.ts
Normal file
21
pkg/interface/src/logic/state/base.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import create, { State, UseStore } from "zustand";
|
||||||
|
import { persist } from "zustand/middleware";
|
||||||
|
import { stateSetter, stateStorageKey } from "../lib/util";
|
||||||
|
|
||||||
|
export interface BaseState<StateType> extends State {
|
||||||
|
set: (fn: (state: StateType) => void) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createState = <StateType extends BaseState<any>>(
|
||||||
|
name: string,
|
||||||
|
properties: Omit<StateType, 'set'>,
|
||||||
|
blacklist: string[] = []
|
||||||
|
): UseStore<StateType> => create(persist((set, get) => ({
|
||||||
|
// TODO why does this typing break?
|
||||||
|
set: fn => stateSetter(fn, set),
|
||||||
|
...properties
|
||||||
|
}), {
|
||||||
|
blacklist,
|
||||||
|
name: stateStorageKey(name),
|
||||||
|
version: 1, // TODO version these according to base hash
|
||||||
|
}));
|
31
pkg/interface/src/logic/state/contact.ts
Normal file
31
pkg/interface/src/logic/state/contact.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { Patp, Rolodex, Scry } from "@urbit/api";
|
||||||
|
|
||||||
|
import { BaseState, createState } from "./base";
|
||||||
|
|
||||||
|
export interface ContactState extends BaseState<ContactState> {
|
||||||
|
contacts: Rolodex;
|
||||||
|
isContactPublic: boolean;
|
||||||
|
nackedContacts: Set<Patp>;
|
||||||
|
// fetchIsAllowed: (entity, name, ship, personal) => Promise<boolean>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const useContactState = createState<ContactState>('Contact', {
|
||||||
|
contacts: {},
|
||||||
|
nackedContacts: new Set(),
|
||||||
|
isContactPublic: false,
|
||||||
|
// fetchIsAllowed: async (
|
||||||
|
// entity,
|
||||||
|
// name,
|
||||||
|
// ship,
|
||||||
|
// personal
|
||||||
|
// ): Promise<boolean> => {
|
||||||
|
// const isPersonal = personal ? 'true' : 'false';
|
||||||
|
// const api = useApi();
|
||||||
|
// return api.scry({
|
||||||
|
// app: 'contact-store',
|
||||||
|
// path: `/is-allowed/${entity}/${name}/${ship}/${isPersonal}`
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
}, ['nackedContacts']);
|
||||||
|
|
||||||
|
export default useContactState;
|
@ -1,52 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import create, { State } from 'zustand';
|
|
||||||
import { persist } from 'zustand/middleware';
|
|
||||||
|
|
||||||
import { Patp, Rolodex, Scry } from "@urbit/api";
|
|
||||||
|
|
||||||
import { stateSetter } from "~/logic/lib/util";
|
|
||||||
// import useApi from "~/logic/lib/useApi";
|
|
||||||
|
|
||||||
export interface ContactState extends State {
|
|
||||||
contacts: Rolodex;
|
|
||||||
isContactPublic: boolean;
|
|
||||||
nackedContacts: Set<Patp>;
|
|
||||||
// fetchIsAllowed: (entity, name, ship, personal) => Promise<boolean>;
|
|
||||||
set: (fn: (state: ContactState) => void) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
const useContactState = create<ContactState>(persist((set, get) => ({
|
|
||||||
contacts: {},
|
|
||||||
nackedContacts: new Set(),
|
|
||||||
isContactPublic: false,
|
|
||||||
// fetchIsAllowed: async (
|
|
||||||
// entity,
|
|
||||||
// name,
|
|
||||||
// ship,
|
|
||||||
// personal
|
|
||||||
// ): Promise<boolean> => {
|
|
||||||
// const isPersonal = personal ? 'true' : 'false';
|
|
||||||
// const api = useApi();
|
|
||||||
// return api.scry({
|
|
||||||
// app: 'contact-store',
|
|
||||||
// path: `/is-allowed/${entity}/${name}/${ship}/${isPersonal}`
|
|
||||||
// });
|
|
||||||
// },
|
|
||||||
set: fn => stateSetter(fn, set)
|
|
||||||
}), {
|
|
||||||
blacklist: ['nackedContacts'],
|
|
||||||
name: 'LandscapeContactState'
|
|
||||||
}));
|
|
||||||
|
|
||||||
function withContactState<P, S extends keyof ContactState>(Component: any, stateMemberKeys?: S[]) {
|
|
||||||
return React.forwardRef((props: Omit<P, S>, ref) => {
|
|
||||||
const contactState = stateMemberKeys ? useContactState(
|
|
||||||
state => stateMemberKeys.reduce(
|
|
||||||
(object, key) => ({ ...object, [key]: state[key] }), {}
|
|
||||||
)
|
|
||||||
): useContactState();
|
|
||||||
return <Component ref={ref} {...contactState} {...props} />
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export { useContactState as default, withContactState };
|
|
@ -1,13 +1,8 @@
|
|||||||
import { Graphs, decToUd, numToUd } from "@urbit/api";
|
import { Graphs, decToUd, numToUd } from "@urbit/api";
|
||||||
import React from "react";
|
|
||||||
import create, { State } from "zustand";
|
|
||||||
import { persist } from "zustand/middleware";
|
|
||||||
|
|
||||||
// import useApi from "~/logic/lib/useApi";
|
import { BaseState, createState } from "./base";
|
||||||
import { stateSetter } from "~/logic/lib/util";
|
|
||||||
// import { graphReducer } from "~/logic/subscription/graph";
|
|
||||||
|
|
||||||
export interface GraphState extends State {
|
export interface GraphState extends BaseState<GraphState> {
|
||||||
graphs: Graphs;
|
graphs: Graphs;
|
||||||
graphKeys: Set<string>;
|
graphKeys: Set<string>;
|
||||||
// getKeys: () => Promise<void>;
|
// getKeys: () => Promise<void>;
|
||||||
@ -19,10 +14,9 @@ export interface GraphState extends State {
|
|||||||
// getYoungerSiblings: (ship: string, resource: string, count: number, index?: string) => Promise<void>;
|
// getYoungerSiblings: (ship: string, resource: string, count: number, index?: string) => Promise<void>;
|
||||||
// getGraphSubset: (ship: string, resource: string, start: string, end: string) => Promise<void>;
|
// getGraphSubset: (ship: string, resource: string, start: string, end: string) => Promise<void>;
|
||||||
// getNode: (ship: string, resource: string, index: string) => Promise<void>;
|
// getNode: (ship: string, resource: string, index: string) => Promise<void>;
|
||||||
set: (fn: (state: GraphState) => void) => void;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const useGraphState = create<GraphState>(persist((set, get) => ({
|
const useGraphState = createState<GraphState>('Graph', {
|
||||||
graphs: {},
|
graphs: {},
|
||||||
graphKeys: new Set(),
|
graphKeys: new Set(),
|
||||||
// getKeys: async () => {
|
// getKeys: async () => {
|
||||||
@ -124,21 +118,6 @@ const useGraphState = create<GraphState>(persist((set, get) => ({
|
|||||||
// });
|
// });
|
||||||
// graphReducer(node);
|
// graphReducer(node);
|
||||||
// },
|
// },
|
||||||
set: fn => stateSetter(fn, set)
|
}, ['graphs', 'graphKeys']);
|
||||||
}), {
|
|
||||||
blacklist: ['graphKeys', 'graphs'],
|
|
||||||
name: 'LandscapeGraphState'
|
|
||||||
}));
|
|
||||||
|
|
||||||
function withGraphState<P, S extends keyof GraphState>(Component: any, stateMemberKeys?: S[]) {
|
export default useGraphState;
|
||||||
return React.forwardRef((props: Omit<P, S>, ref) => {
|
|
||||||
const graphState = stateMemberKeys ? useGraphState(
|
|
||||||
state => stateMemberKeys.reduce(
|
|
||||||
(object, key) => ({ ...object, [key]: state[key] }), {}
|
|
||||||
)
|
|
||||||
): useGraphState();
|
|
||||||
return <Component ref={ref} {...graphState} {...props} />
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export { useGraphState as default, withGraphState };
|
|
15
pkg/interface/src/logic/state/group.ts
Normal file
15
pkg/interface/src/logic/state/group.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import { Path, JoinRequests } from "@urbit/api";
|
||||||
|
|
||||||
|
import { BaseState, createState } from "./base";
|
||||||
|
|
||||||
|
export interface GroupState extends BaseState<GroupState> {
|
||||||
|
groups: Set<Path>;
|
||||||
|
pendingJoin: JoinRequests;
|
||||||
|
};
|
||||||
|
|
||||||
|
const useGroupState = createState<GroupState>('Group', {
|
||||||
|
groups: new Set(),
|
||||||
|
pendingJoin: {},
|
||||||
|
}, ['groups']);
|
||||||
|
|
||||||
|
export default useGroupState;
|
@ -1,36 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import create, { State } from 'zustand';
|
|
||||||
import { persist } from 'zustand/middleware';
|
|
||||||
|
|
||||||
import { JoinRequests } from '@urbit/api/groups';
|
|
||||||
import { Path } from "@urbit/api";
|
|
||||||
|
|
||||||
import { stateSetter } from "~/logic/lib/util";
|
|
||||||
|
|
||||||
export interface GroupState extends State {
|
|
||||||
groups: Set<Path>;
|
|
||||||
pendingJoin: JoinRequests;
|
|
||||||
set: (fn: (state: GroupState) => void) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
const useGroupState = create<GroupState>(persist((set, get) => ({
|
|
||||||
groups: new Set(),
|
|
||||||
pendingJoin: {},
|
|
||||||
set: fn => stateSetter(fn, set)
|
|
||||||
}), {
|
|
||||||
blacklist: ['groups'],
|
|
||||||
name: 'LandscapeGroupState'
|
|
||||||
}));
|
|
||||||
|
|
||||||
function withGroupState<P, S extends keyof GroupState>(Component: any, stateMemberKeys?: S[]) {
|
|
||||||
return React.forwardRef((props: Omit<P, S>, ref) => {
|
|
||||||
const groupState = stateMemberKeys ? useGroupState(
|
|
||||||
state => stateMemberKeys.reduce(
|
|
||||||
(object, key) => ({ ...object, [key]: state[key] }), {}
|
|
||||||
)
|
|
||||||
): useGroupState();
|
|
||||||
return <Component ref={ref} {...groupState} {...props} />
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export { useGroupState as default, withGroupState };
|
|
@ -1,17 +1,12 @@
|
|||||||
import React from "react";
|
|
||||||
import create, { State } from 'zustand';
|
|
||||||
import { persist } from 'zustand/middleware';
|
|
||||||
|
|
||||||
import { NotificationGraphConfig, Timebox, Unreads, dateToDa } from "@urbit/api";
|
import { NotificationGraphConfig, Timebox, Unreads, dateToDa } from "@urbit/api";
|
||||||
import BigIntOrderedMap from "@urbit/api/lib/BigIntOrderedMap";
|
import BigIntOrderedMap from "@urbit/api/lib/BigIntOrderedMap";
|
||||||
|
|
||||||
// import useApi from "~/logic/lib/useApi";
|
|
||||||
// import { harkGraphHookReducer, harkGroupHookReducer, harkReducer } from "~/logic/subscription/hark";
|
// import { harkGraphHookReducer, harkGroupHookReducer, harkReducer } from "~/logic/subscription/hark";
|
||||||
import { stateSetter } from "~/logic/lib/util";
|
import { BaseState, createState } from "./base";
|
||||||
|
|
||||||
export const HARK_FETCH_MORE_COUNT = 3;
|
export const HARK_FETCH_MORE_COUNT = 3;
|
||||||
|
|
||||||
export interface HarkState extends State {
|
export interface HarkState extends BaseState<HarkState> {
|
||||||
archivedNotifications: BigIntOrderedMap<Timebox>;
|
archivedNotifications: BigIntOrderedMap<Timebox>;
|
||||||
doNotDisturb: boolean;
|
doNotDisturb: boolean;
|
||||||
// getMore: () => Promise<boolean>;
|
// getMore: () => Promise<boolean>;
|
||||||
@ -21,11 +16,10 @@ export interface HarkState extends State {
|
|||||||
notificationsCount: number;
|
notificationsCount: number;
|
||||||
notificationsGraphConfig: NotificationGraphConfig; // TODO unthread this everywhere
|
notificationsGraphConfig: NotificationGraphConfig; // TODO unthread this everywhere
|
||||||
notificationsGroupConfig: []; // TODO type this
|
notificationsGroupConfig: []; // TODO type this
|
||||||
set: (fn: (state: HarkState) => void) => void;
|
|
||||||
unreads: Unreads;
|
unreads: Unreads;
|
||||||
};
|
};
|
||||||
|
|
||||||
const useHarkState = create<HarkState>(persist((set, get) => ({
|
const useHarkState = createState('Hark', {
|
||||||
archivedNotifications: new BigIntOrderedMap<Timebox>(),
|
archivedNotifications: new BigIntOrderedMap<Timebox>(),
|
||||||
doNotDisturb: false,
|
doNotDisturb: false,
|
||||||
// getMore: async (): Promise<boolean> => {
|
// getMore: async (): Promise<boolean> => {
|
||||||
@ -65,25 +59,11 @@ const useHarkState = create<HarkState>(persist((set, get) => ({
|
|||||||
watching: []
|
watching: []
|
||||||
},
|
},
|
||||||
notificationsGroupConfig: [],
|
notificationsGroupConfig: [],
|
||||||
set: fn => stateSetter(fn, set),
|
|
||||||
unreads: {
|
unreads: {
|
||||||
graph: {},
|
graph: {},
|
||||||
group: {}
|
group: {}
|
||||||
},
|
},
|
||||||
}), {
|
}, ['notifications', 'archivedNotifications', 'unreads']);
|
||||||
blacklist: ['notifications', 'archivedNotifications', 'unreads'],
|
|
||||||
name: 'LandscapeHarkState'
|
|
||||||
}));
|
|
||||||
|
|
||||||
function withHarkState<P, S extends keyof HarkState>(Component: any, stateMemberKeys?: S[]) {
|
|
||||||
return React.forwardRef((props: Omit<P, S>, ref) => {
|
|
||||||
const harkState = stateMemberKeys ? useHarkState(
|
|
||||||
state => stateMemberKeys.reduce(
|
|
||||||
(object, key) => ({ ...object, [key]: state[key] }), {}
|
|
||||||
)
|
|
||||||
): useHarkState();
|
|
||||||
return <Component ref={ref} {...harkState} {...props} />
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export { useHarkState as default, withHarkState };
|
export default useHarkState;
|
13
pkg/interface/src/logic/state/invite.ts
Normal file
13
pkg/interface/src/logic/state/invite.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { Invites } from '@urbit/api';
|
||||||
|
|
||||||
|
import { BaseState, createState } from "./base";
|
||||||
|
|
||||||
|
export interface InviteState extends BaseState<InviteState> {
|
||||||
|
invites: Invites;
|
||||||
|
};
|
||||||
|
|
||||||
|
const useInviteState = createState<InviteState>('Invite', {
|
||||||
|
invites: {},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default useInviteState;
|
@ -1,32 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import create, { State } from 'zustand';
|
|
||||||
import { persist } from 'zustand/middleware';
|
|
||||||
|
|
||||||
import { Invites } from '@urbit/api';
|
|
||||||
|
|
||||||
import { stateSetter } from "../lib/util";
|
|
||||||
|
|
||||||
export interface InviteState extends State {
|
|
||||||
invites: Invites;
|
|
||||||
set: (fn: (state: InviteState) => void) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
const useInviteState = create<InviteState>(persist((set, get) => ({
|
|
||||||
invites: {},
|
|
||||||
set: fn => stateSetter(fn, set),
|
|
||||||
}), {
|
|
||||||
name: 'LandscapeInviteState'
|
|
||||||
}));
|
|
||||||
|
|
||||||
function withInviteState<P, S extends keyof InviteState>(Component: any, stateMemberKeys?: S[]) {
|
|
||||||
return React.forwardRef((props: Omit<P, S>, ref) => {
|
|
||||||
const inviteState = stateMemberKeys ? useInviteState(
|
|
||||||
state => stateMemberKeys.reduce(
|
|
||||||
(object, key) => ({ ...object, [key]: state[key] }), {}
|
|
||||||
)
|
|
||||||
): useInviteState();
|
|
||||||
return <Component ref={ref} {...inviteState} {...props} />
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export { useInviteState as default, withInviteState };
|
|
25
pkg/interface/src/logic/state/launch.ts
Normal file
25
pkg/interface/src/logic/state/launch.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { Tile, WeatherState } from "~/types/launch-update";
|
||||||
|
|
||||||
|
import { BaseState, createState } from "./base";
|
||||||
|
|
||||||
|
|
||||||
|
export interface LaunchState extends BaseState<LaunchState> {
|
||||||
|
firstTime: boolean;
|
||||||
|
tileOrdering: string[];
|
||||||
|
tiles: {
|
||||||
|
[app: string]: Tile;
|
||||||
|
},
|
||||||
|
weather: WeatherState | null,
|
||||||
|
userLocation: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const useLaunchState = createState<LaunchState>('Launch', {
|
||||||
|
firstTime: true,
|
||||||
|
tileOrdering: [],
|
||||||
|
tiles: {},
|
||||||
|
weather: null,
|
||||||
|
userLocation: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
export default useLaunchState;
|
@ -1,41 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import create, { State } from "zustand";
|
|
||||||
import { persist } from "zustand/middleware";
|
|
||||||
import { Tile, WeatherState } from "~/types/launch-update";
|
|
||||||
import { stateSetter } from "../lib/util";
|
|
||||||
|
|
||||||
|
|
||||||
export interface LaunchState extends State {
|
|
||||||
firstTime: boolean;
|
|
||||||
tileOrdering: string[];
|
|
||||||
tiles: {
|
|
||||||
[app: string]: Tile;
|
|
||||||
},
|
|
||||||
weather: WeatherState | null,
|
|
||||||
userLocation: string | null;
|
|
||||||
set: (fn: (state: LaunchState) => void) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
const useLaunchState = create<LaunchState>(persist((set, get) => ({
|
|
||||||
firstTime: true,
|
|
||||||
tileOrdering: [],
|
|
||||||
tiles: {},
|
|
||||||
weather: null,
|
|
||||||
userLocation: null,
|
|
||||||
set: fn => stateSetter(fn, set)
|
|
||||||
}), {
|
|
||||||
name: 'LandscapeLaunchState'
|
|
||||||
}));
|
|
||||||
|
|
||||||
function withLaunchState<P, S extends keyof LaunchState>(Component: any, stateMemberKeys?: S[]) {
|
|
||||||
return React.forwardRef((props: Omit<P, S>, ref) => {
|
|
||||||
const launchState = stateMemberKeys ? useLaunchState(
|
|
||||||
state => stateMemberKeys.reduce(
|
|
||||||
(object, key) => ({ ...object, [key]: state[key] }), {}
|
|
||||||
)
|
|
||||||
): useLaunchState();
|
|
||||||
return <Component ref={ref} {...launchState} {...props} />
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export { useLaunchState as default, withLaunchState };
|
|
@ -1,27 +1,21 @@
|
|||||||
import React from "react";
|
|
||||||
import create, { State } from 'zustand';
|
|
||||||
import { persist } from 'zustand/middleware';
|
|
||||||
|
|
||||||
import { MetadataUpdatePreview, Associations } from "@urbit/api";
|
import { MetadataUpdatePreview, Associations } from "@urbit/api";
|
||||||
|
|
||||||
// import useApi from "~/logic/lib/useApi";
|
import { BaseState, createState } from "./base";
|
||||||
import { stateSetter } from "~/logic/lib/util";
|
|
||||||
|
|
||||||
export const METADATA_MAX_PREVIEW_WAIT = 150000;
|
export const METADATA_MAX_PREVIEW_WAIT = 150000;
|
||||||
|
|
||||||
export interface MetadataState extends State {
|
export interface MetadataState extends BaseState<MetadataState> {
|
||||||
associations: Associations;
|
associations: Associations;
|
||||||
// preview: (group: string) => Promise<MetadataUpdatePreview>;
|
// preview: (group: string) => Promise<MetadataUpdatePreview>;
|
||||||
set: (fn: (state: MetadataState) => void) => void;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const useMetadataState = create<MetadataState>(persist((set, get) => ({
|
const useMetadataState = createState<MetadataState>('Metadata', {
|
||||||
associations: { groups: {}, graph: {}, contacts: {}, chat: {}, link: {}, publish: {} },
|
associations: { groups: {}, graph: {}, contacts: {}, chat: {}, link: {}, publish: {} },
|
||||||
// preview: async (group): Promise<MetadataUpdatePreview> => {
|
// preview: async (group): Promise<MetadataUpdatePreview> => {
|
||||||
// return new Promise<MetadataUpdatePreview>((resolve, reject) => {
|
// return new Promise<MetadataUpdatePreview>((resolve, reject) => {
|
||||||
// const api = useApi();
|
// const api = useApi();
|
||||||
// let done = false;
|
// let done = false;
|
||||||
|
|
||||||
// setTimeout(() => {
|
// setTimeout(() => {
|
||||||
// if (done) {
|
// if (done) {
|
||||||
// return;
|
// return;
|
||||||
@ -29,7 +23,7 @@ const useMetadataState = create<MetadataState>(persist((set, get) => ({
|
|||||||
// done = true;
|
// done = true;
|
||||||
// reject(new Error('offline'));
|
// reject(new Error('offline'));
|
||||||
// }, METADATA_MAX_PREVIEW_WAIT);
|
// }, METADATA_MAX_PREVIEW_WAIT);
|
||||||
|
|
||||||
// api.subscribe({
|
// api.subscribe({
|
||||||
// app: 'metadata-pull-hook',
|
// app: 'metadata-pull-hook',
|
||||||
// path: `/preview${group}`,
|
// path: `/preview${group}`,
|
||||||
@ -57,20 +51,7 @@ const useMetadataState = create<MetadataState>(persist((set, get) => ({
|
|||||||
// });
|
// });
|
||||||
// });
|
// });
|
||||||
// },
|
// },
|
||||||
set: fn => stateSetter(fn, set),
|
});
|
||||||
}), {
|
|
||||||
name: 'LandscapeMetadataState'
|
|
||||||
}));
|
|
||||||
|
|
||||||
function withMetadataState<P, S extends keyof MetadataState>(Component: any, stateMemberKeys?: S[]) {
|
|
||||||
return React.forwardRef((props: Omit<P, S>, ref) => {
|
|
||||||
const metadataState = stateMemberKeys ? useMetadataState(
|
|
||||||
state => stateMemberKeys.reduce(
|
|
||||||
(object, key) => ({ ...object, [key]: state[key] }), {}
|
|
||||||
)
|
|
||||||
): useMetadataState();
|
|
||||||
return <Component ref={ref} {...metadataState} {...props} />
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export { useMetadataState as default, withMetadataState };
|
export default useMetadataState;
|
19
pkg/interface/src/logic/state/s3.ts
Normal file
19
pkg/interface/src/logic/state/s3.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { BaseState, createState } from "./base";
|
||||||
|
|
||||||
|
export interface S3State extends BaseState<S3State> {
|
||||||
|
configuration: {
|
||||||
|
buckets: Set<string>;
|
||||||
|
currentBucket: string;
|
||||||
|
};
|
||||||
|
credentials: any | null; // TODO better type
|
||||||
|
};
|
||||||
|
|
||||||
|
const useS3State = createState<S3State>('S3', {
|
||||||
|
configuration: {
|
||||||
|
buckets: new Set(),
|
||||||
|
currentBucket: ''
|
||||||
|
},
|
||||||
|
credentials: null,
|
||||||
|
}, ['configuration']);
|
||||||
|
|
||||||
|
export default useS3State;
|
@ -1,26 +0,0 @@
|
|||||||
import create, { State } from "zustand";
|
|
||||||
import { persist } from "zustand/middleware";
|
|
||||||
import { stateSetter } from "../lib/util";
|
|
||||||
|
|
||||||
export interface S3State extends State {
|
|
||||||
configuration: {
|
|
||||||
buckets: Set<string>;
|
|
||||||
currentBucket: string;
|
|
||||||
};
|
|
||||||
credentials: any | null; // TODO better type
|
|
||||||
set: (fn: (state: S3State) => void) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
const useS3State = create<S3State>(persist((set, get) => ({
|
|
||||||
configuration: {
|
|
||||||
buckets: new Set(),
|
|
||||||
currentBucket: ''
|
|
||||||
},
|
|
||||||
credentials: null,
|
|
||||||
set: fn => stateSetter(fn, set)
|
|
||||||
}), {
|
|
||||||
blacklist: ['configuration'],
|
|
||||||
name: 'LandscapeS3State'
|
|
||||||
}));
|
|
||||||
|
|
||||||
export default useS3State;
|
|
@ -27,9 +27,10 @@ import GlobalSubscription from '~/logic/subscription/global';
|
|||||||
import GlobalApi from '~/logic/api/global';
|
import GlobalApi from '~/logic/api/global';
|
||||||
import { uxToHex } from '~/logic/lib/util';
|
import { uxToHex } from '~/logic/lib/util';
|
||||||
import { foregroundFromBackground } from '~/logic/lib/sigil';
|
import { foregroundFromBackground } from '~/logic/lib/sigil';
|
||||||
import { withLocalState } from '~/logic/state/local';
|
import withState from '~/logic/lib/withState';
|
||||||
import { withContactState } from '~/logic/state/contacts';
|
import useLocalState from '~/logic/state/local';
|
||||||
import { withGroupState } from '~/logic/state/groups';
|
import useContactState from '~/logic/state/contact';
|
||||||
|
import useGroupState from '~/logic/state/group';
|
||||||
import { withSettingsState } from '~/logic/state/settings';
|
import { withSettingsState } from '~/logic/state/settings';
|
||||||
|
|
||||||
|
|
||||||
@ -175,7 +176,6 @@ class App extends React.Component {
|
|||||||
ship={this.ship}
|
ship={this.ship}
|
||||||
api={this.api}
|
api={this.api}
|
||||||
subscription={this.subscription}
|
subscription={this.subscription}
|
||||||
{...state}
|
|
||||||
/>
|
/>
|
||||||
</ErrorBoundary>
|
</ErrorBoundary>
|
||||||
</Router>
|
</Router>
|
||||||
@ -186,5 +186,6 @@ class App extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withGroupState(withContactState(withLocalState(process.env.NODE_ENV === 'production' ? App : hot(App))));
|
export default withState(useGroupState, withState(useContactState, withState(useLocalState, process.env.NODE_ENV === 'production' ? App : hot(App))));
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,9 +17,9 @@ import useS3 from '~/logic/lib/useS3';
|
|||||||
import { isWriter, resourceFromPath } from '~/logic/lib/group';
|
import { isWriter, resourceFromPath } from '~/logic/lib/group';
|
||||||
|
|
||||||
import './css/custom.css';
|
import './css/custom.css';
|
||||||
import useContactState from '~/logic/state/contacts';
|
import useContactState from '~/logic/state/contact';
|
||||||
import useGraphState from '~/logic/state/graph';
|
import useGraphState from '~/logic/state/graph';
|
||||||
import useGroupState from '~/logic/state/groups';
|
import useGroupState from '~/logic/state/group';
|
||||||
import useHarkState from '~/logic/state/hark';
|
import useHarkState from '~/logic/state/hark';
|
||||||
|
|
||||||
type ChatResourceProps = StoreState & {
|
type ChatResourceProps = StoreState & {
|
||||||
|
@ -35,7 +35,7 @@ import styled from 'styled-components';
|
|||||||
import useLocalState from '~/logic/state/local';
|
import useLocalState from '~/logic/state/local';
|
||||||
import useSettingsState, {selectCalmState} from "~/logic/state/settings";
|
import useSettingsState, {selectCalmState} from "~/logic/state/settings";
|
||||||
import Timestamp from '~/views/components/Timestamp';
|
import Timestamp from '~/views/components/Timestamp';
|
||||||
import useContactState from '~/logic/state/contacts';
|
import useContactState from '~/logic/state/contact';
|
||||||
|
|
||||||
export const DATESTAMP_FORMAT = '[~]YYYY.M.D';
|
export const DATESTAMP_FORMAT = '[~]YYYY.M.D';
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import _ from 'lodash';
|
|||||||
import { Col, Button, Box, Row, Icon, Text } from '@tlon/indigo-react';
|
import { Col, Button, Box, Row, Icon, Text } from '@tlon/indigo-react';
|
||||||
|
|
||||||
import './css/custom.css';
|
import './css/custom.css';
|
||||||
import useContactState from '~/logic/state/contacts';
|
import useContactState from '~/logic/state/contact';
|
||||||
import Tiles from './components/tiles';
|
import Tiles from './components/tiles';
|
||||||
import Tile from './components/tiles/tile';
|
import Tile from './components/tiles/tile';
|
||||||
import Groups from './components/Groups';
|
import Groups from './components/Groups';
|
||||||
|
@ -9,7 +9,7 @@ import { getUnreadCount, getNotificationCount } from '~/logic/lib/hark';
|
|||||||
import Tile from '../components/tiles/tile';
|
import Tile from '../components/tiles/tile';
|
||||||
import { useTutorialModal } from '~/views/components/useTutorialModal';
|
import { useTutorialModal } from '~/views/components/useTutorialModal';
|
||||||
import { TUTORIAL_HOST, TUTORIAL_GROUP } from '~/logic/lib/tutorialModal';
|
import { TUTORIAL_HOST, TUTORIAL_GROUP } from '~/logic/lib/tutorialModal';
|
||||||
import useGroupState from '~/logic/state/groups';
|
import useGroupState from '~/logic/state/group';
|
||||||
import useHarkState from '~/logic/state/hark';
|
import useHarkState from '~/logic/state/hark';
|
||||||
import useMetadataState from '~/logic/state/metadata';
|
import useMetadataState from '~/logic/state/metadata';
|
||||||
import useSettingsState, { selectCalmState } from '~/logic/state/settings';
|
import useSettingsState, { selectCalmState } from '~/logic/state/settings';
|
||||||
|
@ -2,7 +2,8 @@ import React from 'react';
|
|||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import { Box, Icon, Text, BaseAnchor, BaseInput } from '@tlon/indigo-react';
|
import { Box, Icon, Text, BaseAnchor, BaseInput } from '@tlon/indigo-react';
|
||||||
import ErrorBoundary from '~/views/components/ErrorBoundary';
|
import ErrorBoundary from '~/views/components/ErrorBoundary';
|
||||||
import { withLaunchState } from '~/logic/state/launch';
|
import withState from '~/logic/lib/withState';
|
||||||
|
import useLaunchState from '~/logic/state/launch';
|
||||||
|
|
||||||
import Tile from './tile';
|
import Tile from './tile';
|
||||||
|
|
||||||
@ -290,4 +291,4 @@ class WeatherTile extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withLaunchState(WeatherTile);
|
export default withState(useLaunchState, WeatherTile);
|
||||||
|
@ -18,8 +18,8 @@ import { getSnippet } from '~/logic/lib/publish';
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { MentionText } from '~/views/components/MentionText';
|
import { MentionText } from '~/views/components/MentionText';
|
||||||
import ChatMessage from '../chat/components/ChatMessage';
|
import ChatMessage from '../chat/components/ChatMessage';
|
||||||
import useContactState from '~/logic/state/contacts';
|
import useContactState from '~/logic/state/contact';
|
||||||
import useGroupState from '~/logic/state/groups';
|
import useGroupState from '~/logic/state/group';
|
||||||
|
|
||||||
function getGraphModuleIcon(module: string) {
|
function getGraphModuleIcon(module: string) {
|
||||||
if (module === 'link') {
|
if (module === 'link') {
|
||||||
|
@ -9,7 +9,7 @@ import { Associations, Contact, Contacts, Rolodex } from '@urbit/api';
|
|||||||
import { PropFunc } from '~/types/util';
|
import { PropFunc } from '~/types/util';
|
||||||
import { useShowNickname } from '~/logic/lib/util';
|
import { useShowNickname } from '~/logic/lib/util';
|
||||||
import Timestamp from '~/views/components/Timestamp';
|
import Timestamp from '~/views/components/Timestamp';
|
||||||
import useContactState from '~/logic/state/contacts';
|
import useContactState from '~/logic/state/contact';
|
||||||
import useMetadataState from '~/logic/state/metadata';
|
import useMetadataState from '~/logic/state/metadata';
|
||||||
|
|
||||||
const Text = (props: PropFunc<typeof Text>) => (
|
const Text = (props: PropFunc<typeof Text>) => (
|
||||||
|
@ -20,7 +20,7 @@ import { ImageInput } from '~/views/components/ImageInput';
|
|||||||
import { MarkdownField } from '~/views/apps/publish/components/MarkdownField';
|
import { MarkdownField } from '~/views/apps/publish/components/MarkdownField';
|
||||||
import { resourceFromPath } from '~/logic/lib/group';
|
import { resourceFromPath } from '~/logic/lib/group';
|
||||||
import GroupSearch from '~/views/components/GroupSearch';
|
import GroupSearch from '~/views/components/GroupSearch';
|
||||||
import useContactState from '~/logic/state/contacts';
|
import useContactState from '~/logic/state/contact';
|
||||||
|
|
||||||
const formSchema = Yup.object({
|
const formSchema = Yup.object({
|
||||||
nickname: Yup.string(),
|
nickname: Yup.string(),
|
||||||
|
@ -17,7 +17,7 @@ import { EditProfile } from './EditProfile';
|
|||||||
import { SetStatusBarModal } from '~/views/components/SetStatusBarModal';
|
import { SetStatusBarModal } from '~/views/components/SetStatusBarModal';
|
||||||
import { uxToHex } from '~/logic/lib/util';
|
import { uxToHex } from '~/logic/lib/util';
|
||||||
import { useTutorialModal } from '~/views/components/useTutorialModal';
|
import { useTutorialModal } from '~/views/components/useTutorialModal';
|
||||||
import useContactState from '~/logic/state/contacts';
|
import useContactState from '~/logic/state/contact';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ import RichText from '~/views/components/RichText';
|
|||||||
import { GroupLink } from '~/views/components/GroupLink';
|
import { GroupLink } from '~/views/components/GroupLink';
|
||||||
import { lengthOrder } from '~/logic/lib/util';
|
import { lengthOrder } from '~/logic/lib/util';
|
||||||
import useLocalState from '~/logic/state/local';
|
import useLocalState from '~/logic/state/local';
|
||||||
import useContactState from '~/logic/state/contacts';
|
import useContactState from '~/logic/state/contact';
|
||||||
|
|
||||||
export function ViewProfile(props: any): ReactElement {
|
export function ViewProfile(props: any): ReactElement {
|
||||||
const { hideNicknames } = useSettingsState(selectCalmState);
|
const { hideNicknames } = useSettingsState(selectCalmState);
|
||||||
|
@ -5,7 +5,7 @@ import Helmet from 'react-helmet';
|
|||||||
import { Box } from '@tlon/indigo-react';
|
import { Box } from '@tlon/indigo-react';
|
||||||
|
|
||||||
import { Profile } from './components/Profile';
|
import { Profile } from './components/Profile';
|
||||||
import useContactState from '~/logic/state/contacts';
|
import useContactState from '~/logic/state/contact';
|
||||||
import useHarkState from '~/logic/state/hark';
|
import useHarkState from '~/logic/state/hark';
|
||||||
|
|
||||||
export default function ProfileScreen(props: any) {
|
export default function ProfileScreen(props: any) {
|
||||||
|
@ -7,8 +7,8 @@ import { Contacts, Rolodex, Groups, Associations, Graph, Association, Unreads }
|
|||||||
import { NotebookPosts } from './NotebookPosts';
|
import { NotebookPosts } from './NotebookPosts';
|
||||||
import GlobalApi from '~/logic/api/global';
|
import GlobalApi from '~/logic/api/global';
|
||||||
import { useShowNickname } from '~/logic/lib/util';
|
import { useShowNickname } from '~/logic/lib/util';
|
||||||
import useContactState from '~/logic/state/contacts';
|
import useContactState from '~/logic/state/contact';
|
||||||
import useGroupState from '~/logic/state/groups';
|
import useGroupState from '~/logic/state/group';
|
||||||
|
|
||||||
interface NotebookProps {
|
interface NotebookProps {
|
||||||
api: GlobalApi;
|
api: GlobalApi;
|
||||||
|
@ -2,7 +2,7 @@ import React, { Component } from 'react';
|
|||||||
import { Col } from '@tlon/indigo-react';
|
import { Col } from '@tlon/indigo-react';
|
||||||
import { NotePreview } from './NotePreview';
|
import { NotePreview } from './NotePreview';
|
||||||
import { Contacts, Graph, Unreads, Group } from '@urbit/api';
|
import { Contacts, Graph, Unreads, Group } from '@urbit/api';
|
||||||
import useContactState from '~/logic/state/contacts';
|
import useContactState from '~/logic/state/contact';
|
||||||
|
|
||||||
interface NotebookPostsProps {
|
interface NotebookPostsProps {
|
||||||
graph: Graph;
|
graph: Graph;
|
||||||
|
@ -18,7 +18,7 @@ import Notebook from './Notebook';
|
|||||||
import NewPost from './new-post';
|
import NewPost from './new-post';
|
||||||
import { NoteRoutes } from './NoteRoutes';
|
import { NoteRoutes } from './NoteRoutes';
|
||||||
import useGraphState from '~/logic/state/graph';
|
import useGraphState from '~/logic/state/graph';
|
||||||
import useGroupState from '~/logic/state/groups';
|
import useGroupState from '~/logic/state/group';
|
||||||
|
|
||||||
interface NotebookRoutesProps {
|
interface NotebookRoutesProps {
|
||||||
api: GlobalApi;
|
api: GlobalApi;
|
||||||
|
@ -10,7 +10,8 @@ import { Box, Col } from '@tlon/indigo-react';
|
|||||||
import Api from './api';
|
import Api from './api';
|
||||||
import Store from './store';
|
import Store from './store';
|
||||||
import Subscription from './subscription';
|
import Subscription from './subscription';
|
||||||
import { withHarkState } from '~/logic/state/hark';
|
import withState from '~/logic/lib/withState';
|
||||||
|
import useHarkState from '~/logic/state/hark';
|
||||||
|
|
||||||
import './css/custom.css';
|
import './css/custom.css';
|
||||||
|
|
||||||
@ -94,4 +95,4 @@ class TermApp extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withHarkState(TermApp);
|
export default withState(useHarkState, TermApp);
|
||||||
|
@ -11,7 +11,7 @@ import OverlaySigil from './OverlaySigil';
|
|||||||
import { Sigil } from '~/logic/lib/sigil';
|
import { Sigil } from '~/logic/lib/sigil';
|
||||||
import GlobalApi from '~/logic/api/global';
|
import GlobalApi from '~/logic/api/global';
|
||||||
import Timestamp from './Timestamp';
|
import Timestamp from './Timestamp';
|
||||||
import useContactState from '~/logic/state/contacts';
|
import useContactState from '~/logic/state/contact';
|
||||||
|
|
||||||
interface AuthorProps {
|
interface AuthorProps {
|
||||||
ship: string;
|
ship: string;
|
||||||
|
@ -18,7 +18,7 @@ import { Associations, Association } from '@urbit/api/metadata';
|
|||||||
|
|
||||||
import { roleForShip } from '~/logic/lib/group';
|
import { roleForShip } from '~/logic/lib/group';
|
||||||
import { DropdownSearch } from './DropdownSearch';
|
import { DropdownSearch } from './DropdownSearch';
|
||||||
import useGroupState from '~/logic/state/groups';
|
import useGroupState from '~/logic/state/group';
|
||||||
import useMetadataState from '~/logic/state/metadata';
|
import useMetadataState from '~/logic/state/metadata';
|
||||||
|
|
||||||
interface GroupSearchProps<I extends string> {
|
interface GroupSearchProps<I extends string> {
|
||||||
|
@ -18,7 +18,7 @@ import { GroupInvite } from './Group';
|
|||||||
import { InviteSkeleton } from './InviteSkeleton';
|
import { InviteSkeleton } from './InviteSkeleton';
|
||||||
import { JoinSkeleton } from './JoinSkeleton';
|
import { JoinSkeleton } from './JoinSkeleton';
|
||||||
import { useWaitForProps } from '~/logic/lib/useWaitForProps';
|
import { useWaitForProps } from '~/logic/lib/useWaitForProps';
|
||||||
import useGroupState from '~/logic/state/groups';
|
import useGroupState from '~/logic/state/group';
|
||||||
import useMetadataState from '~/logic/state/metadata';
|
import useMetadataState from '~/logic/state/metadata';
|
||||||
|
|
||||||
interface InviteItemProps {
|
interface InviteItemProps {
|
||||||
|
@ -6,7 +6,7 @@ import RichText from '~/views/components/RichText';
|
|||||||
import { cite, useShowNickname, uxToHex } from '~/logic/lib/util';
|
import { cite, useShowNickname, uxToHex } from '~/logic/lib/util';
|
||||||
import OverlaySigil from '~/views/components/OverlaySigil';
|
import OverlaySigil from '~/views/components/OverlaySigil';
|
||||||
import { useHistory } from 'react-router-dom';
|
import { useHistory } from 'react-router-dom';
|
||||||
import useContactState from '~/logic/state/contacts';
|
import useContactState from '~/logic/state/contact';
|
||||||
|
|
||||||
interface MentionTextProps {
|
interface MentionTextProps {
|
||||||
contact?: Contact;
|
contact?: Contact;
|
||||||
|
@ -24,8 +24,8 @@ import { Rolodex, Groups } from '@urbit/api';
|
|||||||
import { DropdownSearch } from './DropdownSearch';
|
import { DropdownSearch } from './DropdownSearch';
|
||||||
import { cite, deSig } from '~/logic/lib/util';
|
import { cite, deSig } from '~/logic/lib/util';
|
||||||
import { HoverBox } from './HoverBox';
|
import { HoverBox } from './HoverBox';
|
||||||
import useContactState from '~/logic/state/contacts';
|
import useContactState from '~/logic/state/contact';
|
||||||
import useGroupState from '~/logic/state/groups';
|
import useGroupState from '~/logic/state/group';
|
||||||
|
|
||||||
interface InviteSearchProps<I extends string> {
|
interface InviteSearchProps<I extends string> {
|
||||||
autoFocus?: boolean;
|
autoFocus?: boolean;
|
||||||
|
@ -17,8 +17,8 @@ import {useOutsideClick} from '~/logic/lib/useOutsideClick';
|
|||||||
import {Portal} from '../Portal';
|
import {Portal} from '../Portal';
|
||||||
import useSettingsState, {SettingsState} from '~/logic/state/settings';
|
import useSettingsState, {SettingsState} from '~/logic/state/settings';
|
||||||
import { Tile } from '~/types';
|
import { Tile } from '~/types';
|
||||||
import useContactState from '~/logic/state/contacts';
|
import useContactState from '~/logic/state/contact';
|
||||||
import useGroupState from '~/logic/state/groups';
|
import useGroupState from '~/logic/state/group';
|
||||||
import useHarkState from '~/logic/state/hark';
|
import useHarkState from '~/logic/state/hark';
|
||||||
import useInviteState from '~/logic/state/invite';
|
import useInviteState from '~/logic/state/invite';
|
||||||
import useLaunchState from '~/logic/state/launch';
|
import useLaunchState from '~/logic/state/launch';
|
||||||
|
@ -3,9 +3,10 @@ import { Box, Row, Icon, Text } from '@tlon/indigo-react';
|
|||||||
import defaultApps from '~/logic/lib/default-apps';
|
import defaultApps from '~/logic/lib/default-apps';
|
||||||
import Sigil from '~/logic/lib/sigil';
|
import Sigil from '~/logic/lib/sigil';
|
||||||
import { uxToHex, cite } from '~/logic/lib/util';
|
import { uxToHex, cite } from '~/logic/lib/util';
|
||||||
import { withHarkState } from '~/logic/state/hark';
|
import withState from '~/logic/lib/withState';
|
||||||
import { withContactState } from '~/logic/state/contacts';
|
import useHarkState from '~/logic/state/hark';
|
||||||
import { withInviteState } from '~/logic/state/invite';
|
import useContactState from '~/logic/state/contact';
|
||||||
|
import useInviteState from '~/logic/state/invite';
|
||||||
|
|
||||||
export class OmniboxResult extends Component {
|
export class OmniboxResult extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
@ -122,4 +123,4 @@ export class OmniboxResult extends Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withInviteState(withHarkState(withContactState(OmniboxResult), ['notificationsCount']));
|
export default withState(useInviteState, withState(useHarkState, withState(useContactState, OmniboxResult), ['notificationsCount']));
|
||||||
|
@ -9,7 +9,7 @@ import { Groups, Associations, Association } from '@urbit/api';
|
|||||||
import GlobalApi from '~/logic/api/global';
|
import GlobalApi from '~/logic/api/global';
|
||||||
import GroupSearch from '~/views/components/GroupSearch';
|
import GroupSearch from '~/views/components/GroupSearch';
|
||||||
import { AsyncButton } from '~/views/components/AsyncButton';
|
import { AsyncButton } from '~/views/components/AsyncButton';
|
||||||
import useGroupState from '~/logic/state/groups';
|
import useGroupState from '~/logic/state/group';
|
||||||
|
|
||||||
const formSchema = Yup.object({
|
const formSchema = Yup.object({
|
||||||
group: Yup.string().nullable()
|
group: Yup.string().nullable()
|
||||||
|
@ -27,8 +27,8 @@ import '~/views/apps/publish/css/custom.css';
|
|||||||
import { getGroupFromWorkspace } from '~/logic/lib/workspace';
|
import { getGroupFromWorkspace } from '~/logic/lib/workspace';
|
||||||
import { GroupSummary } from './GroupSummary';
|
import { GroupSummary } from './GroupSummary';
|
||||||
import { Workspace } from '~/types/workspace';
|
import { Workspace } from '~/types/workspace';
|
||||||
import useContactState from '~/logic/state/contacts';
|
import useContactState from '~/logic/state/contact';
|
||||||
import useGroupState from '~/logic/state/groups';
|
import useGroupState from '~/logic/state/group';
|
||||||
import useHarkState from '~/logic/state/hark';
|
import useHarkState from '~/logic/state/hark';
|
||||||
import useMetadataState from '~/logic/state/metadata';
|
import useMetadataState from '~/logic/state/metadata';
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ import { StatelessAsyncButton } from '~/views/components/StatelessAsyncButton';
|
|||||||
import { getModuleIcon } from '~/logic/lib/util';
|
import { getModuleIcon } from '~/logic/lib/util';
|
||||||
import { FormError } from '~/views/components/FormError';
|
import { FormError } from '~/views/components/FormError';
|
||||||
import { GroupSummary } from './GroupSummary';
|
import { GroupSummary } from './GroupSummary';
|
||||||
import useGroupState from '~/logic/state/groups';
|
import useGroupState from '~/logic/state/group';
|
||||||
import useMetadataState from '~/logic/state/metadata';
|
import useMetadataState from '~/logic/state/metadata';
|
||||||
|
|
||||||
const formSchema = Yup.object({
|
const formSchema = Yup.object({
|
||||||
|
@ -22,7 +22,7 @@ import { Rolodex } from '@urbit/api';
|
|||||||
import { IconRadio } from '~/views/components/IconRadio';
|
import { IconRadio } from '~/views/components/IconRadio';
|
||||||
import { ChannelWriteFieldSchema, ChannelWritePerms } from './ChannelWritePerms';
|
import { ChannelWriteFieldSchema, ChannelWritePerms } from './ChannelWritePerms';
|
||||||
import { Workspace } from '~/types/workspace';
|
import { Workspace } from '~/types/workspace';
|
||||||
import useGroupState from '~/logic/state/groups';
|
import useGroupState from '~/logic/state/group';
|
||||||
|
|
||||||
type FormSchema = {
|
type FormSchema = {
|
||||||
name: string;
|
name: string;
|
||||||
|
@ -16,7 +16,7 @@ import { AsyncButton } from '~/views/components/AsyncButton';
|
|||||||
import { useWaitForProps } from '~/logic/lib/useWaitForProps';
|
import { useWaitForProps } from '~/logic/lib/useWaitForProps';
|
||||||
import GlobalApi from '~/logic/api/global';
|
import GlobalApi from '~/logic/api/global';
|
||||||
import { stringToSymbol } from '~/logic/lib/util';
|
import { stringToSymbol } from '~/logic/lib/util';
|
||||||
import useGroupState from '~/logic/state/groups';
|
import useGroupState from '~/logic/state/group';
|
||||||
import useMetadataState from '~/logic/state/metadata';
|
import useMetadataState from '~/logic/state/metadata';
|
||||||
|
|
||||||
const formSchema = Yup.object({
|
const formSchema = Yup.object({
|
||||||
|
@ -30,7 +30,7 @@ import { Dropdown } from '~/views/components/Dropdown';
|
|||||||
import GlobalApi from '~/logic/api/global';
|
import GlobalApi from '~/logic/api/global';
|
||||||
import { StatelessAsyncAction } from '~/views/components/StatelessAsyncAction';
|
import { StatelessAsyncAction } from '~/views/components/StatelessAsyncAction';
|
||||||
import useLocalState from '~/logic/state/local';
|
import useLocalState from '~/logic/state/local';
|
||||||
import useContactState from '~/logic/state/contacts';
|
import useContactState from '~/logic/state/contact';
|
||||||
import useSettingsState, { selectCalmState } from '~/logic/state/settings';
|
import useSettingsState, { selectCalmState } from '~/logic/state/settings';
|
||||||
|
|
||||||
const TruncText = styled(Text)`
|
const TruncText = styled(Text)`
|
||||||
|
@ -11,8 +11,8 @@ import { StoreState } from '~/logic/store/type';
|
|||||||
import GlobalApi from '~/logic/api/global';
|
import GlobalApi from '~/logic/api/global';
|
||||||
import { ResourceSkeleton } from './ResourceSkeleton';
|
import { ResourceSkeleton } from './ResourceSkeleton';
|
||||||
import { ChannelPopoverRoutes } from './ChannelPopoverRoutes';
|
import { ChannelPopoverRoutes } from './ChannelPopoverRoutes';
|
||||||
import useGroupState from '~/logic/state/groups';
|
import useGroupState from '~/logic/state/group';
|
||||||
import useContactState from '~/logic/state/contacts';
|
import useContactState from '~/logic/state/contact';
|
||||||
import useHarkState from '~/logic/state/hark';
|
import useHarkState from '~/logic/state/hark';
|
||||||
import useMetadataState from '~/logic/state/metadata';
|
import useMetadataState from '~/logic/state/metadata';
|
||||||
|
|
||||||
|
@ -11,8 +11,8 @@ import RichText from '~/views/components/RichText';
|
|||||||
import GlobalApi from '~/logic/api/global';
|
import GlobalApi from '~/logic/api/global';
|
||||||
import { isWriter } from '~/logic/lib/group';
|
import { isWriter } from '~/logic/lib/group';
|
||||||
import { getItemTitle } from '~/logic/lib/util';
|
import { getItemTitle } from '~/logic/lib/util';
|
||||||
import useContactState from '~/logic/state/contacts';
|
import useContactState from '~/logic/state/contact';
|
||||||
import useGroupState from '~/logic/state/groups';
|
import useGroupState from '~/logic/state/group';
|
||||||
|
|
||||||
const TruncatedText = styled(RichText)`
|
const TruncatedText = styled(RichText)`
|
||||||
white-space: pre;
|
white-space: pre;
|
||||||
@ -55,7 +55,7 @@ export function ResourceSkeleton(props: ResourceSkeletonProps): ReactElement {
|
|||||||
recipient = title;
|
recipient = title;
|
||||||
title = (contacts?.[title]?.nickname) ? contacts[title].nickname : title;
|
title = (contacts?.[title]?.nickname) ? contacts[title].nickname : title;
|
||||||
} else {
|
} else {
|
||||||
recipient = Array.from(group.members).map(e => `~${e}`).join(", ")
|
recipient = Array.from(group ? group.members : []).map(e => `~${e}`).join(", ")
|
||||||
}
|
}
|
||||||
|
|
||||||
const [, , ship, resource] = rid.split('/');
|
const [, , ship, resource] = rid.split('/');
|
||||||
|
@ -20,7 +20,7 @@ import { SidebarAppConfigs } from './types';
|
|||||||
import { SidebarList } from './SidebarList';
|
import { SidebarList } from './SidebarList';
|
||||||
import { roleForShip } from '~/logic/lib/group';
|
import { roleForShip } from '~/logic/lib/group';
|
||||||
import { useTutorialModal } from '~/views/components/useTutorialModal';
|
import { useTutorialModal } from '~/views/components/useTutorialModal';
|
||||||
import useGroupState from '~/logic/state/groups';
|
import useGroupState from '~/logic/state/group';
|
||||||
import useMetadataState from '~/logic/state/metadata';
|
import useMetadataState from '~/logic/state/metadata';
|
||||||
|
|
||||||
const ScrollbarLessCol = styled(Col)`
|
const ScrollbarLessCol = styled(Col)`
|
||||||
|
@ -11,8 +11,8 @@ import { useTutorialModal } from '~/views/components/useTutorialModal';
|
|||||||
import { TUTORIAL_HOST, TUTORIAL_GROUP } from '~/logic/lib/tutorialModal';
|
import { TUTORIAL_HOST, TUTORIAL_GROUP } from '~/logic/lib/tutorialModal';
|
||||||
import { SidebarAppConfigs, SidebarItemStatus } from './types';
|
import { SidebarAppConfigs, SidebarItemStatus } from './types';
|
||||||
import { Workspace } from '~/types/workspace';
|
import { Workspace } from '~/types/workspace';
|
||||||
import useContactState from '~/logic/state/contacts';
|
import useContactState from '~/logic/state/contact';
|
||||||
import useGroupState from '~/logic/state/groups';
|
import useGroupState from '~/logic/state/group';
|
||||||
import useSettingsState, { selectCalmState } from '~/logic/state/settings';
|
import useSettingsState, { selectCalmState } from '~/logic/state/settings';
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ import { roleForShip } from '~/logic/lib/group';
|
|||||||
import { NewChannel } from '~/views/landscape/components/NewChannel';
|
import { NewChannel } from '~/views/landscape/components/NewChannel';
|
||||||
import GlobalApi from '~/logic/api/global';
|
import GlobalApi from '~/logic/api/global';
|
||||||
import { Workspace } from '~/types/workspace';
|
import { Workspace } from '~/types/workspace';
|
||||||
import useGroupState from '~/logic/state/groups';
|
import useGroupState from '~/logic/state/group';
|
||||||
import useMetadataState from '~/logic/state/metadata';
|
import useMetadataState from '~/logic/state/metadata';
|
||||||
|
|
||||||
export function SidebarListHeader(props: {
|
export function SidebarListHeader(props: {
|
||||||
|
@ -18,7 +18,8 @@ import { Loading } from '../components/Loading';
|
|||||||
import { Workspace } from '~/types/workspace';
|
import { Workspace } from '~/types/workspace';
|
||||||
import GlobalSubscription from '~/logic/subscription/global';
|
import GlobalSubscription from '~/logic/subscription/global';
|
||||||
import useGraphState from '~/logic/state/graph';
|
import useGraphState from '~/logic/state/graph';
|
||||||
import { withHarkState } from '~/logic/state/hark';
|
import useHarkState, { withHarkState } from '~/logic/state/hark';
|
||||||
|
import withState from '~/logic/lib/withState';
|
||||||
|
|
||||||
type LandscapeProps = StoreState & {
|
type LandscapeProps = StoreState & {
|
||||||
ship: PatpNoSig;
|
ship: PatpNoSig;
|
||||||
@ -155,4 +156,6 @@ class Landscape extends Component<LandscapeProps, Record<string, never>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withHarkState(Landscape);
|
export default withState(useHarkState, Landscape, ['notificationsCount']);
|
||||||
|
|
||||||
|
// export default withHarkState(Landscape);
|
Loading…
Reference in New Issue
Block a user