diff --git a/src/App.tsx b/src/App.tsx index cb97aa1..3cc7d56 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -10,6 +10,7 @@ import i18nextInstance from '@/i18n/i18n'; import { I18NextProvider } from '@/i18n/useTranslation'; const Home = lazy(() => import('@/pages/Home')); +const Permalink = lazy(() => import('@/pages/Permalink')); const Hello = lazy(() => import('@/pages/Hello')); const NotFound = lazy(() => import('@/pages/NotFound')); @@ -52,6 +53,7 @@ const App: Component = () => { } /> } /> + } /> } /> diff --git a/src/components/column/Columns.tsx b/src/components/column/Columns.tsx index 30ea38d..1a6086e 100644 --- a/src/components/column/Columns.tsx +++ b/src/components/column/Columns.tsx @@ -13,7 +13,7 @@ const Columns = () => { const { config } = useConfig(); return ( -
+
{(column, index) => { const columnIndex = () => index() + 1; diff --git a/src/components/modal/GlobalModal.tsx b/src/components/modal/GlobalModal.tsx index 2f0ed76..49afb9c 100644 --- a/src/components/modal/GlobalModal.tsx +++ b/src/components/modal/GlobalModal.tsx @@ -1,4 +1,4 @@ -import { Show, Switch, Match } from 'solid-js'; +import { Show, Switch, Match, Component } from 'solid-js'; import About from '@/components/modal/About'; import AddColumn from '@/components/modal/AddColumn'; @@ -8,7 +8,7 @@ import useModalState from '@/hooks/useModalState'; import usePubkey from '@/nostr/usePubkey'; import ensureNonNull from '@/utils/ensureNonNull'; -const GlobalModal = () => { +const GlobalModal: Component = () => { const pubkey = usePubkey(); const { modalState, showProfile, closeModal } = useModalState(); diff --git a/src/components/modal/ProfileDisplay.tsx b/src/components/modal/ProfileDisplay.tsx index fe752fa..e5a1491 100644 --- a/src/components/modal/ProfileDisplay.tsx +++ b/src/components/modal/ProfileDisplay.tsx @@ -243,28 +243,32 @@ const ProfileDisplay: Component = (props) => { return ( props.onClose?.()}> - loading}> - } keyed> - {(bannerUrl) => ( -
- header -
- )} -
-
-
-
- - {(pictureUrl) => ( - user icon - )} - -
+ } + keyed + > + {(bannerUrl) => ( +
+ header
+ )} +
+
+
+
+ + {(pictureUrl) => ( + user icon + )} + +
+
+
@@ -284,7 +288,7 @@ const ProfileDisplay: Component = (props) => { - {i18n()('profile.loading')} + {i18n()('general.loading')} @@ -323,105 +327,106 @@ const ProfileDisplay: Component = (props) => {
-
{i18n()('profile.loading')}
+
{i18n()('general.loading')}
{i18n()('profile.followsYou')}
-
-
-
- 0}> -
{profile()?.display_name}
-
-
- 0}> -
@{profile()?.name}
-
- 0}> -
- {nip05Identifier()?.ident} - - - - } - > - - - - - - - - - - - -
-
-
-
-
{npub()}
-
-
-
- 0}> -
- {profile()?.about} -
-
-
+
+
+ {i18n()('general.loading')} + 0}> +
{profile()?.display_name}
+
+
+ 0}> +
@{profile()?.name}
+
+ 0}> +
+ {nip05Identifier()?.ident} + + + + } + > + + + + + + + + + + + +
+
+
+
+
{npub()}
+
+
+
+ 0}> +
+ {profile()?.about} +
+
+
+ + +
+
フォロワー
読み込み中} + when={showFollowers()} + fallback={ + + } + keyed > - {userFollowingPubkeys().length} +
- - -
-
フォロワー
-
- setShowFollowers(true)} - > - 読み込む - - } - keyed - > - - -
-
-
-
- 0}> -
    - - {(website) => ( -
  • - - - - -
  • - )} -
    -
+
+
+ 0}> +
    + + {(website) => ( +
  • + + + + +
  • + )} +
    +
diff --git a/src/core/useConfig.ts b/src/core/useConfig.ts index 4d6388f..ec8b040 100644 --- a/src/core/useConfig.ts +++ b/src/core/useConfig.ts @@ -78,8 +78,8 @@ const InitialConfig = (): Config => ({ customEmojis: {}, dateFormat: 'relative', keepOpenPostForm: false, - useEmojiReaction: false, - showEmojiReaction: false, + useEmojiReaction: true, + showEmojiReaction: true, showMedia: true, hideCount: false, mutedPubkeys: [], @@ -92,7 +92,7 @@ const deserializer = (json: string): Config => ({ ...InitialConfig(), ...JSON.parse(json), - } as Config); + }) as Config; const storage = createStorageWithSerializer(() => window.localStorage, serializer, deserializer); const [config, setConfig] = createStoreWithStorage('RabbitConfig', InitialConfig(), storage); diff --git a/src/hooks/useModalState.ts b/src/hooks/useModalState.ts index 6246c57..b28839a 100644 --- a/src/hooks/useModalState.ts +++ b/src/hooks/useModalState.ts @@ -1,6 +1,7 @@ import { createSignal } from 'solid-js'; type ModalState = + | { type: 'Login' } | { type: 'Profile'; pubkey: string } | { type: 'ProfileEdit' } | { type: 'UserTimeline'; pubkey: string } @@ -11,6 +12,9 @@ type ModalState = const [modalState, setModalState] = createSignal({ type: 'Closed' }); const useModalState = () => { + const showLogin = () => { + setModalState({ type: 'Login' }); + }; const showProfile = (pubkey: string) => { setModalState({ type: 'Profile', pubkey }); }; @@ -29,6 +33,7 @@ const useModalState = () => { return { modalState, setModalState, + showLogin, showProfile, showProfileEdit, showAddColumn, diff --git a/src/locales/en.ts b/src/locales/en.ts index 949247e..6bb2381 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -1,6 +1,10 @@ import ja from '@/locales/ja'; export default { + general: { + loading: 'Loading', + updating: 'Updating', + }, posting: { placeholder: "What's happening?", contentWarning: 'Content warning', @@ -34,8 +38,6 @@ export default { following: 'Following', followers: 'Followers', loadFollowers: 'Load', - loading: 'Loading', - updating: 'Updating', editProfile: 'Edit', follow: 'Follow', unfollow: 'Unfollow', diff --git a/src/locales/ja.ts b/src/locales/ja.ts index a777da0..5cb7e84 100644 --- a/src/locales/ja.ts +++ b/src/locales/ja.ts @@ -1,4 +1,8 @@ export default { + general: { + loading: '読み込み中', + updating: '更新中', + }, posting: { placeholder: 'いまどうしてる?', contentWarning: 'コンテンツ警告を設定', @@ -32,8 +36,6 @@ export default { following: 'フォロー', followers: 'フォロワー', loadFollowers: '読み込む', - loading: '読み込み中', - updating: '更新中', editProfile: '編集', follow: 'フォロー', unfollow: 'フォロー解除', diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index 5ab3cd1..7719c4d 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -6,6 +6,7 @@ import Columns from '@/components/column/Columns'; import GlobalModal from '@/components/modal/GlobalModal'; import SideBar from '@/components/SideBar'; import useConfig from '@/core/useConfig'; +import useModalState from '@/hooks/useModalState'; import usePersistStatus from '@/hooks/usePersistStatus'; import { useMountShortcutKeys } from '@/hooks/useShortcutKeys'; import usePool from '@/nostr/usePool'; diff --git a/src/pages/Permalink.tsx b/src/pages/Permalink.tsx new file mode 100644 index 0000000..efee4fb --- /dev/null +++ b/src/pages/Permalink.tsx @@ -0,0 +1,55 @@ +import { createEffect, onMount } from 'solid-js'; + +import { useNavigate, useParams } from '@solidjs/router'; +import { nip19 } from 'nostr-tools'; + +import GlobalModal from '@/components/modal/GlobalModal'; +import SideBar from '@/components/SideBar'; +import useModalState from '@/hooks/useModalState'; +import usePersistStatus from '@/hooks/usePersistStatus'; + +const Permalink = () => { + const navigate = useNavigate(); + const params = useParams(); + const { modalState, showProfile } = useModalState(); + const { persistStatus } = usePersistStatus(); + + const navigateTop = () => { + if (persistStatus().loggedIn) { + navigate('/'); + } else { + navigate('/hello'); + } + }; + + onMount(() => { + if (params.id != null) { + try { + const decoded = nip19.decode(params.id); + if (decoded.type === 'npub') { + showProfile(decoded.data); + } + } catch (err) { + window.alert('Invalid ID'); + navigateTop(); + } + } else { + navigateTop(); + } + }); + + createEffect(() => { + if (modalState().type === 'Closed') { + navigateTop(); + } + }); + + return ( +
+ + +
+ ); +}; + +export default Permalink;