mirror of
https://github.com/luminous-devs/lume.git
synced 2024-09-19 11:43:30 +00:00
add network to account
This commit is contained in:
parent
4c7826bbb3
commit
373a0f0608
@ -0,0 +1,2 @@
|
||||
-- Add migration script here
|
||||
ALTER TABLE accounts ADD network JSON;
|
@ -89,6 +89,12 @@ fn main() {
|
||||
sql: include_str!("../migrations/20230725010250_update_default_relays.sql"),
|
||||
kind: MigrationKind::Up,
|
||||
},
|
||||
Migration {
|
||||
version: 20230804083544,
|
||||
description: "add network to accounts",
|
||||
sql: include_str!("../migrations/20230804083544_add_network_to_account.sql"),
|
||||
kind: MigrationKind::Up,
|
||||
},
|
||||
],
|
||||
)
|
||||
.build(),
|
||||
|
@ -18,7 +18,7 @@ import { WelcomeScreen } from '@app/auth/welcome';
|
||||
import { ChannelScreen } from '@app/channel';
|
||||
import { ChatScreen } from '@app/chats';
|
||||
import { ErrorScreen } from '@app/error';
|
||||
import { NoteScreen } from '@app/note';
|
||||
import { EventScreen } from '@app/events';
|
||||
import { Root } from '@app/root';
|
||||
import { AccountSettingsScreen } from '@app/settings/account';
|
||||
import { GeneralSettingsScreen } from '@app/settings/general';
|
||||
@ -85,7 +85,7 @@ const router = createBrowserRouter([
|
||||
children: [
|
||||
{ path: 'space', element: <SpaceScreen /> },
|
||||
{ path: 'trending', element: <TrendingScreen /> },
|
||||
{ path: 'note/:id', element: <NoteScreen /> },
|
||||
{ path: 'events/:id', element: <EventScreen /> },
|
||||
{ path: 'users/:pubkey', element: <UserScreen /> },
|
||||
{ path: 'chats/:pubkey', element: <ChatScreen /> },
|
||||
{ path: 'channel/:id', element: <ChannelScreen /> },
|
||||
|
51
src/app/events/index.tsx
Normal file
51
src/app/events/index.tsx
Normal file
@ -0,0 +1,51 @@
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import {
|
||||
NoteActions,
|
||||
NoteContent,
|
||||
NoteReplyForm,
|
||||
NoteStats,
|
||||
ThreadUser,
|
||||
} from '@shared/notes';
|
||||
import { RepliesList } from '@shared/notes/replies/list';
|
||||
import { NoteSkeleton } from '@shared/notes/skeleton';
|
||||
|
||||
import { useAccount } from '@utils/hooks/useAccount';
|
||||
import { useEvent } from '@utils/hooks/useEvent';
|
||||
|
||||
export function EventScreen() {
|
||||
const { id } = useParams();
|
||||
const { account } = useAccount();
|
||||
const { status, data } = useEvent(id);
|
||||
|
||||
return (
|
||||
<div className="mx-auto w-[600px]">
|
||||
<div className="scrollbar-hide flex h-full w-full flex-col gap-1.5 overflow-y-auto pt-11">
|
||||
{status === 'loading' ? (
|
||||
<div className="px-3 py-1.5">
|
||||
<div className="rounded-xl bg-white/10 px-3 py-3">
|
||||
<NoteSkeleton />
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="h-min w-full px-3 pt-1.5">
|
||||
<div className="rounded-xl bg-white/10 px-3 pt-3">
|
||||
<ThreadUser pubkey={data.pubkey} time={data.created_at} />
|
||||
<div className="mt-2">
|
||||
<NoteContent content={data.content} />
|
||||
</div>
|
||||
<div>
|
||||
<NoteActions id={data.id} pubkey={data.pubkey} noOpenThread={true} />
|
||||
<NoteStats id={data.id} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="px-3">
|
||||
<NoteReplyForm id={id} pubkey={account.pubkey} />
|
||||
<RepliesList id={id} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
import { useParams } from 'react-router-dom';
|
||||
|
||||
import { useLiveThread } from '@app/space/hooks/useLiveThread';
|
||||
|
||||
import { NoteMetadata } from '@shared/notes/metadata';
|
||||
import { NoteReplyForm } from '@shared/notes/replies/form';
|
||||
import { RepliesList } from '@shared/notes/replies/list';
|
||||
import { NoteSkeleton } from '@shared/notes/skeleton';
|
||||
import { User } from '@shared/user';
|
||||
|
||||
import { useAccount } from '@utils/hooks/useAccount';
|
||||
import { useEvent } from '@utils/hooks/useEvent';
|
||||
|
||||
export function NoteScreen() {
|
||||
const { id } = useParams();
|
||||
const { account } = useAccount();
|
||||
const { status, data } = useEvent(id);
|
||||
|
||||
useLiveThread(id);
|
||||
|
||||
return (
|
||||
<div className="mx-auto w-[600px]">
|
||||
<div className="scrollbar-hide flex h-full w-full flex-col gap-1.5 overflow-y-auto pb-20 pt-16">
|
||||
{status === 'loading' ? (
|
||||
<div className="px-3 py-1.5">
|
||||
<div className="shadow-input rounded-md bg-white/10 px-3 py-3">
|
||||
<NoteSkeleton />
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<div className="h-min w-full px-3 py-1.5">
|
||||
<div className="rounded-md bg-zinc-900 px-5 pt-5">
|
||||
<User pubkey={data.pubkey} time={data.created_at} />
|
||||
<div className="mt-3">
|
||||
<NoteMetadata id={data.event_id || id} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-3 rounded-md bg-zinc-900">
|
||||
{account && <NoteReplyForm rootID={id} userPubkey={account.pubkey} />}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="px-3">
|
||||
<RepliesList id={id} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -27,27 +27,39 @@ export function Root() {
|
||||
const { ndk, relayUrls, fetcher } = useNDK();
|
||||
const { status, account } = useAccount();
|
||||
|
||||
async function getFollows() {
|
||||
const authors: string[] = [];
|
||||
async function fetchNetwork() {
|
||||
const network = new Set<string>();
|
||||
|
||||
// fetch user's follows
|
||||
const user = ndk.getUser({ hexpubkey: account.pubkey });
|
||||
const follows = await user.follows();
|
||||
|
||||
follows.forEach((follow: NDKUser) => {
|
||||
authors.push(nip19.decode(follow.npub).data as string);
|
||||
network.add(nip19.decode(follow.npub).data as string);
|
||||
});
|
||||
|
||||
// update follows in db
|
||||
await updateAccount('follows', authors, account.pubkey);
|
||||
// update user's follows in db
|
||||
await updateAccount('follows', [...network]);
|
||||
|
||||
return authors;
|
||||
// fetch network
|
||||
for (const item of network) {
|
||||
const user = ndk.getUser({ hexpubkey: item });
|
||||
const follows = await user.follows();
|
||||
follows.forEach((follow: NDKUser) => {
|
||||
network.add(nip19.decode(follow.npub).data as string);
|
||||
});
|
||||
}
|
||||
|
||||
// update user's network in db
|
||||
await updateAccount('network', [...network]);
|
||||
|
||||
return [...network];
|
||||
}
|
||||
|
||||
async function fetchNotes() {
|
||||
try {
|
||||
const follows = await getFollows();
|
||||
const network = await fetchNetwork();
|
||||
|
||||
if (follows.length > 0) {
|
||||
if (network.length > 0) {
|
||||
let since: number;
|
||||
if (totalNotes === 0 || lastLogin === 0) {
|
||||
since = nHoursAgo(48);
|
||||
@ -57,7 +69,7 @@ export function Root() {
|
||||
|
||||
const events = fetcher.allEventsIterator(
|
||||
relayUrls,
|
||||
{ kinds: [1], authors: follows },
|
||||
{ kinds: [1], authors: network },
|
||||
{ since: since },
|
||||
{ skipVerification: true }
|
||||
);
|
||||
|
@ -16,7 +16,7 @@ import { LumeEvent } from '@utils/types';
|
||||
|
||||
const ITEM_PER_PAGE = 10;
|
||||
|
||||
export function FollowingBlock() {
|
||||
export function NetworkBlock() {
|
||||
// subscribe for live update
|
||||
useNewsfeed();
|
||||
|
||||
@ -130,7 +130,7 @@ export function FollowingBlock() {
|
||||
ref={parentRef}
|
||||
className="scrollbar-hide relative h-full w-[400px] shrink-0 overflow-y-auto bg-white/10 pb-20"
|
||||
>
|
||||
<TitleBar title="Your Circle" />
|
||||
<TitleBar title="Network" />
|
||||
<div className="h-full">
|
||||
{status === 'loading' ? (
|
||||
<div className="px-3 py-1.5">
|
@ -2,9 +2,9 @@ import { useQuery } from '@tanstack/react-query';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { FeedBlock } from '@app/space/components/blocks/feed';
|
||||
import { FollowingBlock } from '@app/space/components/blocks/following';
|
||||
import { HashtagBlock } from '@app/space/components/blocks/hashtag';
|
||||
import { ImageBlock } from '@app/space/components/blocks/image';
|
||||
import { NetworkBlock } from '@app/space/components/blocks/network';
|
||||
import { ThreadBlock } from '@app/space/components/blocks/thread';
|
||||
import { UserBlock } from '@app/space/components/blocks/user';
|
||||
import { FeedModal } from '@app/space/components/modals/feed';
|
||||
@ -53,7 +53,7 @@ export function SpaceScreen() {
|
||||
|
||||
return (
|
||||
<div className="scrollbar-hide flex h-full w-full flex-nowrap divide-x divide-white/5 overflow-x-auto overflow-y-hidden">
|
||||
<FollowingBlock />
|
||||
<NetworkBlock />
|
||||
{status === 'loading' ? (
|
||||
<div className="flex w-[350px] shrink-0 flex-col">
|
||||
<div className="flex w-full flex-1 items-center justify-center p-3">
|
||||
|
@ -14,8 +14,6 @@ export default class TauriAdapter implements NDKCacheAdapter {
|
||||
public async query(subscription: NDKSubscription): Promise<void> {
|
||||
const { filter } = subscription;
|
||||
|
||||
// if this filter uses both authors and kinds, then we need to query for each combination of author and kind
|
||||
// and then combine the results
|
||||
if (filter.authors && filter.kinds) {
|
||||
const promises = [];
|
||||
|
||||
|
@ -63,15 +63,12 @@ export async function createAccount(
|
||||
}
|
||||
|
||||
// update account
|
||||
export async function updateAccount(
|
||||
column: string,
|
||||
value: string | string[],
|
||||
pubkey: string
|
||||
) {
|
||||
export async function updateAccount(column: string, value: string | string[]) {
|
||||
const db = await connect();
|
||||
return await db.execute(`UPDATE accounts SET ${column} = ? WHERE pubkey = ?;`, [
|
||||
const account = await getActiveAccount();
|
||||
return await db.execute(`UPDATE accounts SET ${column} = ? WHERE id = ?;`, [
|
||||
value,
|
||||
pubkey,
|
||||
account.id,
|
||||
]);
|
||||
}
|
||||
|
||||
|
@ -18,14 +18,10 @@ export function ComposerModal() {
|
||||
const { account } = useAccount();
|
||||
const [toggle, open] = useComposer((state) => [state.toggleModal, state.open]);
|
||||
|
||||
const closeModal = () => {
|
||||
toggle(false);
|
||||
};
|
||||
|
||||
useHotkeys(COMPOSE_SHORTCUT, () => toggle(true));
|
||||
|
||||
return (
|
||||
<Dialog.Root open={open}>
|
||||
<Dialog.Root open={open} onOpenChange={toggle}>
|
||||
<Dialog.Trigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
@ -51,7 +47,7 @@ export function ComposerModal() {
|
||||
</div>
|
||||
</div>
|
||||
<Dialog.Close
|
||||
onClick={() => closeModal()}
|
||||
onClick={() => toggle(false)}
|
||||
className="inline-flex h-8 w-8 items-center justify-center rounded-md hover:bg-zinc-800"
|
||||
>
|
||||
<CancelIcon className="h-5 w-5 text-white/50" />
|
||||
|
@ -8,14 +8,15 @@ import { Link } from 'react-router-dom';
|
||||
import { HorizontalDotsIcon } from '@shared/icons';
|
||||
|
||||
export function MoreActions({ id, pubkey }: { id: string; pubkey: string }) {
|
||||
const nevent = nip19.neventEncode(id as unknown as EventPointer);
|
||||
|
||||
const copyID = async () => {
|
||||
await writeText(nevent);
|
||||
await writeText(nip19.neventEncode({ id: id, author: pubkey } as EventPointer));
|
||||
};
|
||||
|
||||
const copyLink = async () => {
|
||||
await writeText('https://nostr.com/' + nevent);
|
||||
await writeText(
|
||||
'https://nostr.com/' +
|
||||
nip19.neventEncode({ id: id, author: pubkey } as EventPointer)
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -41,12 +42,12 @@ export function MoreActions({ id, pubkey }: { id: string; pubkey: string }) {
|
||||
<Popover.Portal>
|
||||
<Popover.Content className="w-[200px] overflow-hidden rounded-md bg-white/10 backdrop-blur-xl focus:outline-none">
|
||||
<div className="flex flex-col p-2">
|
||||
<button
|
||||
type="button"
|
||||
<Link
|
||||
to={`/app/events/${id}`}
|
||||
className="inline-flex h-10 items-center rounded-md px-2 text-sm font-medium text-white hover:bg-white/10"
|
||||
>
|
||||
Open as new screen
|
||||
</button>
|
||||
</Link>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => copyLink()}
|
||||
@ -62,7 +63,6 @@ export function MoreActions({ id, pubkey }: { id: string; pubkey: string }) {
|
||||
Copy ID
|
||||
</button>
|
||||
<Link
|
||||
type="button"
|
||||
to={`/app/users/${pubkey}`}
|
||||
className="inline-flex h-10 items-center rounded-md px-2 text-sm font-medium text-white hover:bg-white/10"
|
||||
>
|
||||
|
3
src/utils/types.d.ts
vendored
3
src/utils/types.d.ts
vendored
@ -20,9 +20,10 @@ export interface Account extends NDKUserProfile {
|
||||
id: number;
|
||||
npub: string;
|
||||
pubkey: string;
|
||||
privkey: string;
|
||||
follows: string[] | string;
|
||||
network: string[] | string;
|
||||
is_active: number;
|
||||
privkey?: string; // deprecated
|
||||
}
|
||||
|
||||
export interface Profile extends NDKUserProfile {
|
||||
|
Loading…
Reference in New Issue
Block a user