From 68b2453981c2305e70c39ad104b1afa44978e593 Mon Sep 17 00:00:00 2001 From: don Date: Fri, 20 Dec 2024 00:33:43 +0100 Subject: [PATCH] new day new cleanup --- src-tauri/common/src/types/orm_query.rs | 7 ++ src-tauri/src/commands/clipboard.rs | 21 ++++-- src-tauri/src/service/clipboard.rs | 10 ++- src/components/pages/app/app.tsx | 6 +- .../pages/app/clipboard/base-clipboard.tsx | 64 ++++++++++--------- .../pages/app/clipboard/clipboards.tsx | 7 +- .../pages/app/clipboard/file-clipboard.tsx | 45 ++++++------- .../pages/app/clipboard/image-clipboard.tsx | 48 +++++++------- .../pages/app/clipboard/text-clipboard.tsx | 45 +++++++------ src/components/utils/hotkey-number.tsx | 2 +- src/store/clipboard-store.ts | 18 +++++- src/types/index.ts | 5 ++ src/types/tauri-invoke.ts | 4 +- 13 files changed, 165 insertions(+), 117 deletions(-) diff --git a/src-tauri/common/src/types/orm_query.rs b/src-tauri/common/src/types/orm_query.rs index d5b67f29..54d97632 100644 --- a/src-tauri/common/src/types/orm_query.rs +++ b/src-tauri/common/src/types/orm_query.rs @@ -14,6 +14,13 @@ pub struct ClipboardWithRelations { pub files: Vec, } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ClipboardsResponse { + pub clipboards: Vec, + pub total: u64, + pub has_more: bool, +} + #[derive(Debug, Clone)] pub struct ClipboardManager { pub clipboard_model: entity::clipboard::ActiveModel, diff --git a/src-tauri/src/commands/clipboard.rs b/src-tauri/src/commands/clipboard.rs index f823d2d2..c254b9ae 100644 --- a/src-tauri/src/commands/clipboard.rs +++ b/src-tauri/src/commands/clipboard.rs @@ -2,13 +2,13 @@ extern crate alloc; extern crate image; use crate::{ service::clipboard::{ - clear_clipboards_db, copy_clipboard_from_id, delete_clipboard_db, get_clipboard_db, - get_clipboards_db, star_clipboard_db, + clear_clipboards_db, copy_clipboard_from_id, delete_clipboard_db, get_clipboard_count_db, + get_clipboard_db, get_clipboards_db, star_clipboard_db, }, tauri_config::config::APP, utils::hotkey_manager::unregister_hotkeys, }; -use common::types::{enums::ClipboardType, orm_query::ClipboardWithRelations, types::CommandError}; +use common::types::{enums::ClipboardType, orm_query::ClipboardsResponse, types::CommandError}; use std::fs::File; use tauri::Manager; @@ -18,8 +18,19 @@ pub async fn get_clipboards( search: Option, star: Option, img: Option, -) -> Result, CommandError> { - Ok(get_clipboards_db(cursor, search, star, img).await?) +) -> Result { + let clipboards = get_clipboards_db(cursor, search, star, img).await?; + let total = get_clipboard_count_db().await?; + + // Calculate if there are more items + let current_position = cursor.unwrap_or(0) + clipboards.len() as u64; + let has_more = current_position < total; + + Ok(ClipboardsResponse { + clipboards, + total, + has_more, + }) } #[tauri::command] diff --git a/src-tauri/src/service/clipboard.rs b/src-tauri/src/service/clipboard.rs index 6cbeaf7b..cc974262 100644 --- a/src-tauri/src/service/clipboard.rs +++ b/src-tauri/src/service/clipboard.rs @@ -47,6 +47,14 @@ pub async fn load_clipboards_with_relations( .collect() } +pub async fn get_clipboard_count_db() -> Result { + let db = connection::db().await?; + + let count = clipboard::Entity::find().count(&db).await?; + + Ok(count) +} + pub async fn insert_clipboard_db(model: ClipboardManager) -> Result { let db = connection::db().await?; let clipboard = model.clipboard_model.insert(&db).await?; @@ -181,7 +189,7 @@ pub async fn get_clipboards_db( q.filter(f) }) .offset(cursor) - .limit(10) + .limit(25) .order_by_desc(clipboard::Column::Id); Ok(load_clipboards_with_relations(query.all(&db).await?).await) diff --git a/src/components/pages/app/app.tsx b/src/components/pages/app/app.tsx index a26a8999..87d9ff05 100644 --- a/src/components/pages/app/app.tsx +++ b/src/components/pages/app/app.tsx @@ -1,13 +1,13 @@ import { BsHddFill } from "solid-icons/bs"; import { FiGlobe } from "solid-icons/fi"; import { Show } from "solid-js"; +import { AppStore } from "../../../store/app-store"; +import { SettingsStore } from "../../../store/settings-store"; import { AppSidebar } from "../../navigation/app-sidebar"; import { ClipboardHistory } from "./clipboard-history"; import { RecentClipboards } from "./recent-clipboards"; import { StarredClipboards } from "./starred-clipboards"; import { ViewMore } from "./view-more"; -import { AppStore } from "../../../store/app-store"; -import { SettingsStore } from "../../../store/settings-store"; function App() { const { settings } = SettingsStore; @@ -19,7 +19,7 @@ function App() {
-
+

{getCurrentTab()?.name?.toUpperCase()}

diff --git a/src/components/pages/app/clipboard/base-clipboard.tsx b/src/components/pages/app/clipboard/base-clipboard.tsx index dabe9235..5fdfa950 100644 --- a/src/components/pages/app/clipboard/base-clipboard.tsx +++ b/src/components/pages/app/clipboard/base-clipboard.tsx @@ -18,12 +18,16 @@ interface BaseClipboardProps { } export const BaseClipboard: Component = (props) => { - const { setClipboards } = ClipboardStore; + const { setClipboards, resetClipboards } = ClipboardStore; const { clipboard } = props.data; const handleDelete = async (id: number) => { if (await invokeCommand(InvokeCommand.DeleteClipboard, { id })) { - setClipboards((prev) => prev.filter((o) => o.clipboard.id !== id)); + setClipboards((prev) => { + const updated = prev.filter((o) => o.clipboard.id !== id); + if (!updated.length) resetClipboards(); + return updated; + }); } }; @@ -66,45 +70,47 @@ export const BaseClipboard: Component = (props) => { return (
{/* Actions overlay */} -
-
- { - e.stopPropagation(); - handleStar(clipboard); - }} - class={`${ - clipboard.star ? "text-yellow-400 dark:text-yellow-300" : "hidden text-zinc-700" - } text-lg hover:text-yellow-400 group-hover:block dark:text-white dark:hover:text-yellow-300`} +
+ { + e.stopPropagation(); + handleStar(clipboard); + }} + title="Star" + class={`${ + clipboard.star ? "text-yellow-400 dark:text-yellow-300" : "hidden text-zinc-700" + } cursor-pointer text-lg hover:text-yellow-400 group-hover:block dark:text-white dark:hover:text-yellow-300`} + /> + {props.data.rtf && ( +
+ )} { e.stopPropagation(); handleDelete(clipboard.id); }} - class="hidden text-lg text-zinc-700 hover:text-red-600 group-hover:block dark:text-white dark:hover:text-red-600" + title="Delete" + class="hidden cursor-pointer text-lg text-zinc-700 hover:text-red-600 group-hover:block dark:text-white dark:hover:text-red-600" />
{/* Content rendered by specific clipboard type */} {clipboard.types.includes(ClipboardType.Image) && } {clipboard.types.includes(ClipboardType.File) && } - {clipboard.types.includes(ClipboardType.Text) && } + {(clipboard.types.includes(ClipboardType.Text) || + clipboard.types.includes(ClipboardType.Html) || + clipboard.types.includes(ClipboardType.Rtf)) && }
); }; diff --git a/src/components/pages/app/clipboard/clipboards.tsx b/src/components/pages/app/clipboard/clipboards.tsx index 51ef9068..dc9425c0 100644 --- a/src/components/pages/app/clipboard/clipboards.tsx +++ b/src/components/pages/app/clipboard/clipboards.tsx @@ -6,6 +6,7 @@ import { Component, For, Show, createSignal, onMount } from "solid-js"; import clippy from "../../../../assets/clippy.png"; import { ClipboardStore } from "../../../../store/clipboard-store"; import { HotkeyStore } from "../../../../store/hotkey-store"; +import { HotkeyEvent } from "../../../../types/enums"; import { ListenEvent } from "../../../../types/tauri-listen"; import { listenEvent } from "../../../../utils/tauri"; import { BaseClipboard } from "./base-clipboard"; @@ -14,7 +15,7 @@ dayjs.extend(utc); dayjs.extend(relativeTime); export const Clipboards: Component = () => { - const { clipboards, setClipboards, getClipboards, setWhere, clipboardRef, setClipboardRef } = ClipboardStore; + const { clipboards, setClipboards, getClipboards, setWhere, clipboardRef, setClipboardRef, hasMore } = ClipboardStore; const { globalHotkeyEvent, hotkeys } = HotkeyStore; const [scrollToTop, setScrollToTop] = createSignal(false); @@ -26,7 +27,7 @@ export const Clipboards: Component = () => { clipboardRef()!.scrollTop !== 0 ? setScrollToTop(true) : setScrollToTop(false); - if (bottom) { + if (bottom && hasMore()) { setWhere((prev) => ({ ...prev, cursor: clipboards().length })); const newClipboards = await getClipboards(); setClipboards((prev) => [...prev, ...newClipboards]); @@ -56,7 +57,7 @@ export const Clipboards: Component = () => {
- {hotkeys().find((key) => key.event === "scroll_to_top")?.key} + {hotkeys().find((key) => key.event === HotkeyEvent.ScrollToTop)?.key}
diff --git a/src/components/pages/app/clipboard/file-clipboard.tsx b/src/components/pages/app/clipboard/file-clipboard.tsx index 5b5812d2..766fc8f1 100644 --- a/src/components/pages/app/clipboard/file-clipboard.tsx +++ b/src/components/pages/app/clipboard/file-clipboard.tsx @@ -36,7 +36,6 @@ export const FileClipboard: Component = (props) => { }, {} as Record ); - return grouped || {}; }; @@ -52,34 +51,26 @@ export const FileClipboard: Component = (props) => { diff --git a/src/components/pages/app/clipboard/image-clipboard.tsx b/src/components/pages/app/clipboard/image-clipboard.tsx index 227744d1..04aeb0ed 100644 --- a/src/components/pages/app/clipboard/image-clipboard.tsx +++ b/src/components/pages/app/clipboard/image-clipboard.tsx @@ -1,12 +1,12 @@ +import dayjs from "dayjs"; import { BsImages } from "solid-icons/bs"; import { Component } from "solid-js"; import { ClipboardWithRelations } from "../../../../types"; -import { formatBytes } from "../../../../utils/helpers"; -import { HotkeyNumber } from "../../../utils/hotkey-number"; -import dayjs from "dayjs"; import { ClipboardType } from "../../../../types/enums"; import { InvokeCommand } from "../../../../types/tauri-invoke"; +import { formatBytes } from "../../../../utils/helpers"; import { invokeCommand } from "../../../../utils/tauri"; +import { HotkeyNumber } from "../../../utils/hotkey-number"; interface ImageClipboardProps { data: ClipboardWithRelations; @@ -34,35 +34,33 @@ export const ImageClipboard: Component = (props) => { await invokeCommand(InvokeCommand.SaveClipboardImage, { id: props.data.clipboard.id }); }; + const imageInfo = + props.data.image && + `${props.data.image.width}x${props.data.image.height} ${formatBytes(Number(props.data.image.size || "0"))}`; + return ( diff --git a/src/components/pages/app/clipboard/text-clipboard.tsx b/src/components/pages/app/clipboard/text-clipboard.tsx index 49fab406..46205198 100644 --- a/src/components/pages/app/clipboard/text-clipboard.tsx +++ b/src/components/pages/app/clipboard/text-clipboard.tsx @@ -1,11 +1,11 @@ +import dayjs from "dayjs"; import { IoText } from "solid-icons/io"; import { Component } from "solid-js"; import { ClipboardWithRelations } from "../../../../types"; -import { HotkeyNumber } from "../../../utils/hotkey-number"; -import dayjs from "dayjs"; import { ClipboardType } from "../../../../types/enums"; import { InvokeCommand } from "../../../../types/tauri-invoke"; import { invokeCommand } from "../../../../utils/tauri"; +import { HotkeyNumber } from "../../../utils/hotkey-number"; interface TextClipboardProps { data: ClipboardWithRelations; @@ -13,11 +13,23 @@ interface TextClipboardProps { } export const TextClipboard: Component = (props) => { + let type = ClipboardType.Text; + let data = props.data.text?.data; + + if (!props.data.text?.data && props.data.html?.data) { + type = ClipboardType.Html; + data = props.data.html.data; + } + if (!props.data.text?.data && props.data.rtf?.data) { + type = ClipboardType.Rtf; + data = props.data.rtf.data; + } + const handleClick = async (e: MouseEvent) => { e.stopPropagation(); await invokeCommand(InvokeCommand.CopyClipboard, { id: props.data.clipboard.id, - type: ClipboardType.Text, + type, }); }; @@ -25,23 +37,20 @@ export const TextClipboard: Component = (props) => { diff --git a/src/components/utils/hotkey-number.tsx b/src/components/utils/hotkey-number.tsx index aedd51cd..e0fdb9ee 100644 --- a/src/components/utils/hotkey-number.tsx +++ b/src/components/utils/hotkey-number.tsx @@ -6,7 +6,7 @@ export const HotkeyNumber: Component<{ index: number }> = (props) => { return ( -
+
{props.index + 1}
diff --git a/src/store/clipboard-store.ts b/src/store/clipboard-store.ts index 05d43817..5a017a70 100644 --- a/src/store/clipboard-store.ts +++ b/src/store/clipboard-store.ts @@ -14,12 +14,14 @@ function createClipboardStore() { const [clipboardRef, setClipboardRef] = createSignal(); const [clipboards, setClipboards] = createSignal([]); const [where, setWhere] = createSignal(initialWhere); - + const [hasMore, setHasMore] = createSignal(true); const resetWhere = () => setWhere(initialWhere); const getClipboards = async () => { - const clipboards = await invokeCommand(InvokeCommand.GetClipboards, where()); - return clipboards; + const response = await invokeCommand(InvokeCommand.GetClipboards, where()); + console.log(response); + setHasMore(response.has_more); + return response.clipboards; }; const initClipboards = async () => { @@ -28,11 +30,21 @@ function createClipboardStore() { setClipboards(clipboards); }; + const resetClipboards = async () => { + setWhere(initialWhere); + setHasMore(true); + const clipboards = await getClipboards(); + setClipboards(clipboards); + }; + return { clipboards, setClipboards, where, setWhere, + hasMore, + setHasMore, + resetClipboards, resetWhere, getClipboards, clipboardRef, diff --git a/src/types/index.ts b/src/types/index.ts index 2057b719..581ae38b 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -84,6 +84,11 @@ export interface ClipboardWithRelations { rtf?: ClipboardRtfModel; files?: ClipboardFileModel[]; } +export interface ClipboardResponse { + clipboards: ClipboardWithRelations[]; + total: number; + has_more: boolean; +} export type Hotkey = { id: number; diff --git a/src/types/tauri-invoke.ts b/src/types/tauri-invoke.ts index 365ad37d..8aea9ff6 100644 --- a/src/types/tauri-invoke.ts +++ b/src/types/tauri-invoke.ts @@ -1,4 +1,4 @@ -import { ClipboardWhere, ClipboardWithRelations, DatabaseInfo, Hotkey, Settings } from "."; +import { ClipboardResponse, ClipboardWhere, DatabaseInfo, Hotkey, Settings } from "."; import { ClipboardType, WebWindow } from "./enums"; export enum InvokeCommand { @@ -36,7 +36,7 @@ export interface TauriInvokeCommands { // Clipboard commands [InvokeCommand.GetClipboards]: { args: ClipboardWhere; - return: ClipboardWithRelations[]; + return: ClipboardResponse; }; [InvokeCommand.DeleteClipboard]: { args: { id: number };