feat: remove /hello page

This commit is contained in:
Shusui MOYATANI
2024-01-22 02:07:36 +09:00
parent ffd9a45681
commit 73ecad8b06
5 changed files with 201 additions and 196 deletions

View File

@@ -1,6 +1,6 @@
import { createEffect, onCleanup, lazy, type Component } from 'solid-js'; import { createEffect, onCleanup, Show, lazy, type Component } from 'solid-js';
import { HashRouter, Route } from '@solidjs/router'; import { HashRouter, Route, Navigate } from '@solidjs/router';
import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister'; import { createAsyncStoragePersister } from '@tanstack/query-async-storage-persister';
import { persistQueryClient } from '@tanstack/query-persist-client-core'; import { persistQueryClient } from '@tanstack/query-persist-client-core';
import { QueryClient, QueryClientProvider } from '@tanstack/solid-query'; import { QueryClient, QueryClientProvider } from '@tanstack/solid-query';
@@ -8,12 +8,13 @@ import { get as getItem, set as setItem, del as removeItem } from 'idb-keyval';
import DomainTransferInfo from '@/components/DomainTransferInfo'; import DomainTransferInfo from '@/components/DomainTransferInfo';
import useColorTheme from '@/hooks/useColorTheme'; import useColorTheme from '@/hooks/useColorTheme';
import usePersistStatus from '@/hooks/usePersistStatus';
import i18nextInstance from '@/i18n/i18n'; import i18nextInstance from '@/i18n/i18n';
import { I18NextProvider } from '@/i18n/useTranslation'; import { I18NextProvider } from '@/i18n/useTranslation';
const Hello = lazy(() => import('@/pages/Hello'));
const Home = lazy(() => import('@/pages/Home')); const Home = lazy(() => import('@/pages/Home'));
const Permalink = lazy(() => import('@/pages/Permalink')); const Permalink = lazy(() => import('@/pages/Permalink'));
const Hello = lazy(() => import('@/pages/Hello'));
const NotFound = lazy(() => import('@/pages/NotFound')); const NotFound = lazy(() => import('@/pages/NotFound'));
const queryClient = new QueryClient({}); const queryClient = new QueryClient({});
@@ -34,6 +35,16 @@ const indexedDBPersister = createAsyncStoragePersister({
}, },
}); });
const EntryPoint: Component = () => {
const { persistStatus } = usePersistStatus();
return (
<Show when={persistStatus().loggedIn} fallback={<Hello />}>
<Home />
</Show>
);
};
const App: Component = () => { const App: Component = () => {
createEffect(() => { createEffect(() => {
const [unsubscribe] = persistQueryClient({ const [unsubscribe] = persistQueryClient({
@@ -51,8 +62,8 @@ const App: Component = () => {
<QueryClientProvider client={queryClient}> <QueryClientProvider client={queryClient}>
<DomainTransferInfo> <DomainTransferInfo>
<HashRouter> <HashRouter>
<Route path="/hello" component={() => <Hello />} /> <Route path="/hello" component={() => <Navigate href="/" />} />
<Route path="/" component={() => <Home />} /> <Route path="/" component={() => <EntryPoint />} />
<Route path="/:id" component={() => <Permalink />} /> <Route path="/:id" component={() => <Permalink />} />
<Route path="/*" component={() => <NotFound />} /> <Route path="/*" component={() => <NotFound />} />
</HashRouter> </HashRouter>

View File

@@ -0,0 +1,180 @@
import { createSignal, For } from 'solid-js';
import ArrowTopRightOnSquare from 'heroicons/24/outline/arrow-top-right-on-square.svg';
import { UAParser } from 'ua-parser-js';
import SafeLink from '@/components/utils/SafeLink';
const Browsers = ['pc-chrome', 'pc-firefox', 'ios', 'android'] as const;
type Browser = (typeof Browsers)[number];
type ExtensionDefinition = {
name: string;
url: string;
browsers: Browser[];
guides: {
title: string;
url: string;
lang: 'ja' | 'en';
}[];
};
const BrowserToString: Record<Browser, string> = {
'pc-chrome': 'Chrome',
'pc-firefox': 'Firefox',
ios: 'iOS',
android: 'Android',
};
const browserAsString = (browser: Browser) => BrowserToString[browser];
const Extensions: ExtensionDefinition[] = [
{
name: 'nos2x',
url: 'https://chrome.google.com/webstore/detail/nos2x/kpgefcfmnafjgpblomihpgmejjdanjjp',
browsers: ['pc-chrome', 'android'],
guides: [
{
title: 'nos2xのセットアップと使い方',
url: 'https://scrapbox.io/nostr/nos2x%E3%81%AE%E3%82%BB%E3%83%83%E3%83%88%E3%82%A2%E3%83%83%E3%83%97%E3%81%A8%E4%BD%BF%E3%81%84%E6%96%B9',
lang: 'ja',
},
],
},
{
name: 'nos2x-fox',
browsers: ['pc-firefox', 'android'],
url: 'https://addons.mozilla.org/firefox/addon/nos2x-fox/',
guides: [
{
title: 'nos2x-foxのセットアップと使い方',
url: 'https://scrapbox.io/nostr/nos2x-fox%E3%81%AE%E3%82%BB%E3%83%83%E3%83%88%E3%82%A2%E3%83%83%E3%83%97%E3%81%A8%E4%BD%BF%E3%81%84%E6%96%B9',
lang: 'ja',
},
],
},
{
name: 'nostore',
browsers: ['ios'],
url: 'https://apps.apple.com/jp/app/nostore/id1666553677',
guides: [
{
title: 'nostore(iOS Safari用NIP-07拡張機能)のセットアップ',
url: 'https://scrapbox.io/nostr/nostore(iOS_Safari%E7%94%A8NIP-07%E6%8B%A1%E5%BC%B5%E6%A9%9F%E8%83%BD)%E3%81%AE%E3%82%BB%E3%83%83%E3%83%88%E3%82%A2%E3%83%83%E3%83%97',
lang: 'ja',
},
],
},
];
const getBrowsers = () => {
const parsed = UAParser(window.navigator.userAgent);
const result = new Set<Browser>();
if (parsed.os.name === 'Android') result.add('android');
if (parsed.os.name === 'iOS') result.add('ios');
if (
(parsed.device.type === undefined || parsed.device.type === 'console') &&
(parsed.browser.name === 'Chromium' ||
parsed.browser.name === 'Chrome' ||
parsed.browser.name === 'Vivaldi' ||
parsed.browser.name === 'Brave')
)
result.add('pc-chrome');
if (parsed.browser.name === 'Firefox') result.add('pc-firefox');
return result;
};
const SignerExtensions = () => {
const [selectedBrowsers, setSelectedBrowsers] = createSignal(getBrowsers());
const toggleBrowser = (browser: Browser) =>
setSelectedBrowsers((current) => {
const newSet = new Set(current);
if (!newSet.has(browser)) newSet.add(browser);
else newSet.delete(browser);
return newSet;
});
const extensions = (): ExtensionDefinition[] => {
const browsers = selectedBrowsers();
if (browsers.size === 0) return Extensions;
return Extensions.filter((extension) =>
extension.browsers.some((browser) => browsers.has(browser)),
);
};
return (
<div>
<div class="pt-2">
<ul class="flex gap-1">
<For each={Browsers}>
{(browser) => (
<li>
<button
class="rounded-xl border px-2 text-sm"
classList={{
'border-fg': selectedBrowsers().has(browser),
'font-bold': selectedBrowsers().has(browser),
'text-fg': selectedBrowsers().has(browser),
'border-border': !selectedBrowsers().has(browser),
'font-normal': !selectedBrowsers().has(browser),
'text-fg-secondary': !selectedBrowsers().has(browser),
}}
type="button"
onClick={() => toggleBrowser(browser)}
>
{browserAsString(browser)}
</button>
</li>
)}
</For>
</ul>
</div>
<div>
<For each={extensions()}>
{(extension) => (
<div class="my-2 flex items-center rounded-lg border border-border p-2">
<div class="flex-1">
<SafeLink
class="font-bold hover:text-fg-secondary hover:underline"
href={extension.url}
>
<h3>{extension.name}</h3>
</SafeLink>
<div class="flex items-center">
<ul class="flex items-center gap-1 text-xs">
<For each={extension.guides}>
{(guide) => (
<li class="text-link underline">
<SafeLink href={guide.url}>{guide.title}</SafeLink>
</li>
)}
</For>
</ul>
</div>
<ul class="flex gap-1 pt-1 text-xs">
<For each={extension.browsers}>
{(browser) => (
<li class="rounded-lg border border-border px-1 text-fg-secondary">
{browserAsString(browser)}
</li>
)}
</For>
</ul>
</div>
<div class="shrink-0" aria-hidden="true">
<SafeLink class="font-bold text-fg-secondary" href={extension.url}>
<span class="ms-1 inline-block size-16 p-5">
<ArrowTopRightOnSquare />
</span>
</SafeLink>
</div>
</div>
)}
</For>
</div>
</div>
);
};
export default SignerExtensions;

View File

@@ -2,7 +2,7 @@ import { createEffect, onCleanup } from 'solid-js';
import useConfig from '@/core/useConfig'; import useConfig from '@/core/useConfig';
export const useColorTheme = (el: HTMLElement) => { const useColorTheme = (el: HTMLElement) => {
const { getColorTheme } = useConfig(); const { getColorTheme } = useConfig();
createEffect(() => { createEffect(() => {

View File

@@ -1,79 +1,14 @@
import { createSignal, onMount, For, Switch, Match, type Component } from 'solid-js'; import { createSignal, onMount, Switch, Match, type Component } from 'solid-js';
import { useNavigate } from '@solidjs/router'; import { useNavigate } from '@solidjs/router';
import ArrowTopRightOnSquare from 'heroicons/24/outline/arrow-top-right-on-square.svg';
import { UAParser } from 'ua-parser-js';
import SafeLink from '@/components/utils/SafeLink'; import SignerExtensions from '@/components/SignerExtensions';
import usePersistStatus from '@/hooks/usePersistStatus'; import usePersistStatus from '@/hooks/usePersistStatus';
import { useTranslation } from '@/i18n/useTranslation'; import { useTranslation } from '@/i18n/useTranslation';
import resolveAsset from '@/utils/resolveAsset'; import resolveAsset from '@/utils/resolveAsset';
type SignerStatus = 'checking' | 'available' | 'unavailable'; type SignerStatus = 'checking' | 'available' | 'unavailable';
const Browsers = ['pc-chrome', 'pc-firefox', 'ios', 'android'] as const;
type Browser = (typeof Browsers)[number];
type ExtensionDefinition = {
name: string;
url: string;
browsers: Browser[];
guides: {
title: string;
url: string;
lang: 'ja' | 'en';
}[];
};
const BrowserToString: Record<Browser, string> = {
'pc-chrome': 'Chrome',
'pc-firefox': 'Firefox',
ios: 'iOS',
android: 'Android',
};
const browserAsString = (browser: Browser) => BrowserToString[browser];
const Extensions: ExtensionDefinition[] = [
{
name: 'nos2x',
url: 'https://chrome.google.com/webstore/detail/nos2x/kpgefcfmnafjgpblomihpgmejjdanjjp',
browsers: ['pc-chrome', 'android'],
guides: [
{
title: 'nos2xのセットアップと使い方',
url: 'https://scrapbox.io/nostr/nos2x%E3%81%AE%E3%82%BB%E3%83%83%E3%83%88%E3%82%A2%E3%83%83%E3%83%97%E3%81%A8%E4%BD%BF%E3%81%84%E6%96%B9',
lang: 'ja',
},
],
},
{
name: 'nos2x-fox',
browsers: ['pc-firefox', 'android'],
url: 'https://addons.mozilla.org/firefox/addon/nos2x-fox/',
guides: [
{
title: 'nos2x-foxのセットアップと使い方',
url: 'https://scrapbox.io/nostr/nos2x-fox%E3%81%AE%E3%82%BB%E3%83%83%E3%83%88%E3%82%A2%E3%83%83%E3%83%97%E3%81%A8%E4%BD%BF%E3%81%84%E6%96%B9',
lang: 'ja',
},
],
},
{
name: 'nostore',
browsers: ['ios'],
url: 'https://apps.apple.com/jp/app/nostore/id1666553677',
guides: [
{
title: 'nostore(iOS Safari用NIP-07拡張機能)のセットアップ',
url: 'https://scrapbox.io/nostr/nostore(iOS_Safari%E7%94%A8NIP-07%E6%8B%A1%E5%BC%B5%E6%A9%9F%E8%83%BD)%E3%81%AE%E3%82%BB%E3%83%83%E3%83%88%E3%82%A2%E3%83%83%E3%83%97',
lang: 'ja',
},
],
},
];
const useSignerStatus = () => { const useSignerStatus = () => {
const [signerStatus, setSignerStatus] = createSignal<SignerStatus>('checking'); const [signerStatus, setSignerStatus] = createSignal<SignerStatus>('checking');
@@ -97,115 +32,6 @@ const useSignerStatus = () => {
return signerStatus; return signerStatus;
}; };
const getBrowsers = () => {
const parsed = UAParser(window.navigator.userAgent);
const result = new Set<Browser>();
if (parsed.os.name === 'Android') result.add('android');
if (parsed.os.name === 'iOS') result.add('ios');
if (
(parsed.device.type === undefined || parsed.device.type === 'console') &&
(parsed.browser.name === 'Chromium' ||
parsed.browser.name === 'Chrome' ||
parsed.browser.name === 'Vivaldi' ||
parsed.browser.name === 'Brave')
)
result.add('pc-chrome');
if (parsed.browser.name === 'Firefox') result.add('pc-firefox');
return result;
};
const ExtensionList = () => {
const [selectedBrowsers, setSelectedBrowsers] = createSignal(getBrowsers());
const toggleBrowser = (browser: Browser) =>
setSelectedBrowsers((current) => {
const newSet = new Set(current);
if (!newSet.has(browser)) newSet.add(browser);
else newSet.delete(browser);
return newSet;
});
const extensions = (): ExtensionDefinition[] => {
const browsers = selectedBrowsers();
if (browsers.size === 0) return Extensions;
return Extensions.filter((extension) =>
extension.browsers.some((browser) => browsers.has(browser)),
);
};
return (
<div>
<div class="pt-2">
<ul class="flex gap-1">
<For each={Browsers}>
{(browser) => (
<li>
<button
class="rounded-xl border px-2 text-sm"
classList={{
'border-fg': selectedBrowsers().has(browser),
'font-bold': selectedBrowsers().has(browser),
'text-fg': selectedBrowsers().has(browser),
'border-border': !selectedBrowsers().has(browser),
'font-normal': !selectedBrowsers().has(browser),
'text-fg-secondary': !selectedBrowsers().has(browser),
}}
type="button"
onClick={() => toggleBrowser(browser)}
>
{browserAsString(browser)}
</button>
</li>
)}
</For>
</ul>
</div>
<div>
<For each={extensions()}>
{(extension) => (
<div class="my-2 flex items-center rounded-lg border border-border p-2">
<div class="flex-1">
<SafeLink
class="font-bold hover:text-fg-secondary hover:underline"
href={extension.url}
>
<h3>{extension.name}</h3>
</SafeLink>
<div class="flex items-center">
<ul class="flex items-center gap-1 text-xs">
<For each={extension.guides}>
{(guide) => (
<li class="text-link underline">
<SafeLink href={guide.url}>{guide.title}</SafeLink>
</li>
)}
</For>
</ul>
</div>
<ul class="flex gap-1 pt-1 text-xs">
<For each={extension.browsers}>
{(browser) => (
<li class="rounded-lg border border-border px-1 text-fg-secondary">
{browserAsString(browser)}
</li>
)}
</For>
</ul>
</div>
<div class="shrink-0" aria-hidden="true">
<SafeLink class="font-bold text-fg-secondary" href={extension.url}>
<span class="ms-1 inline-block size-16 p-5">
<ArrowTopRightOnSquare />
</span>
</SafeLink>
</div>
</div>
)}
</For>
</div>
</div>
);
};
const Hello: Component = () => { const Hello: Component = () => {
const i18n = useTranslation(); const i18n = useTranslation();
const signerStatus = useSignerStatus(); const signerStatus = useSignerStatus();
@@ -238,7 +64,7 @@ const Hello: Component = () => {
<Match when={signerStatus() === 'unavailable'}> <Match when={signerStatus() === 'unavailable'}>
<h2 class="font-bold">{i18n()('hello.signerUnavailable')}</h2> <h2 class="font-bold">{i18n()('hello.signerUnavailable')}</h2>
<p>{i18n()('hello.signerUnavailableMessage')}</p> <p>{i18n()('hello.signerUnavailableMessage')}</p>
<ExtensionList /> <SignerExtensions />
<div class="flex flex-col items-center gap-2"> <div class="flex flex-col items-center gap-2">
<p class="text-sm">{i18n()('hello.reloadAfterInstall')}</p> <p class="text-sm">{i18n()('hello.reloadAfterInstall')}</p>
<button <button

View File

@@ -1,12 +1,9 @@
import { createEffect, onMount, type Component, onError } from 'solid-js'; import { createEffect, type Component, onError } from 'solid-js';
import { useNavigate } from '@solidjs/router';
import Columns from '@/components/column/Columns'; import Columns from '@/components/column/Columns';
import GlobalModal from '@/components/modal/GlobalModal'; import GlobalModal from '@/components/modal/GlobalModal';
import SideBar from '@/components/SideBar'; import SideBar from '@/components/SideBar';
import useConfig from '@/core/useConfig'; import useConfig from '@/core/useConfig';
import usePersistStatus from '@/hooks/usePersistStatus';
import { useMountShortcutKeys } from '@/hooks/useShortcutKeys'; import { useMountShortcutKeys } from '@/hooks/useShortcutKeys';
import usePool from '@/nostr/usePool'; import usePool from '@/nostr/usePool';
import usePubkey from '@/nostr/usePubkey'; import usePubkey from '@/nostr/usePubkey';
@@ -14,9 +11,6 @@ import usePubkey from '@/nostr/usePubkey';
const Home: Component = () => { const Home: Component = () => {
useMountShortcutKeys(); useMountShortcutKeys();
const navigate = useNavigate();
const { persistStatus } = usePersistStatus();
const pool = usePool(); const pool = usePool();
const { config, initializeColumns } = useConfig(); const { config, initializeColumns } = useConfig();
const pubkey = usePubkey(); const pubkey = usePubkey();
@@ -49,12 +43,6 @@ const Home: Component = () => {
} }
}); });
onMount(() => {
if (!persistStatus().loggedIn) {
navigate('/hello');
}
});
onError((err) => { onError((err) => {
console.error('uncaught error: ', err); console.error('uncaught error: ', err);
}); });