This commit is contained in:
Ren Amamiya 2023-06-03 08:45:47 +07:00
parent e2491e47c0
commit 6e1fa10402
12 changed files with 104 additions and 76 deletions

View File

@ -16,7 +16,7 @@ tauri-build = { version = "1.2", features = [] }
[dependencies]
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
tauri = { version = "1.2", features = ["clipboard-read-text", "clipboard-write-text", "dialog-open", "fs-read-dir", "fs-read-file", "http-all", "http-multipart", "notification-all", "os-all", "shell-open", "system-tray", "updater", "window-close", "window-start-dragging"] }
tauri = { version = "1.2", features = ["clipboard-read-text", "clipboard-write-text", "dialog-open", "fs-read-dir", "fs-read-file", "http-all", "http-multipart", "notification-all", "os-all", "process-relaunch", "shell-open", "system-tray", "updater", "window-close", "window-start-dragging"] }
tauri-plugin-single-instance = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
tauri-plugin-store = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "dev" }
sqlx-cli = {version = "0.6.3", default-features = false, features = ["sqlite"] }

View File

@ -60,6 +60,12 @@
"window": {
"startDragging": true,
"close": true
},
"process": {
"all": false,
"exit": false,
"relaunch": true,
"relaunchDangerousAllowSymlinkMacos": false
}
},
"bundle": {

View File

@ -1,10 +1,12 @@
import { EyeOffIcon, EyeOnIcon } from "@shared/icons";
import { createAccount } from "@utils/storage";
import { useActiveAccount } from "@stores/accounts";
import { generatePrivateKey, getPublicKey, nip19 } from "nostr-tools";
import { useMemo, useState } from "react";
import { navigate } from "vite-plugin-ssr/client/router";
export function Page() {
const createAccount = useActiveAccount((state: any) => state.create);
const [type, setType] = useState("password");
const privkey = useMemo(() => generatePrivateKey(), []);
@ -22,11 +24,8 @@ export function Page() {
};
const submit = async () => {
const account = await createAccount(npub, pubkey, privkey, null, 1);
if (account) {
navigate("/app/auth/create/step-2");
}
createAccount(npub, pubkey, privkey, null, 1);
navigate("/app/auth/create/step-2");
};
return (

View File

@ -10,11 +10,8 @@ import { navigate } from "vite-plugin-ssr/client/router";
export function Page() {
const pool: any = useContext(RelayContext);
const account = useActiveAccount((state: any) => state.account);
const [account, fetchAccount] = useActiveAccount((state: any) => [
state.account,
state.fetch,
]);
const [image, setImage] = useState(DEFAULT_AVATAR);
const [loading, setLoading] = useState(false);
@ -52,10 +49,6 @@ export function Page() {
);
};
useEffect(() => {
fetchAccount();
}, [fetchAccount]);
useEffect(() => {
setValue("picture", image);
}, [setValue, image]);

View File

@ -3,7 +3,6 @@ import { CheckCircleIcon } from "@shared/icons";
import { RelayContext } from "@shared/relayProvider";
import { useActiveAccount } from "@stores/accounts";
import { WRITEONLY_RELAYS } from "@stores/constants";
import { updateAccount } from "@utils/storage";
import { arrayToNIP02 } from "@utils/transform";
import { getEventHash, getSignature } from "nostr-tools";
import { useContext, useState } from "react";
@ -130,11 +129,8 @@ export function Page() {
const submit = async () => {
setLoading(true);
// update account follows in database
updateAccount("follows", follows, account.pubkey);
// update account follows in state
updateFollows(JSON.stringify(follows));
// update account follows
updateFollows(follows);
const tags = arrayToNIP02(follows);
@ -155,7 +151,7 @@ export function Page() {
// redirect to step 3
setTimeout(
() =>
navigate("/app/prefetch", {
navigate("/", {
overwriteLastHistoryEntry: true,
}),
2000,

View File

@ -1,4 +1,4 @@
import { createAccount } from "@utils/storage";
import { useActiveAccount } from "@stores/accounts";
import { getPublicKey, nip19 } from "nostr-tools";
import { Resolver, useForm } from "react-hook-form";
import { navigate } from "vite-plugin-ssr/client/router";
@ -22,6 +22,7 @@ const resolver: Resolver<FormValues> = async (values) => {
};
export function Page() {
const createAccount = useActiveAccount((state: any) => state.create);
const {
register,
setError,
@ -41,11 +42,8 @@ export function Page() {
const pubkey = getPublicKey(privkey);
const npub = nip19.npubEncode(pubkey);
const account = await createAccount(npub, pubkey, privkey, null, 1);
if (account) {
navigate("/app/auth/import/step-2");
}
createAccount(npub, pubkey, privkey, null, 1);
navigate("/app/auth/import/step-2");
}
} catch (error) {
setError("key", {

View File

@ -1,31 +1,31 @@
import { User } from "@app/auth/components/user";
import { RelayContext } from "@shared/relayProvider";
import { useActiveAccount } from "@stores/accounts";
import { READONLY_RELAYS } from "@stores/constants";
import { updateAccount } from "@utils/storage";
import { METADATA_RELAY } from "@stores/constants";
import { nip02ToArray } from "@utils/transform";
import { useContext, useEffect, useState } from "react";
import { useContext, useState } from "react";
import useSWRSubscription from "swr/subscription";
import { navigate } from "vite-plugin-ssr/client/router";
export function Page() {
const pool: any = useContext(RelayContext);
const [account, fetchAccount, updateFollows] = useActiveAccount(
(state: any) => [state.account, state.fetch, state.updateFollows],
);
const [account, updateFollows] = useActiveAccount((state: any) => [
state.account,
state.updateFollows,
]);
const [loading, setLoading] = useState(false);
const [follows, setFollows] = useState([]);
const [follows, setFollows] = useState(null);
useSWRSubscription(account ? account.pubkey : null, (key: string) => {
useSWRSubscription(account ? ["follows", account.pubkey] : null, () => {
const unsubscribe = pool.subscribe(
[
{
kinds: [3],
authors: [key],
authors: [account.pubkey],
},
],
READONLY_RELAYS,
METADATA_RELAY,
(event: any) => {
setFollows(event.tags);
},
@ -43,23 +43,13 @@ export function Page() {
// follows as list
const followsList = nip02ToArray(follows);
// update account follows in database
updateAccount("follows", followsList, account.pubkey);
// update account follows in store
updateFollows(JSON.stringify(followsList));
updateFollows(followsList);
// redirect to home
setTimeout(
() => navigate("/app/prefetch", { overwriteLastHistoryEntry: true }),
2000,
);
setTimeout(() => navigate("/", { overwriteLastHistoryEntry: true }), 2000);
};
useEffect(() => {
fetchAccount();
}, [fetchAccount]);
return (
<div className="flex h-full w-full items-center justify-center">
<div className="mx-auto w-full max-w-md">

View File

@ -6,19 +6,23 @@ export function Page() {
const fetchLastLogin = useActiveAccount((state: any) => state.fetchLastLogin);
const fetchAccount = useActiveAccount((state: any) => state.fetch);
const account = useActiveAccount((state: any) => state.account);
if (!account && typeof window !== "undefined") {
navigate("/app/auth", { overwriteLastHistoryEntry: true });
}
if (account && typeof window !== "undefined") {
navigate("/app/prefetch", { overwriteLastHistoryEntry: true });
}
const lastLogin = useActiveAccount((state: any) => state.lastLogin);
useEffect(() => {
fetchAccount();
fetchLastLogin();
}, [fetchAccount, fetchLastLogin]);
if (!account) {
navigate("/app/auth", { overwriteLastHistoryEntry: true });
}
if (account) {
navigate("/app/prefetch", { overwriteLastHistoryEntry: true });
}
if (account === null) {
fetchAccount();
}
if (lastLogin === null) {
fetchLastLogin();
}
}, [fetchAccount, fetchLastLogin, account, lastLogin]);
return (
<div className="h-screen w-screen bg-zinc-50 text-zinc-900 dark:bg-black dark:text-white" />

View File

@ -11,7 +11,6 @@ export function NoteReplyForm({ id }: { id: string }) {
const pool: any = useContext(RelayContext);
const account = useActiveAccount((state: any) => state.account);
const { user } = useProfile(account.pubkey);
const [value, setValue] = useState("");
const submitEvent = () => {
@ -35,15 +34,6 @@ export function NoteReplyForm({ id }: { id: string }) {
return (
<div className="flex gap-2.5 py-4">
<div>
<div className="relative h-9 w-9 shrink-0 overflow-hidden rounded-md">
<Image
src={user?.picture}
alt={id}
className="h-9 w-9 rounded-md object-cover"
/>
</div>
</div>
<div className="relative h-24 w-full flex-1 overflow-hidden before:pointer-events-none before:absolute before:-inset-1 before:rounded-[11px] before:border before:border-fuchsia-500 before:opacity-0 before:ring-2 before:ring-fuchsia-500/20 before:transition after:pointer-events-none after:absolute after:inset-px after:rounded-[7px] after:shadow-highlight after:shadow-white/5 after:transition focus-within:before:opacity-100 focus-within:after:shadow-fuchsia-500/100 dark:focus-within:after:shadow-fuchsia-500/20">
<div>
<textarea

View File

@ -19,6 +19,15 @@ if (typeof window !== "undefined") {
totalNotes = await countTotalNotes();
}
function isJSON(str: string) {
try {
JSON.parse(str);
} catch (e) {
return false;
}
return true;
}
export function Page() {
const pool: any = useContext(RelayContext);
const [account, lastLogin] = useActiveAccount((state: any) => [
@ -73,10 +82,17 @@ export function Page() {
since: lastLogin,
});
// long post
query.push({
kinds: [30023],
since: lastLogin,
});
return query;
}, [account]);
useSWRSubscription(account ? "prefetch" : null, () => {
console.log("data prefetching... ", account.pubkey);
const query = getQuery();
const unsubscribe = pool.subscribe(
query,
@ -148,6 +164,7 @@ export function Page() {
addToBlacklist(account.id, event.tags[0][1], 44, 1);
}
break;
// file metadata
case 1063:
createNote(
event.id,
@ -157,9 +174,26 @@ export function Page() {
event.tags,
event.content,
event.created_at,
"",
event.id,
);
break;
// long post
case 30023: {
const verifyMetadata = isJSON(event.tags);
if (verifyMetadata) {
createNote(
event.id,
account.id,
event.pubkey,
event.kind,
event.tags,
event.content,
event.created_at,
"",
);
}
break;
}
default:
break;
}
@ -168,7 +202,10 @@ export function Page() {
() => {
eose.current += 1;
if (eose.current === READONLY_RELAYS.length) {
navigate("/app/space", { overwriteLastHistoryEntry: true });
setTimeout(
() => navigate("/app/space", { overwriteLastHistoryEntry: true }),
2000,
);
}
},
);

View File

@ -1,9 +1,11 @@
import {
addBlockToDB,
createAccount,
getActiveAccount,
getBlocks,
getLastLogin,
removeBlockFromDB,
updateAccount,
} from "@utils/storage";
import { create } from "zustand";
import { createJSONStorage, persist } from "zustand/middleware";
@ -15,7 +17,16 @@ export const useActiveAccount = create(
(set: any, get: any) => ({
account: null,
blocks: null,
lastLogin: 0,
lastLogin: null,
create: async (npub: string, pubkey: string, privkey: string) => {
const response = await createAccount(npub, pubkey, privkey, null, 1);
if (response) {
const activeAccount = await getActiveAccount();
set({
account: activeAccount,
});
}
},
fetch: async () => {
const response = await getActiveAccount();
set({ account: response });
@ -59,8 +70,12 @@ export const useActiveAccount = create(
});
},
updateFollows: (list: any) => {
const account = get().account;
// update db
updateAccount("follows", list, account.pubkey);
// update state
set((state: any) => ({
account: { ...state.account, follows: list },
account: { ...state.account, follows: JSON.stringify(list) },
}));
},
}),

View File

@ -225,7 +225,7 @@ export async function createNote(
) {
const db = await connect();
return await db.execute(
"INSERT OR IGNORE INTO notes (event_id, account_id, pubkey, kind, tags, content, created_at, parent_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?);",
"INSERT INTO notes (event_id, account_id, pubkey, kind, tags, content, created_at, parent_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?);",
[event_id, account_id, pubkey, kind, tags, content, created_at, parent_id],
);
}