fix(layout): fix flickering on home layout
This commit is contained in:
30
src/app.tsx
30
src/app.tsx
@@ -1,4 +1,5 @@
|
||||
import { fetch } from '@tauri-apps/plugin-http';
|
||||
import { nip19 } from 'nostr-tools';
|
||||
import { RouterProvider, createBrowserRouter, defer, redirect } from 'react-router-dom';
|
||||
import { ErrorScreen } from '@app/error';
|
||||
import { useArk } from '@libs/ark';
|
||||
@@ -43,6 +44,21 @@ export default function App() {
|
||||
return { Component: HomeScreen };
|
||||
},
|
||||
},
|
||||
{
|
||||
path: ':address',
|
||||
loader: ({ params }) => {
|
||||
const address = params.address;
|
||||
const decode = nip19.decode(address);
|
||||
if (decode.type === 'npub') return redirect(`/users/${decode.data}`);
|
||||
if (decode.type === 'nprofile')
|
||||
return redirect(`/users/${decode.data.pubkey}`);
|
||||
if (decode.type === 'note') return redirect(`/events/${decode.data}`);
|
||||
if (decode.type === 'nrelay') return redirect(`/relays/${decode.data}`);
|
||||
if (decode.type === 'nevent')
|
||||
return redirect(`/relays/${decode.data.id}`);
|
||||
return null;
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'nwc',
|
||||
async lazy() {
|
||||
@@ -65,20 +81,6 @@ export default function App() {
|
||||
return { Component: RelayScreen };
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'users/:pubkey',
|
||||
async lazy() {
|
||||
const { UserScreen } = await import('@app/users');
|
||||
return { Component: UserScreen };
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'events/:id',
|
||||
async lazy() {
|
||||
const { TextNoteScreen } = await import('@app/notes/text');
|
||||
return { Component: TextNoteScreen };
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'new',
|
||||
element: <ComposerLayout />,
|
||||
|
||||
@@ -93,44 +93,46 @@ export function HomeScreen() {
|
||||
}
|
||||
|
||||
return (
|
||||
<VList
|
||||
ref={ref}
|
||||
className="h-full w-full flex-nowrap overflow-x-auto !overflow-y-hidden scrollbar-none focus:outline-none"
|
||||
initialItemSize={420}
|
||||
tabIndex={0}
|
||||
horizontal
|
||||
onKeyDown={(e) => {
|
||||
if (!ref.current) return;
|
||||
switch (e.code) {
|
||||
case 'ArrowUp':
|
||||
case 'ArrowLeft': {
|
||||
e.preventDefault();
|
||||
const prevIndex = Math.max(selectedIndex - 1, 0);
|
||||
setSelectedIndex(prevIndex);
|
||||
ref.current.scrollToIndex(prevIndex, {
|
||||
align: 'center',
|
||||
smooth: true,
|
||||
});
|
||||
break;
|
||||
<div className="h-full w-full">
|
||||
<VList
|
||||
ref={ref}
|
||||
className="h-full w-full flex-nowrap overflow-x-auto !overflow-y-hidden scrollbar-none focus:outline-none"
|
||||
initialItemSize={420}
|
||||
tabIndex={0}
|
||||
horizontal
|
||||
onKeyDown={(e) => {
|
||||
if (!ref.current) return;
|
||||
switch (e.code) {
|
||||
case 'ArrowUp':
|
||||
case 'ArrowLeft': {
|
||||
e.preventDefault();
|
||||
const prevIndex = Math.max(selectedIndex - 1, 0);
|
||||
setSelectedIndex(prevIndex);
|
||||
ref.current.scrollToIndex(prevIndex, {
|
||||
align: 'center',
|
||||
smooth: true,
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'ArrowDown':
|
||||
case 'ArrowRight': {
|
||||
e.preventDefault();
|
||||
const nextIndex = Math.min(selectedIndex + 1, data.length - 1);
|
||||
setSelectedIndex(nextIndex);
|
||||
ref.current.scrollToIndex(nextIndex, {
|
||||
align: 'center',
|
||||
smooth: true,
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case 'ArrowDown':
|
||||
case 'ArrowRight': {
|
||||
e.preventDefault();
|
||||
const nextIndex = Math.min(selectedIndex + 1, data.length - 1);
|
||||
setSelectedIndex(nextIndex);
|
||||
ref.current.scrollToIndex(nextIndex, {
|
||||
align: 'center',
|
||||
smooth: true,
|
||||
});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}}
|
||||
>
|
||||
{data.map((widget) => renderItem(widget))}
|
||||
<ToggleWidgetList />
|
||||
</VList>
|
||||
}}
|
||||
>
|
||||
{data.map((widget) => renderItem(widget))}
|
||||
<ToggleWidgetList />
|
||||
</VList>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ export class Ark {
|
||||
readonly platform: Platform | null;
|
||||
readonly settings: {
|
||||
autoupdate: boolean;
|
||||
bunker: boolean;
|
||||
outbox: boolean;
|
||||
media: boolean;
|
||||
hashtag: boolean;
|
||||
@@ -53,6 +54,7 @@ export class Ark {
|
||||
this.platform = platform;
|
||||
this.settings = {
|
||||
autoupdate: false,
|
||||
bunker: false,
|
||||
outbox: false,
|
||||
media: true,
|
||||
hashtag: true,
|
||||
@@ -100,7 +102,7 @@ export class Ark {
|
||||
const bunker = new NDK({
|
||||
explicitRelayUrls: ['wss://relay.nsecbunker.com', 'wss://nostr.vulpem.com'],
|
||||
});
|
||||
await bunker.connect();
|
||||
await bunker.connect(3000);
|
||||
|
||||
const remoteSigner = new NDKNip46Signer(bunker, this.account.pubkey, localSigner);
|
||||
await remoteSigner.blockUntilReady();
|
||||
@@ -134,11 +136,14 @@ export class Ark {
|
||||
}
|
||||
|
||||
public async init() {
|
||||
const outboxSetting = await this.getSettingValue('outbox');
|
||||
const bunkerSetting = await this.getSettingValue('nsecbunker');
|
||||
|
||||
const bunker = !!parseInt(bunkerSetting);
|
||||
const enableOutboxModel = !!parseInt(outboxSetting);
|
||||
const settings = await this.getAllSettings();
|
||||
for (const item of settings) {
|
||||
if (item.key === 'nsecbunker') this.settings.bunker = !!parseInt(item.value);
|
||||
if (item.key === 'outbox') this.settings.outbox = !!parseInt(item.value);
|
||||
if (item.key === 'media') this.settings.media = !!parseInt(item.value);
|
||||
if (item.key === 'hashtag') this.settings.hashtag = !!parseInt(item.value);
|
||||
if (item.key === 'autoupdate') this.settings.autoupdate = !!parseInt(item.value);
|
||||
}
|
||||
|
||||
const explicitRelayUrls = normalizeRelayUrlSet([
|
||||
'wss://relay.damus.io',
|
||||
@@ -159,7 +164,7 @@ export class Ark {
|
||||
explicitRelayUrls,
|
||||
outboxRelayUrls,
|
||||
blacklistRelayUrls,
|
||||
enableOutboxModel,
|
||||
enableOutboxModel: this.settings.outbox,
|
||||
autoConnectUserRelays: true,
|
||||
autoFetchUserMutelist: true,
|
||||
// clientName: 'Lume',
|
||||
@@ -167,11 +172,11 @@ export class Ark {
|
||||
});
|
||||
|
||||
// add signer if exist
|
||||
const signer = await this.#initNostrSigner({ nsecbunker: bunker });
|
||||
const signer = await this.#initNostrSigner({ nsecbunker: this.settings.bunker });
|
||||
if (signer) ndk.signer = signer;
|
||||
|
||||
// connect
|
||||
await ndk.connect();
|
||||
await ndk.connect(5000);
|
||||
const fetcher = NostrFetcher.withCustomPool(ndkAdapter(ndk));
|
||||
|
||||
// update account's metadata
|
||||
@@ -356,7 +361,7 @@ export class Ark {
|
||||
const results: { key: string; value: string }[] = await this.#storage.select(
|
||||
'SELECT * FROM settings ORDER BY id DESC;'
|
||||
);
|
||||
if (results.length < 1) return null;
|
||||
if (results.length < 1) return [];
|
||||
return results;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { NDKKind } from '@nostr-dev-kit/ndk';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { ask } from '@tauri-apps/plugin-dialog';
|
||||
import { platform } from '@tauri-apps/plugin-os';
|
||||
import { relaunch } from '@tauri-apps/plugin-process';
|
||||
@@ -9,7 +7,7 @@ import Markdown from 'markdown-to-jsx';
|
||||
import { PropsWithChildren, createContext, useContext, useEffect, useState } from 'react';
|
||||
import { Ark } from '@libs/ark';
|
||||
import { LoaderIcon } from '@shared/icons';
|
||||
import { FETCH_LIMIT, QUOTES } from '@utils/constants';
|
||||
import { QUOTES } from '@utils/constants';
|
||||
|
||||
const ArkContext = createContext<Ark>(undefined);
|
||||
|
||||
@@ -17,8 +15,6 @@ const ArkProvider = ({ children }: PropsWithChildren<object>) => {
|
||||
const [ark, setArk] = useState<Ark>(undefined);
|
||||
const [isNewVersion, setIsNewVersion] = useState(false);
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
async function initArk() {
|
||||
try {
|
||||
const sqlite = await Database.load('sqlite:lume_v2.db');
|
||||
@@ -27,24 +23,7 @@ const ArkProvider = ({ children }: PropsWithChildren<object>) => {
|
||||
const _ark = new Ark({ storage: sqlite, platform: platformName });
|
||||
await _ark.init();
|
||||
|
||||
const settings = await _ark.getAllSettings();
|
||||
let autoUpdater = false;
|
||||
|
||||
if (settings) {
|
||||
settings.forEach((item) => {
|
||||
if (item.key === 'outbox') _ark.settings.outbox = !!parseInt(item.value);
|
||||
|
||||
if (item.key === 'media') _ark.settings.media = !!parseInt(item.value);
|
||||
|
||||
if (item.key === 'hashtag') _ark.settings.hashtag = !!parseInt(item.value);
|
||||
|
||||
if (item.key === 'autoupdate') {
|
||||
if (parseInt(item.value)) autoUpdater = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (autoUpdater) {
|
||||
if (_ark.settings.autoupdate) {
|
||||
// check update
|
||||
const update = await check();
|
||||
// install new version
|
||||
@@ -56,56 +35,6 @@ const ArkProvider = ({ children }: PropsWithChildren<object>) => {
|
||||
}
|
||||
}
|
||||
|
||||
if (_ark.account) {
|
||||
// prefetch newsfeed
|
||||
await queryClient.prefetchInfiniteQuery({
|
||||
queryKey: ['newsfeed'],
|
||||
initialPageParam: 0,
|
||||
queryFn: async ({
|
||||
signal,
|
||||
pageParam,
|
||||
}: {
|
||||
signal: AbortSignal;
|
||||
pageParam: number;
|
||||
}) => {
|
||||
return await ark.getInfiniteEvents({
|
||||
filter: {
|
||||
kinds: [NDKKind.Text, NDKKind.Repost],
|
||||
authors: !ark.account.contacts.length
|
||||
? [ark.account.pubkey]
|
||||
: ark.account.contacts,
|
||||
},
|
||||
limit: FETCH_LIMIT,
|
||||
pageParam,
|
||||
signal,
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// prefetch notification
|
||||
await queryClient.prefetchInfiniteQuery({
|
||||
queryKey: ['notification'],
|
||||
initialPageParam: 0,
|
||||
queryFn: async ({
|
||||
signal,
|
||||
pageParam,
|
||||
}: {
|
||||
signal: AbortSignal;
|
||||
pageParam: number;
|
||||
}) => {
|
||||
return await ark.getInfiniteEvents({
|
||||
filter: {
|
||||
kinds: [NDKKind.Text, NDKKind.Repost, NDKKind.Reaction, NDKKind.Zap],
|
||||
'#p': [ark.account.pubkey],
|
||||
},
|
||||
limit: FETCH_LIMIT,
|
||||
pageParam,
|
||||
signal,
|
||||
});
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
setArk(_ark);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
||||
@@ -4,7 +4,9 @@ import { Navigation } from '@shared/navigation';
|
||||
export function HomeLayout() {
|
||||
return (
|
||||
<div className="flex h-full w-full">
|
||||
<Navigation />
|
||||
<div className="w-[68px] shrink-0">
|
||||
<Navigation />
|
||||
</div>
|
||||
<div className="min-h-0 flex-1 rounded-tl-lg bg-white shadow-[rgba(50,_50,_105,_0.15)_0px_2px_5px_0px,_rgba(0,_0,_0,_0.05)_0px_1px_1px_0px] dark:bg-black dark:shadow-[inset_0_0_0.5px_1px_hsla(0,0%,100%,0.075),0_0_0_1px_hsla(0,0%,0%,0.05),0_0.3px_0.4px_hsla(0,0%,0%,0.02),0_0.9px_1.5px_hsla(0,0%,0%,0.045),0_3.5px_6px_hsla(0,0%,0%,0.09)]">
|
||||
<Outlet />
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user