feat: improve column carousel
This commit is contained in:
@@ -48,18 +48,17 @@ pub fn create_column(column: Column, app_handle: tauri::AppHandle) -> Result<Str
|
|||||||
.incognito(true)
|
.incognito(true)
|
||||||
.transparent(true);
|
.transparent(true);
|
||||||
|
|
||||||
if let Ok(webview) = main_window.add_child(
|
match main_window.add_child(
|
||||||
builder,
|
builder,
|
||||||
LogicalPosition::new(column.x, column.y),
|
LogicalPosition::new(column.x, column.y),
|
||||||
LogicalSize::new(column.width, column.height),
|
LogicalSize::new(column.width, column.height),
|
||||||
) {
|
) {
|
||||||
Ok(webview.label().into())
|
Ok(webview) => Ok(webview.label().into()),
|
||||||
} else {
|
Err(e) => Err(e.to_string()),
|
||||||
Err("Create webview failed".into())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => Err("Main window not found".into()),
|
None => Err("Window not found".into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,35 +67,33 @@ pub fn create_column(column: Column, app_handle: tauri::AppHandle) -> Result<Str
|
|||||||
pub fn close_column(label: String, app_handle: tauri::AppHandle) -> Result<bool, String> {
|
pub fn close_column(label: String, app_handle: tauri::AppHandle) -> Result<bool, String> {
|
||||||
match app_handle.get_webview(&label) {
|
match app_handle.get_webview(&label) {
|
||||||
Some(webview) => Ok(webview.close().is_ok()),
|
Some(webview) => Ok(webview.close().is_ok()),
|
||||||
None => Err("Not found.".into()),
|
None => Err("Cannot close, column not found.".into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command(async)]
|
#[tauri::command(async)]
|
||||||
#[specta::specta]
|
#[specta::specta]
|
||||||
pub fn reposition_column(
|
pub fn update_column(
|
||||||
label: String,
|
|
||||||
x: f32,
|
|
||||||
y: f32,
|
|
||||||
app_handle: tauri::AppHandle,
|
|
||||||
) -> Result<bool, String> {
|
|
||||||
match app_handle.get_webview(&label) {
|
|
||||||
Some(webview) => Ok(webview.set_position(LogicalPosition::new(x, y)).is_ok()),
|
|
||||||
None => Err("Not found".into()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tauri::command(async)]
|
|
||||||
#[specta::specta]
|
|
||||||
pub fn resize_column(
|
|
||||||
label: String,
|
label: String,
|
||||||
width: f32,
|
width: f32,
|
||||||
height: f32,
|
height: f32,
|
||||||
|
x: f32,
|
||||||
|
y: f32,
|
||||||
app_handle: tauri::AppHandle,
|
app_handle: tauri::AppHandle,
|
||||||
) -> Result<bool, String> {
|
) -> Result<(), String> {
|
||||||
match app_handle.get_webview(&label) {
|
match app_handle.get_webview(&label) {
|
||||||
Some(webview) => Ok(webview.set_size(LogicalSize::new(width, height)).is_ok()),
|
Some(webview) => {
|
||||||
None => Err("Not found".into()),
|
if let Err(e) = webview.set_size(LogicalSize::new(width, height)) {
|
||||||
|
return Err(e.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Err(e) = webview.set_position(LogicalPosition::new(x, y)) {
|
||||||
|
return Err(e.to_string());
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
None => Err("Cannot update, column not found.".into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,7 +102,7 @@ pub fn resize_column(
|
|||||||
pub fn reload_column(label: String, app_handle: tauri::AppHandle) -> Result<bool, String> {
|
pub fn reload_column(label: String, app_handle: tauri::AppHandle) -> Result<bool, String> {
|
||||||
match app_handle.get_webview(&label) {
|
match app_handle.get_webview(&label) {
|
||||||
Some(webview) => Ok(webview.eval("window.location.reload()").is_ok()),
|
Some(webview) => Ok(webview.eval("window.location.reload()").is_ok()),
|
||||||
None => Err("Not found".into()),
|
None => Err("Cannot reload, column not found.".into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -151,10 +151,9 @@ fn main() {
|
|||||||
event_to_bech32,
|
event_to_bech32,
|
||||||
user_to_bech32,
|
user_to_bech32,
|
||||||
create_column,
|
create_column,
|
||||||
close_column,
|
update_column,
|
||||||
reposition_column,
|
|
||||||
resize_column,
|
|
||||||
reload_column,
|
reload_column,
|
||||||
|
close_column,
|
||||||
open_window,
|
open_window,
|
||||||
reopen_lume,
|
reopen_lume,
|
||||||
quit
|
quit
|
||||||
|
|||||||
@@ -454,25 +454,9 @@ async createColumn(column: Column) : Promise<Result<string, string>> {
|
|||||||
else return { status: "error", error: e as any };
|
else return { status: "error", error: e as any };
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async closeColumn(label: string) : Promise<Result<boolean, string>> {
|
async updateColumn(label: string, width: number, height: number, x: number, y: number) : Promise<Result<null, string>> {
|
||||||
try {
|
try {
|
||||||
return { status: "ok", data: await TAURI_INVOKE("close_column", { label }) };
|
return { status: "ok", data: await TAURI_INVOKE("update_column", { label, width, height, x, y }) };
|
||||||
} catch (e) {
|
|
||||||
if(e instanceof Error) throw e;
|
|
||||||
else return { status: "error", error: e as any };
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async repositionColumn(label: string, x: number, y: number) : Promise<Result<boolean, string>> {
|
|
||||||
try {
|
|
||||||
return { status: "ok", data: await TAURI_INVOKE("reposition_column", { label, x, y }) };
|
|
||||||
} catch (e) {
|
|
||||||
if(e instanceof Error) throw e;
|
|
||||||
else return { status: "error", error: e as any };
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async resizeColumn(label: string, width: number, height: number) : Promise<Result<boolean, string>> {
|
|
||||||
try {
|
|
||||||
return { status: "ok", data: await TAURI_INVOKE("resize_column", { label, width, height }) };
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if(e instanceof Error) throw e;
|
if(e instanceof Error) throw e;
|
||||||
else return { status: "error", error: e as any };
|
else return { status: "error", error: e as any };
|
||||||
@@ -486,6 +470,14 @@ async reloadColumn(label: string) : Promise<Result<boolean, string>> {
|
|||||||
else return { status: "error", error: e as any };
|
else return { status: "error", error: e as any };
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
async closeColumn(label: string) : Promise<Result<boolean, string>> {
|
||||||
|
try {
|
||||||
|
return { status: "ok", data: await TAURI_INVOKE("close_column", { label }) };
|
||||||
|
} catch (e) {
|
||||||
|
if(e instanceof Error) throw e;
|
||||||
|
else return { status: "error", error: e as any };
|
||||||
|
}
|
||||||
|
},
|
||||||
async openWindow(window: Window) : Promise<Result<null, string>> {
|
async openWindow(window: Window) : Promise<Result<null, string>> {
|
||||||
try {
|
try {
|
||||||
return { status: "ok", data: await TAURI_INVOKE("open_window", { window }) };
|
return { status: "ok", data: await TAURI_INVOKE("open_window", { window }) };
|
||||||
|
|||||||
@@ -1,107 +1,89 @@
|
|||||||
import { commands } from "@/commands.gen";
|
import { commands } from "@/commands.gen";
|
||||||
import { appColumns } from "@/commons";
|
import { appColumns } from "@/commons";
|
||||||
|
import { useRect } from "@/system";
|
||||||
import type { LumeColumn } from "@/types";
|
import type { LumeColumn } from "@/types";
|
||||||
import { CaretDown, Check } from "@phosphor-icons/react";
|
import { CaretDown, Check } from "@phosphor-icons/react";
|
||||||
import { useParams } from "@tanstack/react-router";
|
import { useParams } from "@tanstack/react-router";
|
||||||
import { useStore } from "@tanstack/react-store";
|
import { useStore } from "@tanstack/react-store";
|
||||||
import { invoke } from "@tauri-apps/api/core";
|
|
||||||
import { listen } from "@tauri-apps/api/event";
|
|
||||||
import { Menu, MenuItem, PredefinedMenuItem } from "@tauri-apps/api/menu";
|
import { Menu, MenuItem, PredefinedMenuItem } from "@tauri-apps/api/menu";
|
||||||
import { getCurrentWindow } from "@tauri-apps/api/window";
|
import { getCurrentWindow } from "@tauri-apps/api/window";
|
||||||
import { memo, useCallback, useEffect, useRef, useState } from "react";
|
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||||
import { Spinner } from "./spinner";
|
|
||||||
|
|
||||||
type WindowEvent = {
|
export function Column({ column }: { column: LumeColumn }) {
|
||||||
scroll: boolean;
|
|
||||||
resize: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Column = memo(function Column({ column }: { column: LumeColumn }) {
|
|
||||||
const params = useParams({ strict: false });
|
const params = useParams({ strict: false });
|
||||||
const container = useRef<HTMLDivElement>(null);
|
const webviewLabel = useMemo(
|
||||||
const webviewLabel = `column-${params.account}_${column.label}`;
|
() => `column-${params.account}_${column.label}`,
|
||||||
|
[params.account, column.label],
|
||||||
|
);
|
||||||
|
|
||||||
const [isCreated, setIsCreated] = useState(false);
|
const [rect, ref] = useRect();
|
||||||
|
const [error, setError] = useState<string>(null);
|
||||||
const repositionWebview = useCallback(async () => {
|
|
||||||
if (!container.current) return;
|
|
||||||
|
|
||||||
const newRect = container.current.getBoundingClientRect();
|
|
||||||
await invoke("reposition_column", {
|
|
||||||
label: webviewLabel,
|
|
||||||
x: newRect.x,
|
|
||||||
y: newRect.y,
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const resizeWebview = useCallback(async () => {
|
|
||||||
if (!container.current) return;
|
|
||||||
|
|
||||||
const newRect = container.current.getBoundingClientRect();
|
|
||||||
await invoke("resize_column", {
|
|
||||||
label: webviewLabel,
|
|
||||||
width: newRect.width,
|
|
||||||
height: newRect.height,
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isCreated) return;
|
(async () => {
|
||||||
|
if (rect) {
|
||||||
|
const res = await commands.updateColumn(
|
||||||
|
webviewLabel,
|
||||||
|
rect.width,
|
||||||
|
rect.height,
|
||||||
|
rect.x,
|
||||||
|
rect.y,
|
||||||
|
);
|
||||||
|
|
||||||
const unlisten = listen<WindowEvent>("child_webview", (data) => {
|
if (res.status === "ok") {
|
||||||
if (data.payload.scroll) repositionWebview();
|
console.log("webview is updated: ", webviewLabel);
|
||||||
if (data.payload.resize) repositionWebview().then(() => resizeWebview());
|
} else {
|
||||||
});
|
console.log("webview error: ", res.error);
|
||||||
|
}
|
||||||
return () => {
|
}
|
||||||
unlisten.then((f) => f());
|
})();
|
||||||
};
|
}, [rect]);
|
||||||
}, [isCreated]);
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!container.current) return;
|
const isCreated = window.sessionStorage.getItem(webviewLabel);
|
||||||
|
|
||||||
const rect = container.current.getBoundingClientRect();
|
if (!isCreated) {
|
||||||
const url = `${column.url}?account=${params.account}&label=${column.label}&name=${column.name}`;
|
const initialRect = ref.current.getBoundingClientRect();
|
||||||
|
|
||||||
const prop = {
|
commands
|
||||||
label: webviewLabel,
|
.createColumn({
|
||||||
x: rect.x,
|
label: webviewLabel,
|
||||||
y: rect.y,
|
x: initialRect.x,
|
||||||
width: rect.width,
|
y: initialRect.y,
|
||||||
height: rect.height,
|
width: initialRect.width,
|
||||||
url,
|
height: initialRect.height,
|
||||||
};
|
url: `${column.url}?account=${params.account}&label=${column.label}&name=${column.name}`,
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
if (res.status === "ok") {
|
||||||
|
console.log("webview is created: ", webviewLabel);
|
||||||
|
window.sessionStorage.setItem(webviewLabel, "");
|
||||||
|
} else {
|
||||||
|
setError(res.error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// create new webview
|
return () => {
|
||||||
invoke("create_column", { column: prop }).then(() => {
|
commands.closeColumn(webviewLabel).then((res) => {
|
||||||
console.log("created: ", webviewLabel);
|
if (res.status === "ok") {
|
||||||
setIsCreated(true);
|
console.log("webview is closed: ", webviewLabel);
|
||||||
});
|
} else {
|
||||||
|
console.log("webview error: ", res.error);
|
||||||
// close webview when unmounted
|
}
|
||||||
return () => {
|
});
|
||||||
invoke("close_column", { label: webviewLabel }).then(() => {
|
};
|
||||||
console.log("closed: ", webviewLabel);
|
}
|
||||||
});
|
|
||||||
};
|
|
||||||
}, [params.account]);
|
}, [params.account]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full w-[440px] shrink-0 border-r border-black/5 dark:border-white/5">
|
<div className="h-full w-[440px] shrink-0 border-r border-black/5 dark:border-white/5">
|
||||||
<div className="flex flex-col gap-px size-full">
|
<div className="flex flex-col gap-px size-full">
|
||||||
<Header label={column.label} />
|
<Header label={column.label} />
|
||||||
<div ref={container} className="flex-1 size-full">
|
<div ref={ref} className="flex-1 size-full" />
|
||||||
{!isCreated ? (
|
|
||||||
<div className="size-full flex items-center justify-center">
|
|
||||||
<Spinner />
|
|
||||||
</div>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
}
|
||||||
|
|
||||||
function Header({ label }: { label: string }) {
|
function Header({ label }: { label: string }) {
|
||||||
const [title, setTitle] = useState("");
|
const [title, setTitle] = useState("");
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import { Route as AccountSettingsRelayImport } from './routes/$account/_settings
|
|||||||
import { Route as AccountSettingsProfileImport } from './routes/$account/_settings/profile'
|
import { Route as AccountSettingsProfileImport } from './routes/$account/_settings/profile'
|
||||||
import { Route as AccountSettingsGeneralImport } from './routes/$account/_settings/general'
|
import { Route as AccountSettingsGeneralImport } from './routes/$account/_settings/general'
|
||||||
import { Route as AccountSettingsBitcoinConnectImport } from './routes/$account/_settings/bitcoin-connect'
|
import { Route as AccountSettingsBitcoinConnectImport } from './routes/$account/_settings/bitcoin-connect'
|
||||||
import { Route as AccountAppHomeImport } from './routes/$account/_app/home'
|
|
||||||
import { Route as ColumnsLayoutInterestsIdImport } from './routes/columns/_layout/interests.$id'
|
import { Route as ColumnsLayoutInterestsIdImport } from './routes/columns/_layout/interests.$id'
|
||||||
import { Route as ColumnsLayoutGroupsIdImport } from './routes/columns/_layout/groups.$id'
|
import { Route as ColumnsLayoutGroupsIdImport } from './routes/columns/_layout/groups.$id'
|
||||||
import { Route as ColumnsLayoutCreateNewsfeedUsersImport } from './routes/columns/_layout/create-newsfeed.users'
|
import { Route as ColumnsLayoutCreateNewsfeedUsersImport } from './routes/columns/_layout/create-newsfeed.users'
|
||||||
@@ -63,6 +62,7 @@ const ColumnsLayoutNotificationLazyImport = createFileRoute(
|
|||||||
const ColumnsLayoutLaunchpadLazyImport = createFileRoute(
|
const ColumnsLayoutLaunchpadLazyImport = createFileRoute(
|
||||||
'/columns/_layout/launchpad',
|
'/columns/_layout/launchpad',
|
||||||
)()
|
)()
|
||||||
|
const AccountAppHomeLazyImport = createFileRoute('/$account/_app/home')()
|
||||||
const ColumnsLayoutUsersIdLazyImport = createFileRoute(
|
const ColumnsLayoutUsersIdLazyImport = createFileRoute(
|
||||||
'/columns/_layout/users/$id',
|
'/columns/_layout/users/$id',
|
||||||
)()
|
)()
|
||||||
@@ -208,6 +208,13 @@ const ColumnsLayoutLaunchpadLazyRoute = ColumnsLayoutLaunchpadLazyImport.update(
|
|||||||
import('./routes/columns/_layout/launchpad.lazy').then((d) => d.Route),
|
import('./routes/columns/_layout/launchpad.lazy').then((d) => d.Route),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const AccountAppHomeLazyRoute = AccountAppHomeLazyImport.update({
|
||||||
|
path: '/home',
|
||||||
|
getParentRoute: () => AccountAppRoute,
|
||||||
|
} as any).lazy(() =>
|
||||||
|
import('./routes/$account/_app.home.lazy').then((d) => d.Route),
|
||||||
|
)
|
||||||
|
|
||||||
const ColumnsLayoutStoriesRoute = ColumnsLayoutStoriesImport.update({
|
const ColumnsLayoutStoriesRoute = ColumnsLayoutStoriesImport.update({
|
||||||
path: '/stories',
|
path: '/stories',
|
||||||
getParentRoute: () => ColumnsLayoutRoute,
|
getParentRoute: () => ColumnsLayoutRoute,
|
||||||
@@ -271,13 +278,6 @@ const AccountSettingsBitcoinConnectRoute =
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
const AccountAppHomeRoute = AccountAppHomeImport.update({
|
|
||||||
path: '/home',
|
|
||||||
getParentRoute: () => AccountAppRoute,
|
|
||||||
} as any).lazy(() =>
|
|
||||||
import('./routes/$account/_app/home.lazy').then((d) => d.Route),
|
|
||||||
)
|
|
||||||
|
|
||||||
const ColumnsLayoutUsersIdLazyRoute = ColumnsLayoutUsersIdLazyImport.update({
|
const ColumnsLayoutUsersIdLazyRoute = ColumnsLayoutUsersIdLazyImport.update({
|
||||||
path: '/users/$id',
|
path: '/users/$id',
|
||||||
getParentRoute: () => ColumnsLayoutRoute,
|
getParentRoute: () => ColumnsLayoutRoute,
|
||||||
@@ -457,13 +457,6 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof EditorIndexImport
|
preLoaderRoute: typeof EditorIndexImport
|
||||||
parentRoute: typeof rootRoute
|
parentRoute: typeof rootRoute
|
||||||
}
|
}
|
||||||
'/$account/_app/home': {
|
|
||||||
id: '/$account/_app/home'
|
|
||||||
path: '/home'
|
|
||||||
fullPath: '/$account/home'
|
|
||||||
preLoaderRoute: typeof AccountAppHomeImport
|
|
||||||
parentRoute: typeof AccountAppImport
|
|
||||||
}
|
|
||||||
'/$account/_settings/bitcoin-connect': {
|
'/$account/_settings/bitcoin-connect': {
|
||||||
id: '/$account/_settings/bitcoin-connect'
|
id: '/$account/_settings/bitcoin-connect'
|
||||||
path: '/bitcoin-connect'
|
path: '/bitcoin-connect'
|
||||||
@@ -527,6 +520,13 @@ declare module '@tanstack/react-router' {
|
|||||||
preLoaderRoute: typeof ColumnsLayoutStoriesImport
|
preLoaderRoute: typeof ColumnsLayoutStoriesImport
|
||||||
parentRoute: typeof ColumnsLayoutImport
|
parentRoute: typeof ColumnsLayoutImport
|
||||||
}
|
}
|
||||||
|
'/$account/_app/home': {
|
||||||
|
id: '/$account/_app/home'
|
||||||
|
path: '/home'
|
||||||
|
fullPath: '/$account/home'
|
||||||
|
preLoaderRoute: typeof AccountAppHomeLazyImport
|
||||||
|
parentRoute: typeof AccountAppImport
|
||||||
|
}
|
||||||
'/columns/_layout/launchpad': {
|
'/columns/_layout/launchpad': {
|
||||||
id: '/columns/_layout/launchpad'
|
id: '/columns/_layout/launchpad'
|
||||||
path: '/launchpad'
|
path: '/launchpad'
|
||||||
@@ -617,11 +617,11 @@ declare module '@tanstack/react-router' {
|
|||||||
// Create and export the route tree
|
// Create and export the route tree
|
||||||
|
|
||||||
interface AccountAppRouteChildren {
|
interface AccountAppRouteChildren {
|
||||||
AccountAppHomeRoute: typeof AccountAppHomeRoute
|
AccountAppHomeLazyRoute: typeof AccountAppHomeLazyRoute
|
||||||
}
|
}
|
||||||
|
|
||||||
const AccountAppRouteChildren: AccountAppRouteChildren = {
|
const AccountAppRouteChildren: AccountAppRouteChildren = {
|
||||||
AccountAppHomeRoute: AccountAppHomeRoute,
|
AccountAppHomeLazyRoute: AccountAppHomeLazyRoute,
|
||||||
}
|
}
|
||||||
|
|
||||||
const AccountAppRouteWithChildren = AccountAppRoute._addFileChildren(
|
const AccountAppRouteWithChildren = AccountAppRoute._addFileChildren(
|
||||||
@@ -745,7 +745,6 @@ export interface FileRoutesByFullPath {
|
|||||||
'/auth/import': typeof AuthImportLazyRoute
|
'/auth/import': typeof AuthImportLazyRoute
|
||||||
'/auth/new': typeof AuthNewLazyRoute
|
'/auth/new': typeof AuthNewLazyRoute
|
||||||
'/editor': typeof EditorIndexRoute
|
'/editor': typeof EditorIndexRoute
|
||||||
'/$account/home': typeof AccountAppHomeRoute
|
|
||||||
'/$account/bitcoin-connect': typeof AccountSettingsBitcoinConnectRoute
|
'/$account/bitcoin-connect': typeof AccountSettingsBitcoinConnectRoute
|
||||||
'/$account/general': typeof AccountSettingsGeneralRoute
|
'/$account/general': typeof AccountSettingsGeneralRoute
|
||||||
'/$account/profile': typeof AccountSettingsProfileRoute
|
'/$account/profile': typeof AccountSettingsProfileRoute
|
||||||
@@ -755,6 +754,7 @@ export interface FileRoutesByFullPath {
|
|||||||
'/columns/global': typeof ColumnsLayoutGlobalRoute
|
'/columns/global': typeof ColumnsLayoutGlobalRoute
|
||||||
'/columns/newsfeed': typeof ColumnsLayoutNewsfeedRoute
|
'/columns/newsfeed': typeof ColumnsLayoutNewsfeedRoute
|
||||||
'/columns/stories': typeof ColumnsLayoutStoriesRoute
|
'/columns/stories': typeof ColumnsLayoutStoriesRoute
|
||||||
|
'/$account/home': typeof AccountAppHomeLazyRoute
|
||||||
'/columns/launchpad': typeof ColumnsLayoutLaunchpadLazyRoute
|
'/columns/launchpad': typeof ColumnsLayoutLaunchpadLazyRoute
|
||||||
'/columns/notification': typeof ColumnsLayoutNotificationLazyRoute
|
'/columns/notification': typeof ColumnsLayoutNotificationLazyRoute
|
||||||
'/columns/onboarding': typeof ColumnsLayoutOnboardingLazyRoute
|
'/columns/onboarding': typeof ColumnsLayoutOnboardingLazyRoute
|
||||||
@@ -785,7 +785,6 @@ export interface FileRoutesByTo {
|
|||||||
'/auth/import': typeof AuthImportLazyRoute
|
'/auth/import': typeof AuthImportLazyRoute
|
||||||
'/auth/new': typeof AuthNewLazyRoute
|
'/auth/new': typeof AuthNewLazyRoute
|
||||||
'/editor': typeof EditorIndexRoute
|
'/editor': typeof EditorIndexRoute
|
||||||
'/$account/home': typeof AccountAppHomeRoute
|
|
||||||
'/$account/bitcoin-connect': typeof AccountSettingsBitcoinConnectRoute
|
'/$account/bitcoin-connect': typeof AccountSettingsBitcoinConnectRoute
|
||||||
'/$account/general': typeof AccountSettingsGeneralRoute
|
'/$account/general': typeof AccountSettingsGeneralRoute
|
||||||
'/$account/profile': typeof AccountSettingsProfileRoute
|
'/$account/profile': typeof AccountSettingsProfileRoute
|
||||||
@@ -795,6 +794,7 @@ export interface FileRoutesByTo {
|
|||||||
'/columns/global': typeof ColumnsLayoutGlobalRoute
|
'/columns/global': typeof ColumnsLayoutGlobalRoute
|
||||||
'/columns/newsfeed': typeof ColumnsLayoutNewsfeedRoute
|
'/columns/newsfeed': typeof ColumnsLayoutNewsfeedRoute
|
||||||
'/columns/stories': typeof ColumnsLayoutStoriesRoute
|
'/columns/stories': typeof ColumnsLayoutStoriesRoute
|
||||||
|
'/$account/home': typeof AccountAppHomeLazyRoute
|
||||||
'/columns/launchpad': typeof ColumnsLayoutLaunchpadLazyRoute
|
'/columns/launchpad': typeof ColumnsLayoutLaunchpadLazyRoute
|
||||||
'/columns/notification': typeof ColumnsLayoutNotificationLazyRoute
|
'/columns/notification': typeof ColumnsLayoutNotificationLazyRoute
|
||||||
'/columns/onboarding': typeof ColumnsLayoutOnboardingLazyRoute
|
'/columns/onboarding': typeof ColumnsLayoutOnboardingLazyRoute
|
||||||
@@ -829,7 +829,6 @@ export interface FileRoutesById {
|
|||||||
'/auth/import': typeof AuthImportLazyRoute
|
'/auth/import': typeof AuthImportLazyRoute
|
||||||
'/auth/new': typeof AuthNewLazyRoute
|
'/auth/new': typeof AuthNewLazyRoute
|
||||||
'/editor/': typeof EditorIndexRoute
|
'/editor/': typeof EditorIndexRoute
|
||||||
'/$account/_app/home': typeof AccountAppHomeRoute
|
|
||||||
'/$account/_settings/bitcoin-connect': typeof AccountSettingsBitcoinConnectRoute
|
'/$account/_settings/bitcoin-connect': typeof AccountSettingsBitcoinConnectRoute
|
||||||
'/$account/_settings/general': typeof AccountSettingsGeneralRoute
|
'/$account/_settings/general': typeof AccountSettingsGeneralRoute
|
||||||
'/$account/_settings/profile': typeof AccountSettingsProfileRoute
|
'/$account/_settings/profile': typeof AccountSettingsProfileRoute
|
||||||
@@ -839,6 +838,7 @@ export interface FileRoutesById {
|
|||||||
'/columns/_layout/global': typeof ColumnsLayoutGlobalRoute
|
'/columns/_layout/global': typeof ColumnsLayoutGlobalRoute
|
||||||
'/columns/_layout/newsfeed': typeof ColumnsLayoutNewsfeedRoute
|
'/columns/_layout/newsfeed': typeof ColumnsLayoutNewsfeedRoute
|
||||||
'/columns/_layout/stories': typeof ColumnsLayoutStoriesRoute
|
'/columns/_layout/stories': typeof ColumnsLayoutStoriesRoute
|
||||||
|
'/$account/_app/home': typeof AccountAppHomeLazyRoute
|
||||||
'/columns/_layout/launchpad': typeof ColumnsLayoutLaunchpadLazyRoute
|
'/columns/_layout/launchpad': typeof ColumnsLayoutLaunchpadLazyRoute
|
||||||
'/columns/_layout/notification': typeof ColumnsLayoutNotificationLazyRoute
|
'/columns/_layout/notification': typeof ColumnsLayoutNotificationLazyRoute
|
||||||
'/columns/_layout/onboarding': typeof ColumnsLayoutOnboardingLazyRoute
|
'/columns/_layout/onboarding': typeof ColumnsLayoutOnboardingLazyRoute
|
||||||
@@ -871,7 +871,6 @@ export interface FileRouteTypes {
|
|||||||
| '/auth/import'
|
| '/auth/import'
|
||||||
| '/auth/new'
|
| '/auth/new'
|
||||||
| '/editor'
|
| '/editor'
|
||||||
| '/$account/home'
|
|
||||||
| '/$account/bitcoin-connect'
|
| '/$account/bitcoin-connect'
|
||||||
| '/$account/general'
|
| '/$account/general'
|
||||||
| '/$account/profile'
|
| '/$account/profile'
|
||||||
@@ -881,6 +880,7 @@ export interface FileRouteTypes {
|
|||||||
| '/columns/global'
|
| '/columns/global'
|
||||||
| '/columns/newsfeed'
|
| '/columns/newsfeed'
|
||||||
| '/columns/stories'
|
| '/columns/stories'
|
||||||
|
| '/$account/home'
|
||||||
| '/columns/launchpad'
|
| '/columns/launchpad'
|
||||||
| '/columns/notification'
|
| '/columns/notification'
|
||||||
| '/columns/onboarding'
|
| '/columns/onboarding'
|
||||||
@@ -910,7 +910,6 @@ export interface FileRouteTypes {
|
|||||||
| '/auth/import'
|
| '/auth/import'
|
||||||
| '/auth/new'
|
| '/auth/new'
|
||||||
| '/editor'
|
| '/editor'
|
||||||
| '/$account/home'
|
|
||||||
| '/$account/bitcoin-connect'
|
| '/$account/bitcoin-connect'
|
||||||
| '/$account/general'
|
| '/$account/general'
|
||||||
| '/$account/profile'
|
| '/$account/profile'
|
||||||
@@ -920,6 +919,7 @@ export interface FileRouteTypes {
|
|||||||
| '/columns/global'
|
| '/columns/global'
|
||||||
| '/columns/newsfeed'
|
| '/columns/newsfeed'
|
||||||
| '/columns/stories'
|
| '/columns/stories'
|
||||||
|
| '/$account/home'
|
||||||
| '/columns/launchpad'
|
| '/columns/launchpad'
|
||||||
| '/columns/notification'
|
| '/columns/notification'
|
||||||
| '/columns/onboarding'
|
| '/columns/onboarding'
|
||||||
@@ -952,7 +952,6 @@ export interface FileRouteTypes {
|
|||||||
| '/auth/import'
|
| '/auth/import'
|
||||||
| '/auth/new'
|
| '/auth/new'
|
||||||
| '/editor/'
|
| '/editor/'
|
||||||
| '/$account/_app/home'
|
|
||||||
| '/$account/_settings/bitcoin-connect'
|
| '/$account/_settings/bitcoin-connect'
|
||||||
| '/$account/_settings/general'
|
| '/$account/_settings/general'
|
||||||
| '/$account/_settings/profile'
|
| '/$account/_settings/profile'
|
||||||
@@ -962,6 +961,7 @@ export interface FileRouteTypes {
|
|||||||
| '/columns/_layout/global'
|
| '/columns/_layout/global'
|
||||||
| '/columns/_layout/newsfeed'
|
| '/columns/_layout/newsfeed'
|
||||||
| '/columns/_layout/stories'
|
| '/columns/_layout/stories'
|
||||||
|
| '/$account/_app/home'
|
||||||
| '/columns/_layout/launchpad'
|
| '/columns/_layout/launchpad'
|
||||||
| '/columns/_layout/notification'
|
| '/columns/_layout/notification'
|
||||||
| '/columns/_layout/onboarding'
|
| '/columns/_layout/onboarding'
|
||||||
@@ -1131,10 +1131,6 @@ export const routeTree = rootRoute
|
|||||||
"/editor/": {
|
"/editor/": {
|
||||||
"filePath": "editor/index.tsx"
|
"filePath": "editor/index.tsx"
|
||||||
},
|
},
|
||||||
"/$account/_app/home": {
|
|
||||||
"filePath": "$account/_app/home.tsx",
|
|
||||||
"parent": "/$account/_app"
|
|
||||||
},
|
|
||||||
"/$account/_settings/bitcoin-connect": {
|
"/$account/_settings/bitcoin-connect": {
|
||||||
"filePath": "$account/_settings/bitcoin-connect.tsx",
|
"filePath": "$account/_settings/bitcoin-connect.tsx",
|
||||||
"parent": "/$account/_settings"
|
"parent": "/$account/_settings"
|
||||||
@@ -1175,6 +1171,10 @@ export const routeTree = rootRoute
|
|||||||
"filePath": "columns/_layout/stories.tsx",
|
"filePath": "columns/_layout/stories.tsx",
|
||||||
"parent": "/columns/_layout"
|
"parent": "/columns/_layout"
|
||||||
},
|
},
|
||||||
|
"/$account/_app/home": {
|
||||||
|
"filePath": "$account/_app.home.lazy.tsx",
|
||||||
|
"parent": "/$account/_app"
|
||||||
|
},
|
||||||
"/columns/_layout/launchpad": {
|
"/columns/_layout/launchpad": {
|
||||||
"filePath": "columns/_layout/launchpad.lazy.tsx",
|
"filePath": "columns/_layout/launchpad.lazy.tsx",
|
||||||
"parent": "/columns/_layout"
|
"parent": "/columns/_layout"
|
||||||
|
|||||||
@@ -45,16 +45,16 @@ function Screen() {
|
|||||||
}, [emblaApi]);
|
}, [emblaApi]);
|
||||||
|
|
||||||
const emitScrollEvent = useCallback(() => {
|
const emitScrollEvent = useCallback(() => {
|
||||||
getCurrentWindow().emit("child_webview", { scroll: true });
|
getCurrentWindow().emit("column_scroll", {});
|
||||||
}, []);
|
|
||||||
|
|
||||||
const emitResizeEvent = useCallback(() => {
|
|
||||||
getCurrentWindow().emit("child_webview", { resize: true, direction: "x" });
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const add = useDebouncedCallback((column: LumeColumn) => {
|
const add = useDebouncedCallback((column: LumeColumn) => {
|
||||||
column.label = `${column.label}-${nanoid()}`; // update col label
|
column.label = `${column.label}-${nanoid()}`; // update col label
|
||||||
appColumns.setState((prev) => [column, ...prev]);
|
appColumns.setState((prev) => [column, ...prev]);
|
||||||
|
|
||||||
|
if (emblaApi) {
|
||||||
|
emblaApi.scrollTo(0, true);
|
||||||
|
}
|
||||||
}, 150);
|
}, 150);
|
||||||
|
|
||||||
const remove = useDebouncedCallback((label: string) => {
|
const remove = useDebouncedCallback((label: string) => {
|
||||||
@@ -112,16 +112,14 @@ function Screen() {
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (emblaApi) {
|
if (emblaApi) {
|
||||||
emblaApi.on("scroll", emitScrollEvent);
|
emblaApi.on("scroll", emitScrollEvent);
|
||||||
emblaApi.on("resize", emitResizeEvent);
|
|
||||||
emblaApi.on("slidesChanged", emitScrollEvent);
|
emblaApi.on("slidesChanged", emitScrollEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
emblaApi?.off("scroll", emitScrollEvent);
|
emblaApi?.off("scroll", emitScrollEvent);
|
||||||
emblaApi?.off("resize", emitResizeEvent);
|
|
||||||
emblaApi?.off("slidesChanged", emitScrollEvent);
|
emblaApi?.off("slidesChanged", emitScrollEvent);
|
||||||
};
|
};
|
||||||
}, [emblaApi, emitScrollEvent, emitResizeEvent]);
|
}, [emblaApi, emitScrollEvent]);
|
||||||
|
|
||||||
// Listen for keyboard event
|
// Listen for keyboard event
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
import { createFileRoute } from "@tanstack/react-router";
|
|
||||||
|
|
||||||
export const Route = createFileRoute("/$account/_app/home")();
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
export * from "./event";
|
export * from "./event";
|
||||||
export * from "./window";
|
export * from "./window";
|
||||||
export * from "./hooks/useEvent";
|
export * from "./useEvent";
|
||||||
export * from "./hooks/useProfile";
|
export * from "./useProfile";
|
||||||
|
export * from "./useRect";
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { type Result, type RichEvent, commands } from "@/commands.gen";
|
|||||||
import type { NostrEvent } from "@/types";
|
import type { NostrEvent } from "@/types";
|
||||||
import { useQuery } from "@tanstack/react-query";
|
import { useQuery } from "@tanstack/react-query";
|
||||||
import { nip19 } from "nostr-tools";
|
import { nip19 } from "nostr-tools";
|
||||||
import { LumeEvent } from "../event";
|
import { LumeEvent } from "./event";
|
||||||
|
|
||||||
export function useEvent(id: string, repost?: string) {
|
export function useEvent(id: string, repost?: string) {
|
||||||
const { isLoading, isError, error, data } = useQuery({
|
const { isLoading, isError, error, data } = useQuery({
|
||||||
53
src/system/useRect.ts
Normal file
53
src/system/useRect.ts
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
import { listen } from "@tauri-apps/api/event";
|
||||||
|
import { useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
|
type MutableRefObject<T> = {
|
||||||
|
current: T;
|
||||||
|
};
|
||||||
|
|
||||||
|
const useEffectInEvent = <K extends keyof WindowEventMap>(
|
||||||
|
event: K,
|
||||||
|
set: () => void,
|
||||||
|
useCapture?: boolean,
|
||||||
|
) => {
|
||||||
|
useEffect(() => {
|
||||||
|
if (set) {
|
||||||
|
set();
|
||||||
|
window.addEventListener(event, set, useCapture);
|
||||||
|
|
||||||
|
return () => window.removeEventListener(event, set, useCapture);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
};
|
||||||
|
|
||||||
|
const useTauriInEvent = (set: () => void) => {
|
||||||
|
useEffect(() => {
|
||||||
|
if (set) {
|
||||||
|
const unlisten = listen("column_scroll", () => {
|
||||||
|
set();
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
unlisten.then((f) => f());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useRect = <T extends HTMLDivElement | null>(): [
|
||||||
|
DOMRect | undefined,
|
||||||
|
MutableRefObject<T | null>,
|
||||||
|
] => {
|
||||||
|
const ref = useRef<T>(null);
|
||||||
|
const [rect, setRect] = useState<DOMRect>();
|
||||||
|
|
||||||
|
const set = (): void => {
|
||||||
|
setRect(ref.current?.getBoundingClientRect());
|
||||||
|
};
|
||||||
|
|
||||||
|
useTauriInEvent(set);
|
||||||
|
useEffectInEvent("resize", set);
|
||||||
|
useEffectInEvent("scroll", set, true);
|
||||||
|
|
||||||
|
return [rect, ref];
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user