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> {
|
||||
console.log(path);
|
||||
return fetch(`/~/scry/${app}${path}.json`).then(r => r.json() as Promise<T>);
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,16 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import _ from 'lodash';
|
||||
import f, { memoize } from 'lodash/fp';
|
||||
import f, { compose, memoize } from 'lodash/fp';
|
||||
import bigInt, { BigInteger } from 'big-integer';
|
||||
import { Association, Contact } from '@urbit/api';
|
||||
import useLocalState from '../state/local';
|
||||
import produce from 'immer';
|
||||
import produce, { enableMapSet } from 'immer';
|
||||
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;
|
||||
|
||||
@ -411,7 +416,43 @@ export function getItemTitle(association: Association) {
|
||||
return association.metadata.title || association.resource;
|
||||
}
|
||||
|
||||
export const stateSetter = <StateType>(fn: (state: StateType) => void, set): void => {
|
||||
// TODO this is a stub for the store debugging
|
||||
export const stateSetter = <StateType>(
|
||||
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));
|
||||
};
|
||||
|
||||
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 useContactState, { ContactState } from '../state/contacts';
|
||||
import useContactState, { ContactState } from '../state/contact';
|
||||
import { reduceState } from '../lib/util';
|
||||
|
||||
|
||||
export const ContactReducer = (json) => {
|
||||
const data: ContactUpdate = _.get(json, 'contact-update', false);
|
||||
if (data) {
|
||||
useContactState.setState(
|
||||
compose([
|
||||
reduceState<ContactState, ContactUpdate>(useContactState, data, [
|
||||
initial,
|
||||
add,
|
||||
remove,
|
||||
edit,
|
||||
setPublic
|
||||
].map(reducer => reducer.bind(reducer, data))
|
||||
)(useContactState.getState())
|
||||
);
|
||||
]);
|
||||
}
|
||||
|
||||
// TODO: better isolation
|
||||
|
@ -3,20 +3,18 @@ import { BigIntOrderedMap } from "~/logic/lib/BigIntOrderedMap";
|
||||
import bigInt, { BigInteger } from "big-integer";
|
||||
import useGraphState, { GraphState } from '../state/graph';
|
||||
import { compose } from 'lodash/fp';
|
||||
import { reduceState } from '../lib/util';
|
||||
|
||||
export const GraphReducer = (json) => {
|
||||
const data = _.get(json, 'graph-update', false);
|
||||
if (data) {
|
||||
useGraphState.setState(
|
||||
compose([
|
||||
reduceState<GraphState, any>(useGraphState, data, [
|
||||
keys,
|
||||
addGraph,
|
||||
removeGraph,
|
||||
addNodes,
|
||||
removeNodes
|
||||
].map(reducer => reducer.bind(reducer, data))
|
||||
)(useGraphState.getState())
|
||||
);
|
||||
]);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -13,8 +13,8 @@ import {
|
||||
InvitePolicy
|
||||
} from '@urbit/api/groups';
|
||||
import { Enc, PatpNoSig } from '@urbit/api';
|
||||
import { resourceAsPath } from '../lib/util';
|
||||
import useGroupState, { GroupState } from '../state/groups';
|
||||
import { reduceState, resourceAsPath } from '../lib/util';
|
||||
import useGroupState, { GroupState } from '../state/group';
|
||||
import { compose } from 'lodash/fp';
|
||||
|
||||
function decodeGroup(group: Enc<Group>): Group {
|
||||
@ -61,22 +61,18 @@ export default class GroupReducer {
|
||||
reduce(json: Cage) {
|
||||
const data = json.groupUpdate;
|
||||
if (data) {
|
||||
useGroupState.setState(
|
||||
compose([
|
||||
reduceState<GroupState, GroupUpdate>(useGroupState, data, [
|
||||
initial,
|
||||
addMembers,
|
||||
addTag,
|
||||
removeMembers,
|
||||
initialGroup,
|
||||
removeTag,
|
||||
initial,
|
||||
addGroup,
|
||||
removeGroup,
|
||||
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 data = json['initial'];
|
||||
if (data) {
|
||||
state.set(st => {
|
||||
st.groups = _.mapValues(data, decodeGroup);
|
||||
});
|
||||
state.groups = _.mapValues(data, decodeGroup);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
@ -148,6 +142,7 @@ const removeMembers = (json: GroupUpdate, state: GroupState): GroupState => {
|
||||
state.groups[resourcePath].members.delete(member);
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
const addTag = (json: GroupUpdate, state: GroupState): GroupState => {
|
||||
|
@ -6,7 +6,7 @@ import {
|
||||
UnreadStats,
|
||||
Timebox
|
||||
} from '@urbit/api';
|
||||
import { makePatDa } from '~/logic/lib/util';
|
||||
import { makePatDa, reduceState } from '~/logic/lib/util';
|
||||
import _ from 'lodash';
|
||||
import { StoreState } from '../store/type';
|
||||
import { BigIntOrderedMap } from '../lib/BigIntOrderedMap';
|
||||
@ -20,30 +20,44 @@ export const HarkReducer = (json: any) => {
|
||||
}
|
||||
const graphHookData = _.get(json, 'hark-graph-hook-update', false);
|
||||
if (graphHookData) {
|
||||
useHarkState.setState(
|
||||
compose([
|
||||
reduceState<HarkState, any>(useHarkState, graphHookData, [
|
||||
graphInitial,
|
||||
graphIgnore,
|
||||
graphListen,
|
||||
graphWatchSelf,
|
||||
graphMentions,
|
||||
].map(reducer => reducer.bind(reducer, graphHookData))
|
||||
)(useHarkState.getState())
|
||||
);
|
||||
]);
|
||||
}
|
||||
const groupHookData = _.get(json, 'hark-group-hook-update', false);
|
||||
if (groupHookData) {
|
||||
useHarkState.setState(
|
||||
compose([
|
||||
reduceState<HarkState, any>(useHarkState, groupHookData, [
|
||||
groupInitial,
|
||||
groupListen,
|
||||
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 {
|
||||
const data = _.get(json, 'initial', false);
|
||||
if (data) {
|
||||
@ -115,29 +129,6 @@ function graphWatchSelf(json: any, state: HarkState): HarkState {
|
||||
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 {
|
||||
const data = _.get(json, 'read-all');
|
||||
if(data) {
|
||||
@ -197,7 +188,6 @@ function unreadEach(json: any, state: HarkState): HarkState {
|
||||
function unreads(json: any, state: HarkState): HarkState {
|
||||
const data = _.get(json, 'unreads');
|
||||
if(data) {
|
||||
clearState(state);
|
||||
data.forEach(({ index, stats }) => {
|
||||
const { unreads, notifications, last } = stats;
|
||||
updateNotificationStats(state, index, 'notifications', x => x + notifications);
|
||||
@ -236,28 +226,30 @@ 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)) {
|
||||
return;
|
||||
return state;
|
||||
}
|
||||
const property = [index.graph.graph, index.graph.index, 'unreads'];
|
||||
const curr = _.get(state.unreads.graph, property, 0);
|
||||
const newCount = count(curr);
|
||||
_.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)) {
|
||||
return;
|
||||
return state;
|
||||
}
|
||||
const unreads = _.get(state.unreads.graph, [index.graph.graph, index.graph.index, 'unreads'], new Set<string>());
|
||||
const oldSize = unreads.size;
|
||||
f(unreads);
|
||||
const newSize = unreads.size;
|
||||
_.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') {
|
||||
state.notificationsCount = f(state.notificationsCount);
|
||||
}
|
||||
@ -268,6 +260,7 @@ function updateNotificationStats(state: HarkState, index: NotifIndex, statField:
|
||||
const curr = _.get(state.unreads.group, [index.group, statField], 0);
|
||||
_.set(state.unreads.group, [index.group, statField], f(curr));
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
function added(json: any, state: HarkState): HarkState {
|
||||
@ -282,12 +275,13 @@ function added(json: any, state: HarkState): HarkState {
|
||||
);
|
||||
if (arrIdx !== -1) {
|
||||
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 };
|
||||
state.notifications.set(time, timebox);
|
||||
} else {
|
||||
updateNotificationStats(state, index, 'notifications', x => x+1);
|
||||
state = updateNotificationStats(state, index, 'notifications', x => x+1);
|
||||
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 {
|
||||
const data = _.get(json, 'more', false);
|
||||
if (data) {
|
||||
_.forEach(data, d => reduce(d, state));
|
||||
_.forEach(data, d => reduce(d));
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
@ -5,22 +5,20 @@ import { InviteUpdate } from '@urbit/api/invite';
|
||||
|
||||
import { Cage } from '~/types/cage';
|
||||
import useInviteState, { InviteState } from '../state/invite';
|
||||
import { reduceState } from '../lib/util';
|
||||
|
||||
export default class InviteReducer {
|
||||
reduce(json: Cage) {
|
||||
const data = json['invite-update'];
|
||||
if (data) {
|
||||
useInviteState.setState(
|
||||
compose([
|
||||
reduceState<InviteState, InviteUpdate>(useInviteState, data, [
|
||||
initial,
|
||||
create,
|
||||
deleteInvite,
|
||||
invite,
|
||||
accepted,
|
||||
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 useLaunchState from '../state/launch';
|
||||
import { compose } from 'lodash/fp';
|
||||
import { reduceState } from '../lib/util';
|
||||
|
||||
export default class LaunchReducer {
|
||||
reduce(json: Cage) {
|
||||
const data = _.get(json, 'launch-update', false);
|
||||
if (data) {
|
||||
useLaunchState.setState(
|
||||
compose([
|
||||
reduceState<LaunchState, LaunchUpdate>(useLaunchState, data, [
|
||||
initial,
|
||||
changeFirstTime,
|
||||
changeOrder,
|
||||
changeFirstTime,
|
||||
changeIsShown,
|
||||
].map(reducer => reducer.bind(reducer, data))
|
||||
)(useLaunchState.getState())
|
||||
)
|
||||
]);
|
||||
}
|
||||
|
||||
const weatherData: WeatherState = _.get(json, 'weather', false);
|
||||
if (weatherData) {
|
||||
useLaunchState.setState({ weather: weatherData });
|
||||
useLaunchState.getState().set(state => {
|
||||
state.weather = weatherData;
|
||||
});
|
||||
}
|
||||
|
||||
const locationData = _.get(json, 'location', false);
|
||||
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 useMetadataState, { MetadataState } from '../state/metadata';
|
||||
import { reduceState } from '../lib/util';
|
||||
|
||||
export default class MetadataReducer {
|
||||
reduce(json: Cage) {
|
||||
const data = json['metadata-update'];
|
||||
if (data) {
|
||||
useMetadataState.setState(
|
||||
compose([
|
||||
reduceState<MetadataState, MetadataUpdate>(useMetadataState, data, [
|
||||
associations,
|
||||
add,
|
||||
update,
|
||||
remove,
|
||||
groupInitial,
|
||||
].map(reducer => reducer.bind(reducer, data))
|
||||
)(useMetadataState.getState())
|
||||
);
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const groupInitial = (json: MetadataUpdate, state: MetadataState): MetadataState => {
|
||||
const data = _.get(json, 'initial-group', false);
|
||||
console.log(data);
|
||||
if(data) {
|
||||
state = associations(data, state);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ import _ from 'lodash';
|
||||
import { compose } from 'lodash/fp';
|
||||
import { Cage } from '~/types/cage';
|
||||
import { S3Update } from '~/types/s3-update';
|
||||
import { reduceState } from '../lib/util';
|
||||
import useS3State, { S3State } from '../state/s3';
|
||||
|
||||
|
||||
@ -9,8 +10,7 @@ export default class S3Reducer {
|
||||
reduce(json: Cage) {
|
||||
const data = _.get(json, 's3-update', false);
|
||||
if (data) {
|
||||
useS3State.setState(
|
||||
compose([
|
||||
reduceState<S3State, S3Update>(useS3State, data, [
|
||||
credentials,
|
||||
configuration,
|
||||
currentBucket,
|
||||
@ -19,9 +19,7 @@ export default class S3Reducer {
|
||||
endpoint,
|
||||
accessKeyId,
|
||||
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 React from "react";
|
||||
import create, { State } from "zustand";
|
||||
import { persist } from "zustand/middleware";
|
||||
|
||||
// import useApi from "~/logic/lib/useApi";
|
||||
import { stateSetter } from "~/logic/lib/util";
|
||||
// import { graphReducer } from "~/logic/subscription/graph";
|
||||
import { BaseState, createState } from "./base";
|
||||
|
||||
export interface GraphState extends State {
|
||||
export interface GraphState extends BaseState<GraphState> {
|
||||
graphs: Graphs;
|
||||
graphKeys: Set<string>;
|
||||
// getKeys: () => Promise<void>;
|
||||
@ -19,10 +14,9 @@ export interface GraphState extends State {
|
||||
// getYoungerSiblings: (ship: string, resource: string, count: number, index?: string) => Promise<void>;
|
||||
// getGraphSubset: (ship: string, resource: string, start: string, end: 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: {},
|
||||
graphKeys: new Set(),
|
||||
// getKeys: async () => {
|
||||
@ -124,21 +118,6 @@ const useGraphState = create<GraphState>(persist((set, get) => ({
|
||||
// });
|
||||
// graphReducer(node);
|
||||
// },
|
||||
set: fn => stateSetter(fn, set)
|
||||
}), {
|
||||
blacklist: ['graphKeys', 'graphs'],
|
||||
name: 'LandscapeGraphState'
|
||||
}));
|
||||
}, ['graphs', 'graphKeys']);
|
||||
|
||||
function withGraphState<P, S extends keyof GraphState>(Component: any, stateMemberKeys?: S[]) {
|
||||
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 };
|
||||
export default useGraphState;
|
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 BigIntOrderedMap from "@urbit/api/lib/BigIntOrderedMap";
|
||||
|
||||
// import useApi from "~/logic/lib/useApi";
|
||||
// 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 interface HarkState extends State {
|
||||
export interface HarkState extends BaseState<HarkState> {
|
||||
archivedNotifications: BigIntOrderedMap<Timebox>;
|
||||
doNotDisturb: boolean;
|
||||
// getMore: () => Promise<boolean>;
|
||||
@ -21,11 +16,10 @@ export interface HarkState extends State {
|
||||
notificationsCount: number;
|
||||
notificationsGraphConfig: NotificationGraphConfig; // TODO unthread this everywhere
|
||||
notificationsGroupConfig: []; // TODO type this
|
||||
set: (fn: (state: HarkState) => void) => void;
|
||||
unreads: Unreads;
|
||||
};
|
||||
|
||||
const useHarkState = create<HarkState>(persist((set, get) => ({
|
||||
const useHarkState = createState('Hark', {
|
||||
archivedNotifications: new BigIntOrderedMap<Timebox>(),
|
||||
doNotDisturb: false,
|
||||
// getMore: async (): Promise<boolean> => {
|
||||
@ -65,25 +59,11 @@ const useHarkState = create<HarkState>(persist((set, get) => ({
|
||||
watching: []
|
||||
},
|
||||
notificationsGroupConfig: [],
|
||||
set: fn => stateSetter(fn, set),
|
||||
unreads: {
|
||||
graph: {},
|
||||
group: {}
|
||||
},
|
||||
}), {
|
||||
blacklist: ['notifications', 'archivedNotifications', 'unreads'],
|
||||
name: 'LandscapeHarkState'
|
||||
}));
|
||||
}, ['notifications', 'archivedNotifications', 'unreads']);
|
||||
|
||||
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,21 +1,15 @@
|
||||
import React from "react";
|
||||
import create, { State } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
|
||||
import { MetadataUpdatePreview, Associations } from "@urbit/api";
|
||||
|
||||
// import useApi from "~/logic/lib/useApi";
|
||||
import { stateSetter } from "~/logic/lib/util";
|
||||
import { BaseState, createState } from "./base";
|
||||
|
||||
export const METADATA_MAX_PREVIEW_WAIT = 150000;
|
||||
|
||||
export interface MetadataState extends State {
|
||||
export interface MetadataState extends BaseState<MetadataState> {
|
||||
associations: Associations;
|
||||
// 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: {} },
|
||||
// preview: async (group): Promise<MetadataUpdatePreview> => {
|
||||
// return new Promise<MetadataUpdatePreview>((resolve, reject) => {
|
||||
@ -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 { uxToHex } from '~/logic/lib/util';
|
||||
import { foregroundFromBackground } from '~/logic/lib/sigil';
|
||||
import { withLocalState } from '~/logic/state/local';
|
||||
import { withContactState } from '~/logic/state/contacts';
|
||||
import { withGroupState } from '~/logic/state/groups';
|
||||
import withState from '~/logic/lib/withState';
|
||||
import useLocalState from '~/logic/state/local';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
import useGroupState from '~/logic/state/group';
|
||||
import { withSettingsState } from '~/logic/state/settings';
|
||||
|
||||
|
||||
@ -175,7 +176,6 @@ class App extends React.Component {
|
||||
ship={this.ship}
|
||||
api={this.api}
|
||||
subscription={this.subscription}
|
||||
{...state}
|
||||
/>
|
||||
</ErrorBoundary>
|
||||
</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 './css/custom.css';
|
||||
import useContactState from '~/logic/state/contacts';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
import useGraphState from '~/logic/state/graph';
|
||||
import useGroupState from '~/logic/state/groups';
|
||||
import useGroupState from '~/logic/state/group';
|
||||
import useHarkState from '~/logic/state/hark';
|
||||
|
||||
type ChatResourceProps = StoreState & {
|
||||
|
@ -35,7 +35,7 @@ import styled from 'styled-components';
|
||||
import useLocalState from '~/logic/state/local';
|
||||
import useSettingsState, {selectCalmState} from "~/logic/state/settings";
|
||||
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';
|
||||
|
||||
|
@ -7,7 +7,7 @@ import _ from 'lodash';
|
||||
import { Col, Button, Box, Row, Icon, Text } from '@tlon/indigo-react';
|
||||
|
||||
import './css/custom.css';
|
||||
import useContactState from '~/logic/state/contacts';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
import Tiles from './components/tiles';
|
||||
import Tile from './components/tiles/tile';
|
||||
import Groups from './components/Groups';
|
||||
|
@ -9,7 +9,7 @@ import { getUnreadCount, getNotificationCount } from '~/logic/lib/hark';
|
||||
import Tile from '../components/tiles/tile';
|
||||
import { useTutorialModal } from '~/views/components/useTutorialModal';
|
||||
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 useMetadataState from '~/logic/state/metadata';
|
||||
import useSettingsState, { selectCalmState } from '~/logic/state/settings';
|
||||
|
@ -2,7 +2,8 @@ import React from 'react';
|
||||
import moment from 'moment';
|
||||
import { Box, Icon, Text, BaseAnchor, BaseInput } from '@tlon/indigo-react';
|
||||
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';
|
||||
|
||||
@ -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 { MentionText } from '~/views/components/MentionText';
|
||||
import ChatMessage from '../chat/components/ChatMessage';
|
||||
import useContactState from '~/logic/state/contacts';
|
||||
import useGroupState from '~/logic/state/groups';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
import useGroupState from '~/logic/state/group';
|
||||
|
||||
function getGraphModuleIcon(module: string) {
|
||||
if (module === 'link') {
|
||||
|
@ -9,7 +9,7 @@ import { Associations, Contact, Contacts, Rolodex } from '@urbit/api';
|
||||
import { PropFunc } from '~/types/util';
|
||||
import { useShowNickname } from '~/logic/lib/util';
|
||||
import Timestamp from '~/views/components/Timestamp';
|
||||
import useContactState from '~/logic/state/contacts';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
import useMetadataState from '~/logic/state/metadata';
|
||||
|
||||
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 { resourceFromPath } from '~/logic/lib/group';
|
||||
import GroupSearch from '~/views/components/GroupSearch';
|
||||
import useContactState from '~/logic/state/contacts';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
|
||||
const formSchema = Yup.object({
|
||||
nickname: Yup.string(),
|
||||
|
@ -17,7 +17,7 @@ import { EditProfile } from './EditProfile';
|
||||
import { SetStatusBarModal } from '~/views/components/SetStatusBarModal';
|
||||
import { uxToHex } from '~/logic/lib/util';
|
||||
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 { lengthOrder } from '~/logic/lib/util';
|
||||
import useLocalState from '~/logic/state/local';
|
||||
import useContactState from '~/logic/state/contacts';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
|
||||
export function ViewProfile(props: any): ReactElement {
|
||||
const { hideNicknames } = useSettingsState(selectCalmState);
|
||||
|
@ -5,7 +5,7 @@ import Helmet from 'react-helmet';
|
||||
import { Box } from '@tlon/indigo-react';
|
||||
|
||||
import { Profile } from './components/Profile';
|
||||
import useContactState from '~/logic/state/contacts';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
import useHarkState from '~/logic/state/hark';
|
||||
|
||||
export default function ProfileScreen(props: any) {
|
||||
|
@ -7,8 +7,8 @@ import { Contacts, Rolodex, Groups, Associations, Graph, Association, Unreads }
|
||||
import { NotebookPosts } from './NotebookPosts';
|
||||
import GlobalApi from '~/logic/api/global';
|
||||
import { useShowNickname } from '~/logic/lib/util';
|
||||
import useContactState from '~/logic/state/contacts';
|
||||
import useGroupState from '~/logic/state/groups';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
import useGroupState from '~/logic/state/group';
|
||||
|
||||
interface NotebookProps {
|
||||
api: GlobalApi;
|
||||
|
@ -2,7 +2,7 @@ import React, { Component } from 'react';
|
||||
import { Col } from '@tlon/indigo-react';
|
||||
import { NotePreview } from './NotePreview';
|
||||
import { Contacts, Graph, Unreads, Group } from '@urbit/api';
|
||||
import useContactState from '~/logic/state/contacts';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
|
||||
interface NotebookPostsProps {
|
||||
graph: Graph;
|
||||
|
@ -18,7 +18,7 @@ import Notebook from './Notebook';
|
||||
import NewPost from './new-post';
|
||||
import { NoteRoutes } from './NoteRoutes';
|
||||
import useGraphState from '~/logic/state/graph';
|
||||
import useGroupState from '~/logic/state/groups';
|
||||
import useGroupState from '~/logic/state/group';
|
||||
|
||||
interface NotebookRoutesProps {
|
||||
api: GlobalApi;
|
||||
|
@ -10,7 +10,8 @@ import { Box, Col } from '@tlon/indigo-react';
|
||||
import Api from './api';
|
||||
import Store from './store';
|
||||
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';
|
||||
|
||||
@ -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 GlobalApi from '~/logic/api/global';
|
||||
import Timestamp from './Timestamp';
|
||||
import useContactState from '~/logic/state/contacts';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
|
||||
interface AuthorProps {
|
||||
ship: string;
|
||||
|
@ -18,7 +18,7 @@ import { Associations, Association } from '@urbit/api/metadata';
|
||||
|
||||
import { roleForShip } from '~/logic/lib/group';
|
||||
import { DropdownSearch } from './DropdownSearch';
|
||||
import useGroupState from '~/logic/state/groups';
|
||||
import useGroupState from '~/logic/state/group';
|
||||
import useMetadataState from '~/logic/state/metadata';
|
||||
|
||||
interface GroupSearchProps<I extends string> {
|
||||
|
@ -18,7 +18,7 @@ import { GroupInvite } from './Group';
|
||||
import { InviteSkeleton } from './InviteSkeleton';
|
||||
import { JoinSkeleton } from './JoinSkeleton';
|
||||
import { useWaitForProps } from '~/logic/lib/useWaitForProps';
|
||||
import useGroupState from '~/logic/state/groups';
|
||||
import useGroupState from '~/logic/state/group';
|
||||
import useMetadataState from '~/logic/state/metadata';
|
||||
|
||||
interface InviteItemProps {
|
||||
|
@ -6,7 +6,7 @@ import RichText from '~/views/components/RichText';
|
||||
import { cite, useShowNickname, uxToHex } from '~/logic/lib/util';
|
||||
import OverlaySigil from '~/views/components/OverlaySigil';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import useContactState from '~/logic/state/contacts';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
|
||||
interface MentionTextProps {
|
||||
contact?: Contact;
|
||||
|
@ -24,8 +24,8 @@ import { Rolodex, Groups } from '@urbit/api';
|
||||
import { DropdownSearch } from './DropdownSearch';
|
||||
import { cite, deSig } from '~/logic/lib/util';
|
||||
import { HoverBox } from './HoverBox';
|
||||
import useContactState from '~/logic/state/contacts';
|
||||
import useGroupState from '~/logic/state/groups';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
import useGroupState from '~/logic/state/group';
|
||||
|
||||
interface InviteSearchProps<I extends string> {
|
||||
autoFocus?: boolean;
|
||||
|
@ -17,8 +17,8 @@ import {useOutsideClick} from '~/logic/lib/useOutsideClick';
|
||||
import {Portal} from '../Portal';
|
||||
import useSettingsState, {SettingsState} from '~/logic/state/settings';
|
||||
import { Tile } from '~/types';
|
||||
import useContactState from '~/logic/state/contacts';
|
||||
import useGroupState from '~/logic/state/groups';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
import useGroupState from '~/logic/state/group';
|
||||
import useHarkState from '~/logic/state/hark';
|
||||
import useInviteState from '~/logic/state/invite';
|
||||
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 Sigil from '~/logic/lib/sigil';
|
||||
import { uxToHex, cite } from '~/logic/lib/util';
|
||||
import { withHarkState } from '~/logic/state/hark';
|
||||
import { withContactState } from '~/logic/state/contacts';
|
||||
import { withInviteState } from '~/logic/state/invite';
|
||||
import withState from '~/logic/lib/withState';
|
||||
import useHarkState from '~/logic/state/hark';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
import useInviteState from '~/logic/state/invite';
|
||||
|
||||
export class OmniboxResult extends Component {
|
||||
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 GroupSearch from '~/views/components/GroupSearch';
|
||||
import { AsyncButton } from '~/views/components/AsyncButton';
|
||||
import useGroupState from '~/logic/state/groups';
|
||||
import useGroupState from '~/logic/state/group';
|
||||
|
||||
const formSchema = Yup.object({
|
||||
group: Yup.string().nullable()
|
||||
|
@ -27,8 +27,8 @@ import '~/views/apps/publish/css/custom.css';
|
||||
import { getGroupFromWorkspace } from '~/logic/lib/workspace';
|
||||
import { GroupSummary } from './GroupSummary';
|
||||
import { Workspace } from '~/types/workspace';
|
||||
import useContactState from '~/logic/state/contacts';
|
||||
import useGroupState from '~/logic/state/groups';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
import useGroupState from '~/logic/state/group';
|
||||
import useHarkState from '~/logic/state/hark';
|
||||
import useMetadataState from '~/logic/state/metadata';
|
||||
|
||||
|
@ -22,7 +22,7 @@ import { StatelessAsyncButton } from '~/views/components/StatelessAsyncButton';
|
||||
import { getModuleIcon } from '~/logic/lib/util';
|
||||
import { FormError } from '~/views/components/FormError';
|
||||
import { GroupSummary } from './GroupSummary';
|
||||
import useGroupState from '~/logic/state/groups';
|
||||
import useGroupState from '~/logic/state/group';
|
||||
import useMetadataState from '~/logic/state/metadata';
|
||||
|
||||
const formSchema = Yup.object({
|
||||
|
@ -22,7 +22,7 @@ import { Rolodex } from '@urbit/api';
|
||||
import { IconRadio } from '~/views/components/IconRadio';
|
||||
import { ChannelWriteFieldSchema, ChannelWritePerms } from './ChannelWritePerms';
|
||||
import { Workspace } from '~/types/workspace';
|
||||
import useGroupState from '~/logic/state/groups';
|
||||
import useGroupState from '~/logic/state/group';
|
||||
|
||||
type FormSchema = {
|
||||
name: string;
|
||||
|
@ -16,7 +16,7 @@ import { AsyncButton } from '~/views/components/AsyncButton';
|
||||
import { useWaitForProps } from '~/logic/lib/useWaitForProps';
|
||||
import GlobalApi from '~/logic/api/global';
|
||||
import { stringToSymbol } from '~/logic/lib/util';
|
||||
import useGroupState from '~/logic/state/groups';
|
||||
import useGroupState from '~/logic/state/group';
|
||||
import useMetadataState from '~/logic/state/metadata';
|
||||
|
||||
const formSchema = Yup.object({
|
||||
|
@ -30,7 +30,7 @@ import { Dropdown } from '~/views/components/Dropdown';
|
||||
import GlobalApi from '~/logic/api/global';
|
||||
import { StatelessAsyncAction } from '~/views/components/StatelessAsyncAction';
|
||||
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';
|
||||
|
||||
const TruncText = styled(Text)`
|
||||
|
@ -11,8 +11,8 @@ import { StoreState } from '~/logic/store/type';
|
||||
import GlobalApi from '~/logic/api/global';
|
||||
import { ResourceSkeleton } from './ResourceSkeleton';
|
||||
import { ChannelPopoverRoutes } from './ChannelPopoverRoutes';
|
||||
import useGroupState from '~/logic/state/groups';
|
||||
import useContactState from '~/logic/state/contacts';
|
||||
import useGroupState from '~/logic/state/group';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
import useHarkState from '~/logic/state/hark';
|
||||
import useMetadataState from '~/logic/state/metadata';
|
||||
|
||||
|
@ -11,8 +11,8 @@ import RichText from '~/views/components/RichText';
|
||||
import GlobalApi from '~/logic/api/global';
|
||||
import { isWriter } from '~/logic/lib/group';
|
||||
import { getItemTitle } from '~/logic/lib/util';
|
||||
import useContactState from '~/logic/state/contacts';
|
||||
import useGroupState from '~/logic/state/groups';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
import useGroupState from '~/logic/state/group';
|
||||
|
||||
const TruncatedText = styled(RichText)`
|
||||
white-space: pre;
|
||||
@ -55,7 +55,7 @@ export function ResourceSkeleton(props: ResourceSkeletonProps): ReactElement {
|
||||
recipient = title;
|
||||
title = (contacts?.[title]?.nickname) ? contacts[title].nickname : title;
|
||||
} 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('/');
|
||||
|
@ -20,7 +20,7 @@ import { SidebarAppConfigs } from './types';
|
||||
import { SidebarList } from './SidebarList';
|
||||
import { roleForShip } from '~/logic/lib/group';
|
||||
import { useTutorialModal } from '~/views/components/useTutorialModal';
|
||||
import useGroupState from '~/logic/state/groups';
|
||||
import useGroupState from '~/logic/state/group';
|
||||
import useMetadataState from '~/logic/state/metadata';
|
||||
|
||||
const ScrollbarLessCol = styled(Col)`
|
||||
|
@ -11,8 +11,8 @@ import { useTutorialModal } from '~/views/components/useTutorialModal';
|
||||
import { TUTORIAL_HOST, TUTORIAL_GROUP } from '~/logic/lib/tutorialModal';
|
||||
import { SidebarAppConfigs, SidebarItemStatus } from './types';
|
||||
import { Workspace } from '~/types/workspace';
|
||||
import useContactState from '~/logic/state/contacts';
|
||||
import useGroupState from '~/logic/state/groups';
|
||||
import useContactState from '~/logic/state/contact';
|
||||
import useGroupState from '~/logic/state/group';
|
||||
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 GlobalApi from '~/logic/api/global';
|
||||
import { Workspace } from '~/types/workspace';
|
||||
import useGroupState from '~/logic/state/groups';
|
||||
import useGroupState from '~/logic/state/group';
|
||||
import useMetadataState from '~/logic/state/metadata';
|
||||
|
||||
export function SidebarListHeader(props: {
|
||||
|
@ -18,7 +18,8 @@ import { Loading } from '../components/Loading';
|
||||
import { Workspace } from '~/types/workspace';
|
||||
import GlobalSubscription from '~/logic/subscription/global';
|
||||
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 & {
|
||||
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