diff --git a/src/App.tsx b/src/App.tsx
index c5fa9fd..4a36e23 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,12 +1,27 @@
import { Route, Router } from "@solidjs/router";
import { ThemeProvider } from "@suid/material";
-import { Component, lazy } from "solid-js";
+import {
+ Component,
+ createRenderEffect,
+ createSignal,
+ ErrorBoundary,
+ lazy,
+} from "solid-js";
import { useRootTheme } from "./material/mui.js";
-import "./App.css"
+import {
+ Provider as ClientProvider,
+ createMastoClientFor,
+ type Session,
+} from "./masto/clients.js";
+import "./App.css";
+import { $accounts } from "./accounts/stores.js";
+import { useStore } from "@nanostores/solid";
const AccountSignIn = lazy(() => import("./accounts/SignIn.js"));
-const AccountMastodonOAuth2Callback = lazy(() => import("./accounts/MastodonOAuth2Callback.js"))
-const TimelineHome = lazy(() => import("./timelines/Home.js"))
+const AccountMastodonOAuth2Callback = lazy(
+ () => import("./accounts/MastodonOAuth2Callback.js"),
+);
+const TimelineHome = lazy(() => import("./timelines/Home.js"));
const Routing: Component = () => {
return (
@@ -14,7 +29,10 @@ const Routing: Component = () => {
-
+
);
@@ -22,10 +40,29 @@ const Routing: Component = () => {
const App: Component = () => {
const theme = useRootTheme();
+ const accts = useStore($accounts);
+ const clientStore = createSignal([]);
+
+ createRenderEffect(() => {
+ const [, setClients] = clientStore;
+ setClients(
+ accts().map((x) => ({ account: x, client: createMastoClientFor(x) })),
+ );
+ });
+
return (
-
-
-
+ {
+ console.error(err);
+ return <>>;
+ }}
+ >
+
+
+
+
+
+
);
};
diff --git a/src/accounts/stores.ts b/src/accounts/stores.ts
index 96c6499..fe408f9 100644
--- a/src/accounts/stores.ts
+++ b/src/accounts/stores.ts
@@ -1,9 +1,6 @@
import { persistentAtom } from "@nanostores/persistent";
-import { useStore } from "@nanostores/solid";
-import { useNavigate } from "@solidjs/router";
import { createOAuthAPIClient, createRestAPIClient } from "masto";
import { action } from "nanostores";
-import { createRenderEffect } from "solid-js";
export type Account = {
site: string;
@@ -175,15 +172,3 @@ export const getOrRegisterApp = action(
return all[site];
},
);
-
-export function useAccts() {
- const accts = useStore($accounts);
- const naviagte = useNavigate();
-
- createRenderEffect(() => {
- if (accts().length > 0) return;
- naviagte("/accounts/sign-in");
- });
-
- return accts;
-}
diff --git a/src/masto/acct.ts b/src/masto/acct.ts
index 51c8ea2..eafd297 100644
--- a/src/masto/acct.ts
+++ b/src/masto/acct.ts
@@ -1,9 +1,7 @@
import { Accessor, createResource } from "solid-js";
-import { Account } from "../accounts/stores";
-import { useMastoClientFor } from "./clients";
+import type { mastodon } from "masto";
-export function useAcctProfile(account: Accessor) {
- const client = useMastoClientFor(account)
+export function useAcctProfile(client: Accessor) {
return createResource(client, (client) => {
return client.v1.accounts.verifyCredentials()
}, {
diff --git a/src/masto/clients.ts b/src/masto/clients.ts
index 3ff1be6..9e71b8c 100644
--- a/src/masto/clients.ts
+++ b/src/masto/clients.ts
@@ -1,41 +1,78 @@
-import { Accessor, createMemo, createResource } from "solid-js";
+import {
+ Accessor,
+ createContext,
+ createRenderEffect,
+ createResource,
+ Signal,
+ useContext,
+} from "solid-js";
import { Account } from "../accounts/stores";
import { createRestAPIClient, mastodon } from "masto";
+import { useLocation, useNavigate } from "@solidjs/router";
-const restfulCache: Record = {}
+const restfulCache: Record = {};
export function createMastoClientFor(account: Account) {
- const cacheKey = [account.site, account.accessToken].join('')
- const cache = restfulCache[cacheKey]
+ const cacheKey = [account.site, account.accessToken].join("");
+ const cache = restfulCache[cacheKey];
if (cache) return cache;
const client = createRestAPIClient({
url: account.site,
accessToken: account.accessToken,
- })
- restfulCache[cacheKey] = client
+ });
+ restfulCache[cacheKey] = client;
- return client
-}
-
-export function useMastoClientFor(account: Accessor) {
- return createMemo(() => createMastoClientFor(account()))
+ return client;
}
export function createUnauthorizedClient(site: string) {
- const cache = restfulCache[site]
+ const cache = restfulCache[site];
if (cache) return cache;
const client = createRestAPIClient({
- url: site
- })
- restfulCache[site] = client
+ url: site,
+ });
+ restfulCache[site] = client;
- return client
+ return client;
}
export function useInstance(client: Accessor) {
return createResource(client, async (client) => {
- return await client.v2.instance.fetch()
- })
+ return await client.v2.instance.fetch();
+ });
+}
+
+export type Session = {
+ account: Account;
+ client: mastodon.rest.Client;
+};
+
+const Context = /* @__PURE__ */ createContext>();
+
+export const Provider = Context.Provider;
+
+export function useSessions() {
+ const [sessions] = useSessionsRw();
+ const navigate = useNavigate();
+ const location = useLocation();
+
+ createRenderEffect(() => {
+ if (sessions().length > 0) return;
+ navigate(
+ "/accounts/sign-in?back=" + encodeURIComponent(location.pathname),
+ { replace: true },
+ );
+ });
+
+ return sessions;
+}
+
+export function useSessionsRw() {
+ const store = useContext(Context);
+ if (!store) {
+ throw new TypeError("sessions are not provided");
+ }
+ return store;
}
diff --git a/src/timelines/Home.tsx b/src/timelines/Home.tsx
index 696c0a2..16fa2e1 100644
--- a/src/timelines/Home.tsx
+++ b/src/timelines/Home.tsx
@@ -3,15 +3,12 @@ import {
For,
onCleanup,
createSignal,
- createEffect,
Show,
untrack,
onMount,
} from "solid-js";
-import { $accounts, useAccts } from "../accounts/stores";
import { useDocumentTitle } from "../utils";
-import { useStore } from "@nanostores/solid";
-import { useMastoClientFor } from "../masto/clients";
+import { useSessions } from "../masto/clients";
import { type mastodon } from "masto";
import Scaffold from "../material/Scaffold";
import {
@@ -24,7 +21,6 @@ import {
MenuItem,
Switch,
Toolbar,
- Typography,
} from "@suid/material";
import { css } from "solid-styled";
import { TimeSourceProvider, createTimeSource } from "../platform/timesrc";
@@ -152,11 +148,11 @@ const TimelinePanel: Component<{
const Home: Component = () => {
let panelList: HTMLDivElement;
useDocumentTitle("Timelines");
- const accounts = useAccts();
const now = createTimeSource();
- const client = useMastoClientFor(() => accounts()[0]);
- const [profile] = useAcctProfile(() => accounts()[0]);
+ const sessions = useSessions();
+ const client = () => sessions()[0].client;
+ const [profile] = useAcctProfile(client);
const [panelOffset, setPanelOffset] = createSignal(0);
const [prefetching, setPrefetching] = createSignal(true);