diff --git a/packages/client/src/components/app.tsx b/packages/client/src/components/app.tsx index 1c8744d..57ae994 100644 --- a/packages/client/src/components/app.tsx +++ b/packages/client/src/components/app.tsx @@ -129,8 +129,8 @@ export function App(): JSX.Element { } setInitUserData( await createUserData( - res.data.token as GA.TokenMasterFragment, // TODO: ここのキャストおかしい - ), + res.data.token as GA.TokenMasterFragment // TODO: ここのキャストおかしい + ) ); } catch { setInitUserData(null); @@ -340,50 +340,49 @@ export function App(): JSX.Element { /> - - {location.state?.background ? ( - - ) : null} - {location.state?.background ? ( - - ) : null} - {location.state?.background ? ( - - ) : null} - {location.state?.background ? ( - - ) : null} - {location.state?.background ? ( - - ) : null} - {location.state?.background ? ( - - ) : null} - {location.state?.background ? ( - - ) : null} + {location.state?.background ? ( + + ) : null} + {location.state?.background ? ( + + ) : null} + {location.state?.background ? ( + + ) : null} + {location.state?.background ? ( + + ) : null} + {location.state?.background ? ( + + ) : null} + {location.state?.background ? ( + + ) : null} + {location.state?.background ? ( + + ) : null} ); diff --git a/packages/client/src/components/page.tsx b/packages/client/src/components/page.tsx index fbe5b6e..fde6ca3 100644 --- a/packages/client/src/components/page.tsx +++ b/packages/client/src/components/page.tsx @@ -1,4 +1,4 @@ -import { Icon, IconButton } from "@mui/material"; +import { CircularProgress, Icon, IconButton } from "@mui/material"; import React, { useState } from "react"; import * as style from "./page.module.scss"; @@ -33,7 +33,11 @@ export const Page: React.FC = ({ setIsLeft(!isLeft)}> {isLeft ? "chevron_left" : "chevron_right"} - {isLeft ? sidebar : null} + {isLeft ? ( + }> + {sidebar} + + ) : null} ) : null}
= ({ }} className={!disableScroll ? style.mainScroll : undefined} > - {children} + }> + {children} +
); diff --git a/packages/client/src/components/res.tsx b/packages/client/src/components/res.tsx index a08e461..453c091 100644 --- a/packages/client/src/components/res.tsx +++ b/packages/client/src/components/res.tsx @@ -13,10 +13,7 @@ import { Snack } from "./snack"; import { isNullish } from "../utils/isNullish"; import { useBackground } from "../hooks/useBackground"; import { NG, NGs, TextMatcher } from "../domains/entities/storage/NGs"; -import { - useSetStorage, - usePrefixedStorageCollection, -} from "../domains/entities/storage/StorageCollectionHooks"; +import { useSetStorage } from "../domains/entities/storage/StorageCollectionHooks"; function textMatcher(matcher: TextMatcher, text: string): boolean { if (matcher.text.length === 0) { @@ -26,7 +23,7 @@ function textMatcher(matcher: TextMatcher, text: string): boolean { try { return new RegExp( matcher.text, - [matcher.ignoreCase ? "i" : ""].join(""), + [matcher.ignoreCase ? "i" : ""].join("") ).test(text); } catch { return false; @@ -105,6 +102,7 @@ function isNG(ng: NG, res: GA.ResFragment): boolean { interface ResProps { res: GA.ResFragment; update?: (res: GA.ResFragment) => void; + ngs: NG[]; } export const Res = React.memo(function Res(props: ResProps) { @@ -129,13 +127,13 @@ export const Res = React.memo(function Res(props: ResProps) { }; const [submitVote] = GA.useVoteResMutation(); - const ngs = usePrefixedStorageCollection(NGs); const [addNG] = useSetStorage(NGs); + const ng = React.useMemo( + () => props.ngs.some((ng) => isNG(ng, props.res)), + [props.ngs, props.res] + ); - return user.value !== null && - !props.res.self && - !disableNG && - ngs.some((ng) => isNG(ng, props.res)) ? ( + return user.value !== null && !props.res.self && !disableNG && ng ? ( あぼーん setDisableNG(true)}>[見る] @@ -246,7 +244,7 @@ export const Res = React.memo(function Res(props: ResProps) { state: { background, }, - }, + } )} > @{props.res.profile.sn} @@ -256,7 +254,7 @@ export const Res = React.memo(function Res(props: ResProps) { {dateFormat.format(props.res.date)} @@ -269,7 +267,7 @@ export const Res = React.memo(function Res(props: ResProps) { state: { background, }, - }, + } )} > #{props.res.hash.substr(0, 6)} @@ -357,7 +355,7 @@ export const Res = React.memo(function Res(props: ResProps) { component={Link} to={routes.res.to( { id: props.res.reply.id, topic: props.res.topic.id }, - { state: { background } }, + { state: { background } } )} style={small} size="small" @@ -371,7 +369,7 @@ export const Res = React.memo(function Res(props: ResProps) { component={Link} to={routes.resReply.to( { id: props.res.id, topic: props.res.topic.id }, - { state: { background } }, + { state: { background } } )} style={small} size="small" diff --git a/packages/client/src/components/tags-input.tsx b/packages/client/src/components/tags-input.tsx index ef0ebd9..ab8903b 100644 --- a/packages/client/src/components/tags-input.tsx +++ b/packages/client/src/components/tags-input.tsx @@ -1,7 +1,6 @@ import { Chip, TextField, Autocomplete, Icon } from "@mui/material"; import * as React from "react"; import * as GA from "../generated/graphql-apollo"; -import { Snack } from "./snack"; import { useDeleteStorage, useSetStorage, @@ -16,20 +15,16 @@ export interface TagsInputProps { } export function TagsInput({ value, onChange, fullWidth }: TagsInputProps) { + // TODO: Suspenseが起きる範囲を狭くする const favoTags = usePrefixedStorageCollection(FavoriteTags); const tagsSet = React.useMemo(() => { return new Set([...favoTags.map((t) => t.tag)]); }, [favoTags]); const [deleteTag] = useDeleteStorage(FavoriteTags); const [setTag] = useSetStorage(FavoriteTags); - const { data, loading, error } = GA.useFindTopicTagsQuery(); + const { data, loading } = GA.useFindTopicTagsQuery(); - if (loading) { - return Loading...; - } - if (error || !data) { - return ; - } + // TODO: `useFindTopicTagsQuery` error handling return ( @@ -37,8 +32,9 @@ export function TagsInput({ value, onChange, fullWidth }: TagsInputProps) { placeholder="タグ" freeSolo multiple - options={data.topicTags.map((t) => t.name)} + options={data?.topicTags.map((t) => t.name) ?? []} renderInput={(params) => } + loading={loading} renderTags={(value: string[], getTagProps) => value.map((option: string, index: number) => ( { - {tabIndex === 0 ? : null} - {tabIndex === 1 ? : null} + }> + {tabIndex === 0 ? : null} + {tabIndex === 1 ? : null} + ) : ( diff --git a/packages/client/src/pages/notifications.tsx b/packages/client/src/pages/notifications.tsx index 89f2a0c..cd5be85 100644 --- a/packages/client/src/pages/notifications.tsx +++ b/packages/client/src/pages/notifications.tsx @@ -9,11 +9,14 @@ import { RA, O } from "../prelude"; import { useRegisterSW } from "virtual:pwa-register/react"; import { Env } from "../env"; import { Snack } from "../components/snack"; +import { usePrefixedStorageCollection } from "../domains/entities/storage/StorageCollectionHooks"; +import { NGs } from "../domains/entities/storage/NGs"; type NotificationsPageProps = RouteComponentProps<{}> & UserSwitchProps; export const NotificationsPage = userSwitch( (_props: NotificationsPageProps) => { + const ngs = usePrefixedStorageCollection(NGs); const [registration, setRegistration] = React.useState< ServiceWorkerRegistration | undefined >(undefined); @@ -130,7 +133,9 @@ export const NotificationsPage = userSwitch(
{reses.data !== undefined - ? reses.data.reses.map((r) => ) + ? reses.data.reses.map((r) => ( + + )) : null}
@@ -173,5 +178,5 @@ export const NotificationsPage = userSwitch(
); - }, + } ); diff --git a/packages/client/src/pages/res-hash.tsx b/packages/client/src/pages/res-hash.tsx index a56f5df..f9b06f0 100644 --- a/packages/client/src/pages/res-hash.tsx +++ b/packages/client/src/pages/res-hash.tsx @@ -3,11 +3,14 @@ import { useTitle } from "react-use"; import { Page, Res, Snack } from "../components"; import * as GA from "../generated/graphql-apollo"; import { withModal } from "../utils"; +import { usePrefixedStorageCollection } from "../domains/entities/storage/StorageCollectionHooks"; +import { NGs } from "../domains/entities/storage/NGs"; function ResHashBase(_props: {}) { const params = useParams<{ hash: string }>(); const hash = decodeURIComponent(params.hash); const resesResult = GA.useFindResesQuery({ variables: { query: { hash } } }); + const ngs = usePrefixedStorageCollection(NGs); useTitle(`HASH:${hash}`); return ( @@ -17,7 +20,9 @@ function ResHashBase(_props: {}) { ) : null} {resesResult.data !== undefined - ? resesResult.data.reses.map((res) => ) + ? resesResult.data.reses.map((res) => ( + + )) : undefined} ); diff --git a/packages/client/src/pages/res-reply.tsx b/packages/client/src/pages/res-reply.tsx index 1cd29db..0d2f883 100644 --- a/packages/client/src/pages/res-reply.tsx +++ b/packages/client/src/pages/res-reply.tsx @@ -3,12 +3,15 @@ import { useParams } from "react-router-dom"; import { Page, Res, Snack } from "../components"; import * as GA from "../generated/graphql-apollo"; import { withModal } from "../utils"; +import { usePrefixedStorageCollection } from "../domains/entities/storage/StorageCollectionHooks"; +import { NGs } from "../domains/entities/storage/NGs"; function ResReplyBase() { const { id } = useParams<{ id: string }>(); const { loading, error, data } = GA.useFindResesQuery({ variables: { query: { reply: id } }, }); + const ngs = usePrefixedStorageCollection(NGs); return (
@@ -19,7 +22,7 @@ function ResReplyBase() { ) : ( <> {data.reses.map((res) => ( - + ))} )} diff --git a/packages/client/src/pages/res.tsx b/packages/client/src/pages/res.tsx index db18220..b76d238 100644 --- a/packages/client/src/pages/res.tsx +++ b/packages/client/src/pages/res.tsx @@ -3,6 +3,8 @@ import { useParams } from "react-router-dom"; import { Page, Res, Snack } from "../components"; import * as GA from "../generated/graphql-apollo"; import { withModal } from "../utils"; +import { usePrefixedStorageCollection } from "../domains/entities/storage/StorageCollectionHooks"; +import { NGs } from "../domains/entities/storage/NGs"; interface ResBaseProps { zDepth?: number; @@ -14,6 +16,7 @@ function ResBase({ zDepth: _zDepth }: ResBaseProps) { const { loading, error, data } = GA.useFindResesQuery({ variables: { query: { id: [id] } }, }); + const ngs = usePrefixedStorageCollection(NGs); return (
@@ -22,7 +25,7 @@ function ResBase({ zDepth: _zDepth }: ResBaseProps) { {error || !data || data.reses.length === 0 ? ( ) : ( - + )}
); diff --git a/packages/client/src/pages/topic/view.tsx b/packages/client/src/pages/topic/view.tsx index 17aaf38..04aef20 100644 --- a/packages/client/src/pages/topic/view.tsx +++ b/packages/client/src/pages/topic/view.tsx @@ -28,11 +28,13 @@ import { epic } from "./epic"; import { useBackground } from "../../hooks/useBackground"; import { useDeleteStorage, + usePrefixedStorageCollection, useSetStorage, useSingleStorage, } from "../../domains/entities/storage/StorageCollectionHooks"; import { FavoriteTopics } from "../../domains/entities/storage/FavoriteTopics"; import { TopicReads } from "../../domains/entities/storage/TopicReads"; +import { NGs } from "../../domains/entities/storage/NGs"; export const TopicPage = (_props: {}) => { const params = useParams<{ id: string }>(); @@ -42,7 +44,7 @@ export const TopicPage = (_props: {}) => { { topicId: params.id, }, - null, + null ); const [setTopicRead] = useSetStorage(TopicReads); const user = useUserContext(); @@ -60,8 +62,9 @@ export const TopicPage = (_props: {}) => { apolloClient: apolloClient, setTopicRead, initTopicDate: topicRead?.resCreatedAt, - }, + } ); + const ngs = usePrefixedStorageCollection(NGs); React.useEffect(() => { dispatch({ @@ -81,7 +84,7 @@ export const TopicPage = (_props: {}) => { const reversedReses = React.useMemo( () => (state.reses !== null ? RA.reverse(state.reses) : null), - [state.reses], + [state.reses] ); const handleUpdateRes = React.useCallback((res: GA.ResFragment) => { @@ -204,7 +207,7 @@ export const TopicPage = (_props: {}) => { { id: state.topicId, }, - { state: { background } }, + { state: { background } } )} > 詳細データ @@ -218,7 +221,7 @@ export const TopicPage = (_props: {}) => { { id: state.topicId, }, - { state: { background } }, + { state: { background } } )} > トピック編集 @@ -232,7 +235,7 @@ export const TopicPage = (_props: {}) => { { id: state.topicId, }, - { state: { background } }, + { state: { background } } )} > 派生トピック @@ -316,7 +319,9 @@ export const TopicPage = (_props: {}) => { itemToKey={(res) => res.id} - renderItem={(res) => } + renderItem={(res) => ( + + )} className={style.reses} items={reversedReses} jumpItemKey={state.jumpResId} diff --git a/packages/client/src/utils/with-modal.tsx b/packages/client/src/utils/with-modal.tsx index 34e7109..897df2f 100644 --- a/packages/client/src/utils/with-modal.tsx +++ b/packages/client/src/utils/with-modal.tsx @@ -1,10 +1,11 @@ import * as React from "react"; import { useHistory } from "react-router"; import { Modal } from "../components"; +import { CircularProgress } from "@mui/material"; export const withModal =

( Page: React.ComponentType

, - title: string, + title: string ) => { return (props: P): JSX.Element => { const history = useHistory(); @@ -12,13 +13,15 @@ export const withModal =

( () => () => { history.goBack(); }, - [history], + [history] ); return (

{title}

- {React.createElement(Page, props)} + }> + {React.createElement(Page, props)} + ); };