mirror of
https://github.com/luminous-devs/lume.git
synced 2024-10-01 09:21:07 +00:00
fix(layout): fix flickering on home layout
This commit is contained in:
parent
2fcc4dead1
commit
591373fd52
@ -83,8 +83,7 @@
|
|||||||
"sonner": "^1.2.4",
|
"sonner": "^1.2.4",
|
||||||
"tippy.js": "^6.3.7",
|
"tippy.js": "^6.3.7",
|
||||||
"tiptap-markdown": "^0.8.8",
|
"tiptap-markdown": "^0.8.8",
|
||||||
"virtua": "^0.17.5",
|
"virtua": "^0.17.5"
|
||||||
"zustand": "^4.4.7"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/forms": "^0.5.7",
|
"@tailwindcss/forms": "^0.5.7",
|
||||||
|
@ -203,9 +203,6 @@ dependencies:
|
|||||||
virtua:
|
virtua:
|
||||||
specifier: ^0.17.5
|
specifier: ^0.17.5
|
||||||
version: 0.17.5(react-dom@18.2.0)(react@18.2.0)
|
version: 0.17.5(react-dom@18.2.0)(react@18.2.0)
|
||||||
zustand:
|
|
||||||
specifier: ^4.4.7
|
|
||||||
version: 4.4.7(@types/react@18.2.43)(react@18.2.0)
|
|
||||||
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@tailwindcss/forms':
|
'@tailwindcss/forms':
|
||||||
@ -5967,14 +5964,6 @@ packages:
|
|||||||
tslib: 2.6.2
|
tslib: 2.6.2
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/use-sync-external-store@1.2.0(react@18.2.0):
|
|
||||||
resolution: {integrity: sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==}
|
|
||||||
peerDependencies:
|
|
||||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
|
||||||
dependencies:
|
|
||||||
react: 18.2.0
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/utf-8-validate@5.0.10:
|
/utf-8-validate@5.0.10:
|
||||||
resolution: {integrity: sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==}
|
resolution: {integrity: sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==}
|
||||||
engines: {node: '>=6.14.2'}
|
engines: {node: '>=6.14.2'}
|
||||||
@ -6193,23 +6182,3 @@ packages:
|
|||||||
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/zustand@4.4.7(@types/react@18.2.43)(react@18.2.0):
|
|
||||||
resolution: {integrity: sha512-QFJWJMdlETcI69paJwhSMJz7PPWjVP8Sjhclxmxmxv/RYI7ZOvR5BHX+ktH0we9gTWQMxcne8q1OY8xxz604gw==}
|
|
||||||
engines: {node: '>=12.7.0'}
|
|
||||||
peerDependencies:
|
|
||||||
'@types/react': '>=16.8'
|
|
||||||
immer: '>=9.0'
|
|
||||||
react: '>=16.8'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
'@types/react':
|
|
||||||
optional: true
|
|
||||||
immer:
|
|
||||||
optional: true
|
|
||||||
react:
|
|
||||||
optional: true
|
|
||||||
dependencies:
|
|
||||||
'@types/react': 18.2.43
|
|
||||||
react: 18.2.0
|
|
||||||
use-sync-external-store: 1.2.0(react@18.2.0)
|
|
||||||
dev: false
|
|
||||||
|
30
src/app.tsx
30
src/app.tsx
@ -1,4 +1,5 @@
|
|||||||
import { fetch } from '@tauri-apps/plugin-http';
|
import { fetch } from '@tauri-apps/plugin-http';
|
||||||
|
import { nip19 } from 'nostr-tools';
|
||||||
import { RouterProvider, createBrowserRouter, defer, redirect } from 'react-router-dom';
|
import { RouterProvider, createBrowserRouter, defer, redirect } from 'react-router-dom';
|
||||||
import { ErrorScreen } from '@app/error';
|
import { ErrorScreen } from '@app/error';
|
||||||
import { useArk } from '@libs/ark';
|
import { useArk } from '@libs/ark';
|
||||||
@ -43,6 +44,21 @@ export default function App() {
|
|||||||
return { Component: HomeScreen };
|
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',
|
path: 'nwc',
|
||||||
async lazy() {
|
async lazy() {
|
||||||
@ -65,20 +81,6 @@ export default function App() {
|
|||||||
return { Component: RelayScreen };
|
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',
|
path: 'new',
|
||||||
element: <ComposerLayout />,
|
element: <ComposerLayout />,
|
||||||
|
@ -93,44 +93,46 @@ export function HomeScreen() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VList
|
<div className="h-full w-full">
|
||||||
ref={ref}
|
<VList
|
||||||
className="h-full w-full flex-nowrap overflow-x-auto !overflow-y-hidden scrollbar-none focus:outline-none"
|
ref={ref}
|
||||||
initialItemSize={420}
|
className="h-full w-full flex-nowrap overflow-x-auto !overflow-y-hidden scrollbar-none focus:outline-none"
|
||||||
tabIndex={0}
|
initialItemSize={420}
|
||||||
horizontal
|
tabIndex={0}
|
||||||
onKeyDown={(e) => {
|
horizontal
|
||||||
if (!ref.current) return;
|
onKeyDown={(e) => {
|
||||||
switch (e.code) {
|
if (!ref.current) return;
|
||||||
case 'ArrowUp':
|
switch (e.code) {
|
||||||
case 'ArrowLeft': {
|
case 'ArrowUp':
|
||||||
e.preventDefault();
|
case 'ArrowLeft': {
|
||||||
const prevIndex = Math.max(selectedIndex - 1, 0);
|
e.preventDefault();
|
||||||
setSelectedIndex(prevIndex);
|
const prevIndex = Math.max(selectedIndex - 1, 0);
|
||||||
ref.current.scrollToIndex(prevIndex, {
|
setSelectedIndex(prevIndex);
|
||||||
align: 'center',
|
ref.current.scrollToIndex(prevIndex, {
|
||||||
smooth: true,
|
align: 'center',
|
||||||
});
|
smooth: true,
|
||||||
break;
|
});
|
||||||
|
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();
|
{data.map((widget) => renderItem(widget))}
|
||||||
const nextIndex = Math.min(selectedIndex + 1, data.length - 1);
|
<ToggleWidgetList />
|
||||||
setSelectedIndex(nextIndex);
|
</VList>
|
||||||
ref.current.scrollToIndex(nextIndex, {
|
</div>
|
||||||
align: 'center',
|
|
||||||
smooth: true,
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{data.map((widget) => renderItem(widget))}
|
|
||||||
<ToggleWidgetList />
|
|
||||||
</VList>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ export class Ark {
|
|||||||
readonly platform: Platform | null;
|
readonly platform: Platform | null;
|
||||||
readonly settings: {
|
readonly settings: {
|
||||||
autoupdate: boolean;
|
autoupdate: boolean;
|
||||||
|
bunker: boolean;
|
||||||
outbox: boolean;
|
outbox: boolean;
|
||||||
media: boolean;
|
media: boolean;
|
||||||
hashtag: boolean;
|
hashtag: boolean;
|
||||||
@ -53,6 +54,7 @@ export class Ark {
|
|||||||
this.platform = platform;
|
this.platform = platform;
|
||||||
this.settings = {
|
this.settings = {
|
||||||
autoupdate: false,
|
autoupdate: false,
|
||||||
|
bunker: false,
|
||||||
outbox: false,
|
outbox: false,
|
||||||
media: true,
|
media: true,
|
||||||
hashtag: true,
|
hashtag: true,
|
||||||
@ -100,7 +102,7 @@ export class Ark {
|
|||||||
const bunker = new NDK({
|
const bunker = new NDK({
|
||||||
explicitRelayUrls: ['wss://relay.nsecbunker.com', 'wss://nostr.vulpem.com'],
|
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);
|
const remoteSigner = new NDKNip46Signer(bunker, this.account.pubkey, localSigner);
|
||||||
await remoteSigner.blockUntilReady();
|
await remoteSigner.blockUntilReady();
|
||||||
@ -134,11 +136,14 @@ export class Ark {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async init() {
|
public async init() {
|
||||||
const outboxSetting = await this.getSettingValue('outbox');
|
const settings = await this.getAllSettings();
|
||||||
const bunkerSetting = await this.getSettingValue('nsecbunker');
|
for (const item of settings) {
|
||||||
|
if (item.key === 'nsecbunker') this.settings.bunker = !!parseInt(item.value);
|
||||||
const bunker = !!parseInt(bunkerSetting);
|
if (item.key === 'outbox') this.settings.outbox = !!parseInt(item.value);
|
||||||
const enableOutboxModel = !!parseInt(outboxSetting);
|
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([
|
const explicitRelayUrls = normalizeRelayUrlSet([
|
||||||
'wss://relay.damus.io',
|
'wss://relay.damus.io',
|
||||||
@ -159,7 +164,7 @@ export class Ark {
|
|||||||
explicitRelayUrls,
|
explicitRelayUrls,
|
||||||
outboxRelayUrls,
|
outboxRelayUrls,
|
||||||
blacklistRelayUrls,
|
blacklistRelayUrls,
|
||||||
enableOutboxModel,
|
enableOutboxModel: this.settings.outbox,
|
||||||
autoConnectUserRelays: true,
|
autoConnectUserRelays: true,
|
||||||
autoFetchUserMutelist: true,
|
autoFetchUserMutelist: true,
|
||||||
// clientName: 'Lume',
|
// clientName: 'Lume',
|
||||||
@ -167,11 +172,11 @@ export class Ark {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// add signer if exist
|
// 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;
|
if (signer) ndk.signer = signer;
|
||||||
|
|
||||||
// connect
|
// connect
|
||||||
await ndk.connect();
|
await ndk.connect(5000);
|
||||||
const fetcher = NostrFetcher.withCustomPool(ndkAdapter(ndk));
|
const fetcher = NostrFetcher.withCustomPool(ndkAdapter(ndk));
|
||||||
|
|
||||||
// update account's metadata
|
// update account's metadata
|
||||||
@ -356,7 +361,7 @@ export class Ark {
|
|||||||
const results: { key: string; value: string }[] = await this.#storage.select(
|
const results: { key: string; value: string }[] = await this.#storage.select(
|
||||||
'SELECT * FROM settings ORDER BY id DESC;'
|
'SELECT * FROM settings ORDER BY id DESC;'
|
||||||
);
|
);
|
||||||
if (results.length < 1) return null;
|
if (results.length < 1) return [];
|
||||||
return results;
|
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 { ask } from '@tauri-apps/plugin-dialog';
|
||||||
import { platform } from '@tauri-apps/plugin-os';
|
import { platform } from '@tauri-apps/plugin-os';
|
||||||
import { relaunch } from '@tauri-apps/plugin-process';
|
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 { PropsWithChildren, createContext, useContext, useEffect, useState } from 'react';
|
||||||
import { Ark } from '@libs/ark';
|
import { Ark } from '@libs/ark';
|
||||||
import { LoaderIcon } from '@shared/icons';
|
import { LoaderIcon } from '@shared/icons';
|
||||||
import { FETCH_LIMIT, QUOTES } from '@utils/constants';
|
import { QUOTES } from '@utils/constants';
|
||||||
|
|
||||||
const ArkContext = createContext<Ark>(undefined);
|
const ArkContext = createContext<Ark>(undefined);
|
||||||
|
|
||||||
@ -17,8 +15,6 @@ const ArkProvider = ({ children }: PropsWithChildren<object>) => {
|
|||||||
const [ark, setArk] = useState<Ark>(undefined);
|
const [ark, setArk] = useState<Ark>(undefined);
|
||||||
const [isNewVersion, setIsNewVersion] = useState(false);
|
const [isNewVersion, setIsNewVersion] = useState(false);
|
||||||
|
|
||||||
const queryClient = useQueryClient();
|
|
||||||
|
|
||||||
async function initArk() {
|
async function initArk() {
|
||||||
try {
|
try {
|
||||||
const sqlite = await Database.load('sqlite:lume_v2.db');
|
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 });
|
const _ark = new Ark({ storage: sqlite, platform: platformName });
|
||||||
await _ark.init();
|
await _ark.init();
|
||||||
|
|
||||||
const settings = await _ark.getAllSettings();
|
if (_ark.settings.autoupdate) {
|
||||||
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) {
|
|
||||||
// check update
|
// check update
|
||||||
const update = await check();
|
const update = await check();
|
||||||
// install new version
|
// 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);
|
setArk(_ark);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
|
@ -4,7 +4,9 @@ import { Navigation } from '@shared/navigation';
|
|||||||
export function HomeLayout() {
|
export function HomeLayout() {
|
||||||
return (
|
return (
|
||||||
<div className="flex h-full w-full">
|
<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)]">
|
<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 />
|
<Outlet />
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user