mirror of
https://github.com/urbit/shrub.git
synced 2024-12-19 16:51:42 +03:00
Merge pull request #4802 from urbit/mp/landscape/type-safety-1
landscape/logic: type safety adjustments
This commit is contained in:
commit
72b1650635
8
pkg/interface/package-lock.json
generated
8
pkg/interface/package-lock.json
generated
@ -9495,9 +9495,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"typescript": {
|
||||
"version": "3.9.7",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz",
|
||||
"integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==",
|
||||
"version": "4.2.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz",
|
||||
"integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==",
|
||||
"dev": true
|
||||
},
|
||||
"unherit": {
|
||||
@ -9916,7 +9916,6 @@
|
||||
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
|
||||
"integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"is-extendable": "^0.1.0"
|
||||
}
|
||||
@ -9983,7 +9982,6 @@
|
||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
|
||||
"integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"kind-of": "^3.0.2"
|
||||
}
|
||||
|
@ -88,7 +88,7 @@
|
||||
"react-hot-loader": "^4.13.0",
|
||||
"sass": "^1.32.5",
|
||||
"sass-loader": "^8.0.2",
|
||||
"typescript": "^3.9.7",
|
||||
"typescript": "^4.2.4",
|
||||
"webpack": "^4.46.0",
|
||||
"webpack-cli": "^3.3.12",
|
||||
"webpack-dev-server": "^3.11.2"
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Post, GraphNode, TextContent, Graph, NodeMap } from '@urbit/api';
|
||||
import { Post, GraphNode, TextContent } from '@urbit/api';
|
||||
import { buntPost } from '~/logic/lib/post';
|
||||
import { unixToDa } from '~/logic/lib/util';
|
||||
import BigIntOrderedMap from "@urbit/api/lib/BigIntOrderedMap";
|
||||
@ -7,7 +7,7 @@ import bigInt, { BigInteger } from 'big-integer';
|
||||
export function newPost(
|
||||
title: string,
|
||||
body: string
|
||||
): [BigInteger, NodeMap] {
|
||||
): [BigInteger, any] {
|
||||
const now = Date.now();
|
||||
const nowDa = unixToDa(now);
|
||||
const root: Post = {
|
||||
@ -73,13 +73,16 @@ export function editPost(rev: number, noteId: BigInteger, title: string, body: s
|
||||
}
|
||||
|
||||
export function getLatestRevision(node: GraphNode): [number, string, string, Post] {
|
||||
const revs = node.children.get(bigInt(1));
|
||||
const revs = node.children?.get(bigInt(1));
|
||||
const empty = [1, '', '', buntPost()] as [number, string, string, Post];
|
||||
if(!revs) {
|
||||
return empty;
|
||||
}
|
||||
const [revNum, rev] = [...revs.children][0];
|
||||
if(!rev) {
|
||||
let revNum, rev;
|
||||
if (revs?.children !== null) {
|
||||
[revNum, rev] = [...revs.children][0];
|
||||
}
|
||||
if (!rev) {
|
||||
return empty;
|
||||
}
|
||||
const [title, body] = rev.post.contents as TextContent[];
|
||||
@ -88,18 +91,22 @@ export function getLatestRevision(node: GraphNode): [number, string, string, Pos
|
||||
|
||||
export function getLatestCommentRevision(node: GraphNode): [number, Post] {
|
||||
const empty = [1, buntPost()] as [number, Post];
|
||||
if (node.children.size <= 0) {
|
||||
const childSize = node?.children?.size ?? 0;
|
||||
if (childSize <= 0) {
|
||||
return empty;
|
||||
}
|
||||
const [revNum, rev] = [...node.children][0];
|
||||
if(!rev) {
|
||||
let revNum, rev;
|
||||
if (node?.children !== null) {
|
||||
[revNum, rev] = [...node.children][0];
|
||||
}
|
||||
if (!rev) {
|
||||
return empty;
|
||||
}
|
||||
return [revNum.toJSNumber(), rev.post];
|
||||
}
|
||||
|
||||
export function getComments(node: GraphNode): GraphNode {
|
||||
const comments = node.children.get(bigInt(2));
|
||||
const comments = node.children?.get(bigInt(2));
|
||||
if(!comments) {
|
||||
return { post: buntPost(), children: new BigIntOrderedMap() };
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { TutorialProgress, Associations } from '@urbit/api';
|
||||
import { Associations } from '@urbit/api';
|
||||
import { TutorialProgress } from '~/types';
|
||||
import { AlignX, AlignY } from '~/logic/lib/relativePosition';
|
||||
import { Direction } from '~/views/components/Triangle';
|
||||
|
||||
@ -22,7 +23,7 @@ interface StepDetail {
|
||||
alignY: AlignY | AlignY[];
|
||||
offsetX: number;
|
||||
offsetY: number;
|
||||
arrow: Direction;
|
||||
arrow?: Direction;
|
||||
}
|
||||
|
||||
export function hasTutorialGroup(props: { associations: Associations }) {
|
||||
|
@ -15,7 +15,8 @@ function retrieve<T>(key: string, initial: T): T {
|
||||
interface SetStateFunc<T> {
|
||||
(t: T): T;
|
||||
}
|
||||
type SetState<T> = T | SetStateFunc<T>;
|
||||
// See microsoft/typescript#37663 for filed bug
|
||||
type SetState<T> = T extends any ? SetStateFunc<T> : never;
|
||||
export function useLocalStorageState<T>(key: string, initial: T) {
|
||||
const [state, _setState] = useState(() => retrieve(key, initial));
|
||||
|
||||
|
@ -2,18 +2,14 @@ import React, {
|
||||
useState,
|
||||
ReactNode,
|
||||
useCallback,
|
||||
SyntheticEvent,
|
||||
useMemo,
|
||||
useEffect,
|
||||
useRef
|
||||
} from 'react';
|
||||
|
||||
import { Box } from '@tlon/indigo-react';
|
||||
import { useOutsideClick } from './useOutsideClick';
|
||||
import { ModalOverlay } from '~/views/components/ModalOverlay';
|
||||
import { Portal } from '~/views/components/Portal';
|
||||
import { ModalPortal } from '~/views/components/ModalPortal';
|
||||
import { PropFunc } from '@urbit/api';
|
||||
import { PropFunc } from '~/types';
|
||||
|
||||
type ModalFunc = (dismiss: () => void) => JSX.Element;
|
||||
interface UseModalProps {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { useRef } from 'react';
|
||||
import { Primitive } from '@urbit/api';
|
||||
import { Primitive } from '~/types';
|
||||
|
||||
export default function usePreviousValue<T extends Primitive>(value: T): T {
|
||||
const prev = useRef<T | null>(null);
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useWaitForProps } from "./useWaitForProps";
|
||||
import {unstable_batchedUpdates} from "react-dom";
|
||||
|
||||
export type IOInstance<I, P, O> = (
|
||||
@ -10,7 +9,7 @@ export function useRunIO<I, O>(
|
||||
io: (i: I) => Promise<O>,
|
||||
after: (o: O) => void,
|
||||
key: string
|
||||
): () => Promise<void> {
|
||||
): (i: I) => Promise<unknown> {
|
||||
const [resolve, setResolve] = useState<() => void>(() => () => {});
|
||||
const [reject, setReject] = useState<(e: any) => void>(() => () => {});
|
||||
const [output, setOutput] = useState<O | null>(null);
|
||||
|
@ -5,7 +5,7 @@ export function useStatelessAsyncClickable(
|
||||
onClick: (e: MouseEvent) => Promise<void>,
|
||||
name: string
|
||||
) {
|
||||
const [state, setState] = useState<ButtonState>('waiting');
|
||||
const [state, setState] = useState<AsyncClickableState>('waiting');
|
||||
const handleClick = useCallback(
|
||||
async (e: MouseEvent) => {
|
||||
try {
|
||||
|
@ -16,7 +16,7 @@ export interface IuseStorage {
|
||||
upload: (file: File, bucket: string) => Promise<string>;
|
||||
uploadDefault: (file: File) => Promise<string>;
|
||||
uploading: boolean;
|
||||
promptUpload: () => Promise<string | undefined>;
|
||||
promptUpload: () => Promise<unknown>;
|
||||
}
|
||||
|
||||
const useStorage = ({ accept = '*' } = { accept: '*' }): IuseStorage => {
|
||||
|
@ -192,7 +192,10 @@ export function uxToHex(ux: string) {
|
||||
export const hexToUx = (hex) => {
|
||||
const ux = f.flow(
|
||||
f.chunk(4),
|
||||
f.map(x => _.dropWhile(x, y => y === 0).join('')),
|
||||
// eslint-disable-next-line prefer-arrow-callback
|
||||
f.map(x => _.dropWhile(x, function(y: unknown) {
|
||||
return y === 0;
|
||||
}).join('')),
|
||||
f.join('.')
|
||||
)(hex.split(''));
|
||||
return `0x${ux}`;
|
||||
@ -417,7 +420,7 @@ export const useHovering = (): useHoveringInterface => {
|
||||
onMouseLeave,
|
||||
}), [onMouseLeave, onMouseOver]);
|
||||
|
||||
|
||||
|
||||
return useMemo(() => ({ hovering, bind }), [hovering, bind]);
|
||||
};
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Associations, Workspace } from '@urbit/api';
|
||||
import { Associations } from '@urbit/api';
|
||||
import { Workspace } from '~/types';
|
||||
|
||||
export function getTitleFromWorkspace(
|
||||
associations: Associations,
|
||||
|
@ -1,5 +1,4 @@
|
||||
import _ from 'lodash';
|
||||
import { StoreState } from '../../store/type';
|
||||
import { StoreState } from '../store/type';
|
||||
import { Cage } from '~/types/cage';
|
||||
|
||||
type LocalState = Pick<StoreState, 'connection'>;
|
||||
|
@ -5,16 +5,14 @@ import {
|
||||
Group,
|
||||
Tags,
|
||||
GroupPolicy,
|
||||
GroupPolicyDiff,
|
||||
OpenPolicyDiff,
|
||||
OpenPolicy,
|
||||
InvitePolicyDiff,
|
||||
InvitePolicy
|
||||
} from '@urbit/api/groups';
|
||||
import { Enc, PatpNoSig } from '@urbit/api';
|
||||
import { Enc } from '@urbit/api';
|
||||
import { resourceAsPath } from '../lib/util';
|
||||
import useGroupState, { GroupState } from '../state/group';
|
||||
import { compose } from 'lodash/fp';
|
||||
import { reduceState } from '../state/base';
|
||||
|
||||
function decodeGroup(group: Enc<Group>): Group {
|
||||
@ -45,11 +43,11 @@ function decodeTags(tags: Enc<Tags>): Tags {
|
||||
tags,
|
||||
(acc, ships, key): Tags => {
|
||||
if (key.search(/\\/) === -1) {
|
||||
acc.role[key] = new Set(ships);
|
||||
acc.role[key] = new Set([ships]);
|
||||
return acc;
|
||||
} else {
|
||||
const [app, tag, resource] = key.split('\\');
|
||||
_.set(acc, [app, resource, tag], new Set(ships));
|
||||
_.set(acc, [app, resource, tag], new Set([ships]));
|
||||
return acc;
|
||||
}
|
||||
},
|
||||
@ -125,9 +123,9 @@ const addMembers = (json: GroupUpdate, state: GroupState): GroupState => {
|
||||
state.groups[resourcePath].members.add(member);
|
||||
if (
|
||||
'invite' in state.groups[resourcePath].policy &&
|
||||
state.groups[resourcePath].policy.invite.pending.has(member)
|
||||
state.groups[resourcePath].policy['invite'].pending.has(member)
|
||||
) {
|
||||
state.groups[resourcePath].policy.invite.pending.delete(member)
|
||||
state.groups[resourcePath].policy['invite'].pending.delete(member);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -159,7 +157,7 @@ const addTag = (json: GroupUpdate, state: GroupState): GroupState => {
|
||||
_.set(tags, tagAccessors, tagged);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
const removeTag = (json: GroupUpdate, state: GroupState): GroupState => {
|
||||
if ('removeTag' in json) {
|
||||
|
@ -1,18 +1,14 @@
|
||||
import {
|
||||
Notifications,
|
||||
NotifIndex,
|
||||
NotificationGraphConfig,
|
||||
GroupNotificationsConfig,
|
||||
UnreadStats,
|
||||
Timebox
|
||||
} from '@urbit/api';
|
||||
import { makePatDa } from '~/logic/lib/util';
|
||||
import _ from 'lodash';
|
||||
import BigIntOrderedMap from "@urbit/api/lib/BigIntOrderedMap";
|
||||
import BigIntOrderedMap from '@urbit/api/lib/BigIntOrderedMap';
|
||||
import useHarkState, { HarkState } from '../state/hark';
|
||||
import { compose } from 'lodash/fp';
|
||||
import { reduceState } from '../state/base';
|
||||
import bigInt, {BigInteger} from 'big-integer';
|
||||
import {BigInteger} from 'big-integer';
|
||||
|
||||
export const HarkReducer = (json: any) => {
|
||||
const data = _.get(json, 'harkUpdate', false);
|
||||
@ -151,7 +147,7 @@ function graphWatchSelf(json: any, state: HarkState): HarkState {
|
||||
|
||||
function readAll(json: any, state: HarkState): HarkState {
|
||||
const data = _.get(json, 'read-all');
|
||||
if(data) {
|
||||
if(data) {
|
||||
clearState(state);
|
||||
}
|
||||
return state;
|
||||
@ -264,7 +260,7 @@ function updateUnreads(state: HarkState, index: NotifIndex, f: (us: Set<string>)
|
||||
if(!('graph' in index)) {
|
||||
return state;
|
||||
}
|
||||
let unreads = _.get(state.unreads.graph, [index.graph.graph, index.graph.index, 'unreads'], new Set<string>());
|
||||
let unreads: any = _.get(state.unreads.graph, [index.graph.graph, index.graph.index, 'unreads'], new Set<string>());
|
||||
f(unreads);
|
||||
|
||||
_.set(state.unreads.graph, [index.graph.graph, index.graph.index, 'unreads'], unreads);
|
||||
@ -278,7 +274,7 @@ function addNotificationToUnread(state: HarkState, index: NotifIndex, time: BigI
|
||||
_.set(state.unreads.graph, path,
|
||||
[
|
||||
...curr.filter(c => !(c.time.eq(time) && notifIdxEqual(c.index, index))),
|
||||
{ time, index}
|
||||
{ time, index }
|
||||
]
|
||||
);
|
||||
} else if ('group' in index) {
|
||||
@ -287,7 +283,7 @@ function addNotificationToUnread(state: HarkState, index: NotifIndex, time: BigI
|
||||
_.set(state.unreads.group, path,
|
||||
[
|
||||
...curr.filter(c => !(c.time.eq(time) && notifIdxEqual(c.index, index))),
|
||||
{ time, index}
|
||||
{ time, index }
|
||||
]
|
||||
);
|
||||
}
|
||||
@ -312,10 +308,10 @@ function removeNotificationFromUnread(state: HarkState, index: NotifIndex, time:
|
||||
function updateNotificationStats(state: HarkState, index: NotifIndex, statField: 'unreads' | 'last', f: (x: number) => number) {
|
||||
|
||||
if('graph' in index) {
|
||||
const curr = _.get(state.unreads.graph, [index.graph.graph, index.graph.index, statField], 0);
|
||||
const curr: any = _.get(state.unreads.graph, [index.graph.graph, index.graph.index, statField], 0);
|
||||
_.set(state.unreads.graph, [index.graph.graph, index.graph.index, statField], f(curr));
|
||||
} else if('group' in index) {
|
||||
const curr = _.get(state.unreads.group, [index.group.group, statField], 0);
|
||||
const curr: any = _.get(state.unreads.group, [index.group.group, statField], 0);
|
||||
_.set(state.unreads.group, [index.group.group, statField], f(curr));
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ export default class LaunchReducer {
|
||||
]);
|
||||
}
|
||||
|
||||
const weatherData: WeatherState = _.get(json, 'weather', false);
|
||||
const weatherData: WeatherState | boolean | Record<string, never> = _.get(json, 'weather', false);
|
||||
if (weatherData) {
|
||||
useLaunchState.getState().set(state => {
|
||||
state.weather = weatherData;
|
||||
|
@ -1,7 +1,8 @@
|
||||
import _ from 'lodash';
|
||||
import useSettingsState, { SettingsState } from "~/logic/state/settings";
|
||||
import { SettingsUpdate } from '@urbit/api/dist/settings';
|
||||
import useSettingsState, { SettingsState } from '~/logic/state/settings';
|
||||
import { SettingsUpdate } from '@urbit/api/settings';
|
||||
import { reduceState } from '../state/base';
|
||||
import { string } from 'prop-types';
|
||||
|
||||
export default class SettingsReducer {
|
||||
reduce(json: any) {
|
||||
@ -40,21 +41,21 @@ export default class SettingsReducer {
|
||||
return state;
|
||||
}
|
||||
|
||||
putEntry(json: SettingsUpdate, state: SettingsState): SettingsState {
|
||||
const data = _.get(json, 'put-entry', false);
|
||||
putEntry(json: SettingsUpdate, state: any): SettingsState {
|
||||
const data: Record<string, string> = _.get(json, 'put-entry', false);
|
||||
if (data) {
|
||||
if (!state[data["bucket-key"]]) {
|
||||
state[data["bucket-key"]] = {};
|
||||
if (!state[data['bucket-key']]) {
|
||||
state[data['bucket-key']] = {};
|
||||
}
|
||||
state[data["bucket-key"]][data["entry-key"]] = data.value;
|
||||
state[data['bucket-key']][data['entry-key']] = data.value;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
delEntry(json: SettingsUpdate, state: SettingsState): SettingsState {
|
||||
delEntry(json: SettingsUpdate, state: any): SettingsState {
|
||||
const data = _.get(json, 'del-entry', false);
|
||||
if (data) {
|
||||
delete state[data["bucket-key"]][data["entry-key"]];
|
||||
delete state[data['bucket-key']][data['entry-key']];
|
||||
}
|
||||
return state;
|
||||
}
|
||||
@ -76,7 +77,7 @@ export default class SettingsReducer {
|
||||
return state;
|
||||
}
|
||||
|
||||
getEntry(json: any, state: SettingsState) {
|
||||
getEntry(json: any, state: any) {
|
||||
const bucketKey = _.get(json, 'bucket-key', false);
|
||||
const entryKey = _.get(json, 'entry-key', false);
|
||||
const entry = _.get(json, 'entry', false);
|
||||
|
@ -9,7 +9,7 @@ export interface LaunchState extends BaseState<LaunchState> {
|
||||
tiles: {
|
||||
[app: string]: Tile;
|
||||
},
|
||||
weather: WeatherState | null,
|
||||
weather: WeatherState | null | Record<string, never> | boolean,
|
||||
userLocation: string | null;
|
||||
baseHash: string | null;
|
||||
};
|
||||
|
@ -3,10 +3,8 @@ import _ from 'lodash';
|
||||
import BaseStore from './base';
|
||||
import InviteReducer from '../reducers/invite-update';
|
||||
import MetadataReducer from '../reducers/metadata-update';
|
||||
import LocalReducer from '../reducers/local';
|
||||
|
||||
import { StoreState } from './type';
|
||||
import { Timebox } from '@urbit/api';
|
||||
import { Cage } from '~/types/cage';
|
||||
import S3Reducer from '../reducers/s3-update';
|
||||
import { GraphReducer } from '../reducers/graph-update';
|
||||
@ -17,8 +15,6 @@ import LaunchReducer from '../reducers/launch-update';
|
||||
import ConnectionReducer from '../reducers/connection';
|
||||
import SettingsReducer from '../reducers/settings-update';
|
||||
import GcpReducer from '../reducers/gcp-reducer';
|
||||
import { OrderedMap } from '../lib/OrderedMap';
|
||||
import { BigIntOrderedMap } from '../lib/BigIntOrderedMap';
|
||||
import { GroupViewReducer } from '../reducers/group-view';
|
||||
import { unstable_batchedUpdates } from 'react-dom';
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user