fixed sql query

This commit is contained in:
Ren Amamiya 2023-02-26 11:19:18 +07:00
parent a2fcb12eef
commit 3fbe6b3986
7 changed files with 60 additions and 220 deletions

View File

@ -27,11 +27,7 @@ export const User = memo(function User({ pubkey, time }: { pubkey: string; time:
const metadata: any = JSON.parse(rawMetadata.content);
if (profile.picture === null || profile.name === null) {
setProfile(metadata);
await db.execute(
`INSERT OR IGNORE INTO cache_profiles (pubkey, metadata) VALUES ("${pubkey}", '${JSON.stringify(
metadata
)}')`
);
await db.execute(`INSERT OR IGNORE INTO cache_profiles (id, metadata) VALUES ("${pubkey}", '${JSON.stringify(metadata)}')`);
} else {
return;
}
@ -42,9 +38,7 @@ export const User = memo(function User({ pubkey, time }: { pubkey: string; time:
useEffect(() => {
const initialProfile = async () => {
const result: any = await db.select(
`SELECT metadata FROM cache_profiles WHERE pubkey = "${pubkey}"`
);
const result: any = await db.select(`SELECT metadata FROM cache_profiles WHERE id = "${pubkey}"`);
db.close;
return result;
};
@ -62,27 +56,15 @@ export const User = memo(function User({ pubkey, time }: { pubkey: string; time:
<div className="relative flex items-start gap-4">
<div className="relative h-11 w-11 shrink overflow-hidden rounded-full border border-white/10">
{profile.picture ? (
<ImageWithFallback
src={profile.picture}
alt={pubkey}
fill={true}
className="rounded-full object-cover"
/>
<ImageWithFallback src={profile.picture} alt={pubkey} fill={true} className="rounded-full object-cover" />
) : (
<Avatar
size={44}
name={pubkey}
variant="beam"
colors={['#FEE2E2', '#FEF3C7', '#F59E0B', '#EC4899', '#D946EF', '#8B5CF6']}
/>
<Avatar size={44} name={pubkey} variant="beam" colors={['#FEE2E2', '#FEF3C7', '#F59E0B', '#EC4899', '#D946EF', '#8B5CF6']} />
)}
</div>
<div className="flex w-full flex-1 items-start justify-between">
<div className="flex w-full justify-between">
<div className="flex items-baseline gap-2 text-sm">
<span className="font-bold leading-tight">
{profile.name ? profile.name : truncate(pubkey, 16, ' .... ')}
</span>
<span className="font-bold leading-tight">{profile.name ? profile.name : truncate(pubkey, 16, ' .... ')}</span>
<span className="leading-tight text-zinc-500">·</span>
<Moment fromNow unix className="text-zinc-500">
{time}

View File

@ -35,14 +35,14 @@ export default function Page() {
}, []);
const getAccount = useCallback(async () => {
const result = await db.select(`SELECT id FROM accounts ASC LIMIT 1`);
const result = await db.select(`SELECT * FROM accounts ASC LIMIT 1`);
return result;
}, []);
const getFollows = useCallback(async (account) => {
const arr = [];
const result: any = await db.select(`SELECT pubkey FROM follows WHERE account = "${account.pubkey}"`);
const result: any = await db.select(`SELECT pubkey FROM follows WHERE account = "${account.id}"`);
result.forEach((item: { pubkey: string }) => {
arr.push(item.pubkey);
@ -59,7 +59,6 @@ export default function Page() {
requestNotification().then(() => {
getAccount()
.then((res: any) => {
console.log(res);
if (res.length === 0) {
setTimeout(() => {
setLoading(false);

View File

@ -43,12 +43,8 @@ export default function Page() {
const [privKey] = useState(() => generatePrivateKey());
const [name] = useState(() => uniqueNamesGenerator(config).toString());
const [avatar] = useState(
() => defaultAvatars[Math.floor(Math.random() * defaultAvatars.length)]
);
const [banner] = useState(
() => defaultBanners[Math.floor(Math.random() * defaultBanners.length)]
);
const [avatar] = useState(() => defaultAvatars[Math.floor(Math.random() * defaultAvatars.length)]);
const [banner] = useState(() => defaultBanners[Math.floor(Math.random() * defaultBanners.length)]);
const pubKey = getPublicKey(privKey);
const npub = nip19.npubEncode(pubKey);
@ -81,9 +77,7 @@ export default function Page() {
// save account to database
const db = await Database.load('sqlite:lume.db');
await db.execute(
`INSERT INTO accounts (privkey, pubkey, npub, nsec, current, metadata) VALUES ("${privKey}", "${pubKey}", "${npub}", "${nsec}", "1", '${JSON.stringify(
data
)}')`
`INSERT INTO accounts (id, privkey, npub, nsec, metadata) VALUES ("${pubKey}", "${privKey}", "${npub}", "${nsec}", '${JSON.stringify(data)}')`
);
await db.close();
@ -115,14 +109,12 @@ export default function Page() {
<div>{/* spacer */}</div>
<motion.div layoutId="form">
<div className="mb-8 flex flex-col gap-3">
<motion.h1
layoutId="title"
className="bg-gradient-to-br from-zinc-200 to-zinc-400 bg-clip-text text-3xl font-medium text-transparent">
<motion.h1 layoutId="title" className="bg-gradient-to-br from-zinc-200 to-zinc-400 bg-clip-text text-3xl font-medium text-transparent">
Create new key
</motion.h1>
<motion.h2 layoutId="subtitle" className="w-3/4 text-zinc-400">
Lume will generate key with default profile for you, you can edit it later, and please
store your key safely so you can restore your account or use other client
Lume will generate key with default profile for you, you can edit it later, and please store your key safely so you can restore your
account or use other client
</motion.h2>
</div>
<div className="flex flex-col gap-4">
@ -145,9 +137,7 @@ export default function Page() {
value={nsec}
className="relative w-full rounded-lg border border-black/5 px-3.5 py-2 shadow-input shadow-black/5 !outline-none placeholder:text-zinc-400 dark:bg-zinc-800 dark:text-zinc-200 dark:shadow-black/10 dark:placeholder:text-zinc-600"
/>
<button
onClick={() => showNsec()}
className="group absolute right-2 top-1/2 -translate-y-1/2 transform rounded p-1 hover:bg-zinc-700">
<button onClick={() => showNsec()} className="group absolute right-2 top-1/2 -translate-y-1/2 transform rounded p-1 hover:bg-zinc-700">
{type === 'password' ? (
<EyeClosedIcon className="h-5 w-5 text-zinc-500 group-hover:text-zinc-200" />
) : (
@ -157,19 +147,12 @@ export default function Page() {
</div>
</div>
<div className="flex flex-col gap-1">
<label className="text-sm font-semibold text-zinc-400">
Default Profile (you can change it later)
</label>
<label className="text-sm font-semibold text-zinc-400">Default Profile (you can change it later)</label>
<div className="relative max-w-sm shrink-0 before:pointer-events-none before:absolute before:-inset-1 before:rounded-[11px] before:border before:border-blue-500 before:opacity-0 before:ring-2 before:ring-blue-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-blue-500/100 dark:focus-within:after:shadow-blue-500/20">
<div className="relative max-w-sm rounded-lg border border-black/5 px-3.5 py-4 shadow-input shadow-black/5 !outline-none placeholder:text-zinc-400 dark:bg-zinc-800 dark:text-zinc-200 dark:shadow-black/10 dark:placeholder:text-zinc-600">
<div className="flex space-x-4">
<div className="relative h-10 w-10 rounded-full">
<Image
className="inline-block rounded-full"
src={data.picture}
alt=""
fill={true}
/>
<Image className="inline-block rounded-full" src={data.picture} alt="" fill={true} />
</div>
<div className="flex-1 space-y-4 py-1">
<div className="flex items-center gap-2">
@ -193,18 +176,8 @@ export default function Page() {
<motion.div layoutId="action" className="pb-5">
<div className="flex h-10 items-center">
{loading === true ? (
<svg
className="h-5 w-5 animate-spin text-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24">
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"></circle>
<svg className="h-5 w-5 animate-spin text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
<path
className="opacity-75"
fill="currentColor"
@ -226,13 +199,7 @@ export default function Page() {
}
Page.getLayout = function getLayout(
page:
| string
| number
| boolean
| ReactElement<unknown, string | JSXElementConstructor<unknown>>
| ReactFragment
| ReactPortal
page: string | number | boolean | ReactElement<unknown, string | JSXElementConstructor<unknown>> | ReactFragment | ReactPortal
) {
return (
<BaseLayout>

View File

@ -5,14 +5,7 @@ import OnboardingLayout from '@layouts/onboardingLayout';
import { motion } from 'framer-motion';
import { useRouter } from 'next/router';
import { useNostrEvents } from 'nostr-react';
import {
JSXElementConstructor,
ReactElement,
ReactFragment,
ReactPortal,
useEffect,
useState,
} from 'react';
import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useEffect, useState } from 'react';
import Database from 'tauri-plugin-sql-api';
export default function Page() {
@ -44,9 +37,7 @@ export default function Page() {
const db = await Database.load('sqlite:lume.db');
follows.forEach(async (item) => {
if (item) {
await db.execute(
`INSERT OR IGNORE INTO follows (pubkey, account) VALUES ("${item[1]}", "${pubkey}")`
);
await db.execute(`INSERT OR IGNORE INTO follows (pubkey, account) VALUES ("${item[1]}", "${pubkey}")`);
}
});
};
@ -68,32 +59,19 @@ export default function Page() {
<div>{/* spacer */}</div>
<motion.div layoutId="form">
<div className="mb-8 flex flex-col gap-3">
<motion.h1
layoutId="title"
className="bg-gradient-to-br from-zinc-200 to-zinc-400 bg-clip-text text-3xl font-medium text-transparent">
<motion.h1 layoutId="title" className="bg-gradient-to-br from-zinc-200 to-zinc-400 bg-clip-text text-3xl font-medium text-transparent">
Fetching your follows...
</motion.h1>
<motion.h2 layoutId="subtitle" className="w-3/4 text-zinc-400">
Not only profile, every nostr client can sync your follows list when you move to a new
client, so please keep your key safely (again)
Not only profile, every nostr client can sync your follows list when you move to a new client, so please keep your key safely (again)
</motion.h2>
</div>
</motion.div>
<motion.div layoutId="action" className="pb-5">
<div className="flex h-10 items-center">
{loading === true ? (
<svg
className="h-5 w-5 animate-spin text-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24">
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"></circle>
<svg className="h-5 w-5 animate-spin text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
<path
className="opacity-75"
fill="currentColor"
@ -109,13 +87,7 @@ export default function Page() {
}
Page.getLayout = function getLayout(
page:
| string
| number
| boolean
| ReactElement<unknown, string | JSXElementConstructor<unknown>>
| ReactFragment
| ReactPortal
page: string | number | boolean | ReactElement<unknown, string | JSXElementConstructor<unknown>> | ReactFragment | ReactPortal
) {
return (
<BaseLayout>

View File

@ -6,14 +6,7 @@ import { motion } from 'framer-motion';
import { useRouter } from 'next/router';
import { useNostrEvents } from 'nostr-react';
import { getPublicKey, nip19 } from 'nostr-tools';
import {
JSXElementConstructor,
ReactElement,
ReactFragment,
ReactPortal,
useEffect,
useState,
} from 'react';
import { JSXElementConstructor, ReactElement, ReactFragment, ReactPortal, useCallback, useEffect, useState } from 'react';
import Database from 'tauri-plugin-sql-api';
export default function Page() {
@ -43,20 +36,19 @@ export default function Page() {
}
});
const insertDB = useCallback(async () => {
// save account to database
const db = await Database.load('sqlite:lume.db');
const metadata = JSON.stringify(account);
await db.execute(
`INSERT INTO accounts (id, privkey, npub, nsec, metadata) VALUES ("${pubkey}", "${privkey}", "${npub}", "${nsec}", '${metadata}')`
);
await db.close();
}, [account, npub, nsec, privkey, pubkey]);
useEffect(() => {
setLoading(true);
const insertDB = async () => {
// save account to database
const db = await Database.load('sqlite:lume.db');
await db.execute(
`INSERT INTO accounts (privkey, pubkey, npub, nsec, current, metadata) VALUES ("${privkey}", "${pubkey}", "${npub}", "${nsec}", "1", '${JSON.stringify(
account
)}')`
);
await db.close();
};
if (account !== null) {
insertDB()
.then(() => {
@ -70,39 +62,26 @@ export default function Page() {
})
.catch(console.error);
}
}, [account, npub, nsec, privkey, pubkey, router]);
}, [account, insertDB, npub, nsec, privkey, pubkey, router]);
return (
<div className="flex h-full flex-col justify-between px-8">
<div>{/* spacer */}</div>
<motion.div layoutId="form">
<div className="mb-8 flex flex-col gap-3">
<motion.h1
layoutId="title"
className="bg-gradient-to-br from-zinc-200 to-zinc-400 bg-clip-text text-3xl font-medium text-transparent">
<motion.h1 layoutId="title" className="bg-gradient-to-br from-zinc-200 to-zinc-400 bg-clip-text text-3xl font-medium text-transparent">
Fetching your profile...
</motion.h1>
<motion.h2 layoutId="subtitle" className="w-3/4 text-zinc-400">
As long as you have private key, you alway can sync your profile on every nostr client,
so please keep your key safely
As long as you have private key, you alway can sync your profile on every nostr client, so please keep your key safely
</motion.h2>
</div>
</motion.div>
<motion.div layoutId="action" className="pb-5">
<div className="flex h-10 items-center">
{loading === true ? (
<svg
className="h-5 w-5 animate-spin text-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24">
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"></circle>
<svg className="h-5 w-5 animate-spin text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
<path
className="opacity-75"
fill="currentColor"
@ -118,13 +97,7 @@ export default function Page() {
}
Page.getLayout = function getLayout(
page:
| string
| number
| boolean
| ReactElement<unknown, string | JSXElementConstructor<unknown>>
| ReactFragment
| ReactPortal
page: string | number | boolean | ReactElement<unknown, string | JSXElementConstructor<unknown>> | ReactFragment | ReactPortal
) {
return (
<BaseLayout>

View File

@ -33,14 +33,11 @@ export default function Page() {
const insertDB = async () => {
const db = await Database.load('sqlite:lume.db');
await db.execute(
`INSERT INTO follows (pubkey, account) VALUES ("${$currentUser.pubkey}", "${$currentUser.pubkey}")`
);
// self followed
await db.execute(`INSERT INTO follows (pubkey, account) VALUES ("${$currentUser.pubkey}", "${$currentUser.pubkey}")`);
follow.forEach(async (npub) => {
const { data } = nip19.decode(npub);
await db.execute(
`INSERT INTO follows (pubkey, account) VALUES ("${data}", "${$currentUser.pubkey}")`
);
await db.execute(`INSERT INTO follows (pubkey, account) VALUES ("${data}", "${$currentUser.pubkey}")`);
});
};
@ -60,14 +57,11 @@ export default function Page() {
<div>{/* spacer */}</div>
<motion.div layoutId="form" className="flex flex-col">
<div className="mb-8 flex flex-col gap-3">
<motion.h1
layoutId="title"
className="bg-gradient-to-br from-zinc-200 to-zinc-400 bg-clip-text text-3xl font-medium text-transparent">
<motion.h1 layoutId="title" className="bg-gradient-to-br from-zinc-200 to-zinc-400 bg-clip-text text-3xl font-medium text-transparent">
Choose 10 people you want to following
</motion.h1>
<motion.h2 layoutId="subtitle" className="w-3/4 text-zinc-400">
For better experiences, you should follow the people you care about to personalize your
newsfeed, otherwise you will be very bored
For better experiences, you should follow the people you care about to personalize your newsfeed, otherwise you will be very bored
</motion.h2>
</div>
<div className="h-full w-full shrink">
@ -81,27 +75,14 @@ export default function Page() {
follow.includes(item.npub) ? 'bg-zinc-800' : ''
}`}>
<div className="relative h-10 w-10 flex-shrink-0">
<Image
className="rounded-full object-cover"
src={item.avatar}
alt={item.name}
fill={true}
/>
<Image className="rounded-full object-cover" src={item.avatar} alt={item.name} fill={true} />
</div>
<div className="inline-flex flex-1 items-center justify-between">
<div>
<p className="truncate text-sm font-medium text-zinc-200">{item.name}</p>
<p className="text-sm leading-tight text-zinc-500">
{truncate(item.npub, 16, ' .... ')}
</p>
</div>
<div>
{follow.includes(item.npub) ? (
<CheckCircledIcon className="h-4 w-4 text-green-500" />
) : (
<></>
)}
<p className="text-sm leading-tight text-zinc-500">{truncate(item.npub, 16, ' .... ')}</p>
</div>
<div>{follow.includes(item.npub) ? <CheckCircledIcon className="h-4 w-4 text-green-500" /> : <></>}</div>
</div>
</div>
))}
@ -111,18 +92,8 @@ export default function Page() {
<motion.div layoutId="action" className="pb-5">
<div className="flex h-10 items-center">
{loading === true ? (
<svg
className="h-5 w-5 animate-spin text-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24">
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"></circle>
<svg className="h-5 w-5 animate-spin text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
<path
className="opacity-75"
fill="currentColor"
@ -145,13 +116,7 @@ export default function Page() {
}
Page.getLayout = function getLayout(
page:
| string
| number
| boolean
| ReactElement<unknown, string | JSXElementConstructor<unknown>>
| ReactFragment
| ReactPortal
page: string | number | boolean | ReactElement<unknown, string | JSXElementConstructor<unknown>> | ReactFragment | ReactPortal
) {
return (
<BaseLayout>

View File

@ -60,14 +60,12 @@ export default function Page() {
<div>{/* spacer */}</div>
<motion.div layoutId="form">
<div className="mb-8 flex flex-col gap-3">
<motion.h1
layoutId="title"
className="bg-gradient-to-br from-zinc-200 to-zinc-400 bg-clip-text text-3xl font-medium text-transparent">
<motion.h1 layoutId="title" className="bg-gradient-to-br from-zinc-200 to-zinc-400 bg-clip-text text-3xl font-medium text-transparent">
Import your private key
</motion.h1>
<motion.h2 layoutId="subtitle" className="w-3/4 text-zinc-400">
You can import private key format as hex string or nsec. If you have installed Nostr
Connect compality wallet in your mobile, you can connect by scan QR Code below
You can import private key format as hex string or nsec. If you have installed Nostr Connect compality wallet in your mobile, you can
connect by scan QR Code below
</motion.h2>
</div>
<div className="flex flex-col gap-2">
@ -85,18 +83,8 @@ export default function Page() {
<motion.div layoutId="action" className="pb-5">
<div className="flex h-10 items-center">
{isSubmitting ? (
<svg
className="h-5 w-5 animate-spin text-white"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24">
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"></circle>
<svg className="h-5 w-5 animate-spin text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
<path
className="opacity-75"
fill="currentColor"
@ -117,13 +105,7 @@ export default function Page() {
}
Page.getLayout = function getLayout(
page:
| string
| number
| boolean
| ReactElement<unknown, string | JSXElementConstructor<unknown>>
| ReactFragment
| ReactPortal
page: string | number | boolean | ReactElement<unknown, string | JSXElementConstructor<unknown>> | ReactFragment | ReactPortal
) {
return (
<BaseLayout>