Skip to content

Commit

Permalink
add tooltip
Browse files Browse the repository at this point in the history
  • Loading branch information
0-don committed Dec 23, 2024
1 parent 52a4b4e commit 936c98d
Show file tree
Hide file tree
Showing 11 changed files with 191 additions and 83 deletions.
6 changes: 3 additions & 3 deletions src-tauri/src/commands/clipboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ pub async fn get_clipboards(
star: Option<bool>,
img: Option<bool>,
) -> Result<ClipboardsResponse, CommandError> {
let clipboards = get_clipboards_db(cursor, search.clone(), star, img)
let clipboards = get_clipboards_db(cursor, search, star, img)
.await
.expect("Error getting clipboards");

Expand Down Expand Up @@ -73,8 +73,8 @@ pub async fn delete_clipboard(id: i32) -> Result<(), CommandError> {
}

#[tauri::command]
pub async fn clear_clipboards() -> Result<(), CommandError> {
clear_clipboards_db().await?;
pub async fn clear_clipboards(r#type: Option<ClipboardType>) -> Result<(), CommandError> {
clear_clipboards_db(r#type).await?;
get_main_window()
.emit(ListenEvent::Init.to_string().as_str(), ())
.expect("Failed to emit");
Expand Down
6 changes: 6 additions & 0 deletions src-tauri/src/commands/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ pub async fn get_db_path() -> Result<String, CommandError> {
Ok(config.db)
}

#[tauri::command]
pub async fn get_config_path() -> Result<String, CommandError> {
let data_path = get_data_path();
Ok(data_path.config_file_path)
}

#[tauri::command]
pub async fn open_folder(location: FolderLocation) -> Result<(), CommandError> {
let data_path = get_data_path();
Expand Down
1 change: 1 addition & 0 deletions src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ pub fn run() {
window::get_app_version,
window::get_db_info,
window::get_db_path,
window::get_config_path,
window::open_folder,
])
.run(tauri::generate_context!())
Expand Down
83 changes: 78 additions & 5 deletions src-tauri/src/service/clipboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,13 +238,86 @@ pub async fn delete_clipboard_db(id: i32) -> Result<bool, DbErr> {
Ok(true)
}

pub async fn clear_clipboards_db() -> Result<(), DbErr> {
pub async fn clear_clipboards_db(r#type: Option<ClipboardType>) -> Result<(), DbErr> {
let db = connection::db().await?;

clipboard::Entity::delete_many()
.filter(clipboard::Column::Star.eq(false))
.exec(&db)
.await?;
match r#type {
None => {
// Keep existing behavior - delete all non-starred clipboards
clipboard::Entity::delete_many()
.filter(clipboard::Column::Star.eq(false))
.exec(&db)
.await?;
}
Some(clipboard_type) => {
// Find all non-starred clipboards that contain the specified type
let clipboards = clipboard::Entity::find()
.filter(
clipboard::Column::Star
.eq(false)
.and(clipboard::Column::Types.contains(clipboard_type.to_string())),
)
.all(&db)
.await?;

for clipboard in clipboards {
// Delete the type-specific data first
match clipboard_type {
ClipboardType::Text => {
clipboard_text::Entity::delete_many()
.filter(clipboard_text::Column::ClipboardId.eq(clipboard.id))
.exec(&db)
.await?;
}
ClipboardType::Image => {
clipboard_image::Entity::delete_many()
.filter(clipboard_image::Column::ClipboardId.eq(clipboard.id))
.exec(&db)
.await?;
}
ClipboardType::Html => {
clipboard_html::Entity::delete_many()
.filter(clipboard_html::Column::ClipboardId.eq(clipboard.id))
.exec(&db)
.await?;
}
ClipboardType::Rtf => {
clipboard_rtf::Entity::delete_many()
.filter(clipboard_rtf::Column::ClipboardId.eq(clipboard.id))
.exec(&db)
.await?;
}
ClipboardType::File => {
clipboard_file::Entity::delete_many()
.filter(clipboard_file::Column::ClipboardId.eq(clipboard.id))
.exec(&db)
.await?;
}
}

// Parse and update the types JSON array
if let Some(mut types) = ClipboardType::from_json_value(&clipboard.types) {
// Remove the specified type
types.retain(|t| t != &clipboard_type);

if types.is_empty() {
// If no types remain, delete the clipboard
clipboard::Entity::delete_by_id(clipboard.id)
.exec(&db)
.await?;
} else {
// Update the clipboard with the remaining types
let model = clipboard::ActiveModel {
id: Set(clipboard.id),
types: Set(ClipboardType::to_json_value(&types)),
..Default::default()
};
clipboard::Entity::update(model).exec(&db).await?;
}
}
}
}
}

Ok(())
}
Expand Down
4 changes: 2 additions & 2 deletions src-tauri/src/service/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use super::clipboard::get_last_clipboard_db;
use super::global::get_app;
use crate::connection;
use crate::prelude::*;
use crate::service::hotkey::with_hotkeys;
use crate::service::window::get_monitor_scale_factor;
use crate::{commands::settings::get_settings, service::hotkey::with_hotkeys};
use common::constants::CONFIG_NAME;
use common::constants::DB_NAME;
use common::language::get_system_language;
Expand Down Expand Up @@ -183,7 +183,7 @@ pub async fn sync_clipboard_history_disable() {
}

pub async fn sync_clipboard_history_toggle() {
let settings = get_settings().await.expect("Failed to get settings");
let settings = get_settings_db().await.expect("Failed to get settings");

printlog!("synchronize: {}", settings.synchronize);
with_hotkeys(false, async move {
Expand Down
5 changes: 2 additions & 3 deletions src-tauri/src/tauri_config/config.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::commands::settings::get_settings;
use crate::prelude::*;
use crate::service::global::get_app;
use crate::service::settings::get_data_path;
use crate::service::settings::{get_data_path, get_settings_db};
use common::types::enums::WebWindow;
use common::types::hotkey::SafeHotKeyManager;
use common::types::types::{Config, Key};
Expand Down Expand Up @@ -72,7 +71,7 @@ pub fn create_config() {
pub fn autostart() {
tauri::async_runtime::spawn(async {
let app: &tauri::AppHandle = get_app();
let settings = get_settings().await.expect("Failed to get settings");
let settings = get_settings_db().await.expect("Failed to get settings");
let manager: tauri::State<'_, AutoLaunchManager> = app.state::<AutoLaunchManager>();

// Use the manager as needed
Expand Down
13 changes: 6 additions & 7 deletions src/components/pages/app/clipboard/base-clipboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,12 @@ export const BaseClipboard: Component<BaseClipboardProps> = (props) => {
const { clipboard } = props.data;

const handleDelete = async (id: number) => {
if (await invokeCommand(InvokeCommand.DeleteClipboard, { id })) {
setClipboards((prev) => {
const updated = prev.filter((o) => o.clipboard.id !== id);
if (!updated.length) resetClipboards();
return updated;
});
}
await invokeCommand(InvokeCommand.DeleteClipboard, { id });
setClipboards((prev) => {
const updated = prev.filter((o) => o.clipboard.id !== id);
if (!updated.length) resetClipboards();
return updated;
});
};

const handleStar = async (clipboard: ClipboardModel) => {
Expand Down
82 changes: 49 additions & 33 deletions src/components/pages/settings/settings-backup.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { BsGlobeAmericas } from "solid-icons/bs";
import { FiUpload } from "solid-icons/fi";
import { AiTwotoneFolderOpen } from "solid-icons/ai";
import { BsGearWideConnected } from "solid-icons/bs";
import { RiDeviceSave3Fill } from "solid-icons/ri";
import { SiSqlite } from "solid-icons/si";
import { TbDatabaseStar } from "solid-icons/tb";
import { Component, Show, createEffect, createSignal, on } from "solid-js";
import { Component, createResource } from "solid-js";
import { SettingsStore } from "../../../store/settings-store";
import { FolderLocation } from "../../../types/enums";
import { InvokeCommand } from "../../../types/tauri-invoke";
Expand All @@ -13,14 +14,8 @@ import { Toggle } from "../../elements/toggle";
interface SettingsBackupProps {}

export const SettingsBackup: Component<SettingsBackupProps> = ({}) => {
const [url, setUrl] = createSignal<string>();

createEffect(
on(
() => SettingsStore.settings()?.synchronize,
() => setTimeout(async () => setUrl(await invokeCommand(InvokeCommand.GetDbPath)), 100)
)
);
const [databaseUrl, setDatabaseUrl] = createResource(() => invokeCommand(InvokeCommand.GetDbPath));
const [configUrl] = createResource(() => invokeCommand(InvokeCommand.GetConfigPath));

return (
<>
Expand All @@ -33,34 +28,55 @@ export const SettingsBackup: Component<SettingsBackupProps> = ({}) => {

<Toggle
checked={!!SettingsStore.settings()?.synchronize}
onChange={() => void SettingsStore.syncClipboard()}
onChange={async () => {
await SettingsStore.syncClipboard();
setDatabaseUrl.refetch();
}}
/>
</div>
</TextBlock>

<Show when={url()}>
<TextBlock Icon={BsGlobeAmericas} title="Database Location" className="animate-fade">
<div class="list-disc px-5 pb-5 pt-2.5">
<div class="relative w-full cursor-pointer">
<div
title={url()}
onClick={() => invokeCommand(InvokeCommand.OpenFolder, { location: FolderLocation.Database })}
class="w-full truncate rounded-md border border-gray-300 px-3 py-0.5 text-left text-sm italic focus:outline-none dark:border-dark-light dark:bg-dark-light dark:text-white dark:focus:bg-dark-dark"
>
{url()}
</div>
<button
type="button"
onClick={SettingsStore.syncClipboard}
class="group absolute inset-y-0 right-1 my-1 flex items-center space-x-1 rounded bg-gray-600 px-2 text-xs text-white group-hover:bg-gray-400"
>
<FiUpload class="dark:text-white" />
<div>Browse</div>
</button>
<TextBlock Icon={SiSqlite} title="Database Location">
<div class="list-disc px-5 pb-5 pt-2.5">
<div class="relative w-full cursor-pointer">
<div
title={databaseUrl()}
class="w-full truncate rounded-md border border-gray-300 px-3 py-0.5 text-left text-sm italic focus:outline-none dark:border-dark-light dark:bg-dark-light dark:text-white dark:focus:bg-dark-dark"
>
{databaseUrl()}
</div>
<button
type="button"
onClick={() => invokeCommand(InvokeCommand.OpenFolder, { location: FolderLocation.Database })}
class="group absolute inset-y-0 right-1 my-1 flex items-center space-x-1 rounded bg-gray-600 px-2 text-xs text-white group-hover:bg-gray-400"
>
<AiTwotoneFolderOpen class="dark:text-white" />
<div>Open</div>
</button>
</div>
</TextBlock>
</Show>
</div>
</TextBlock>

<TextBlock Icon={BsGearWideConnected} title="Config Location">
<div class="list-disc px-5 pb-5 pt-2.5">
<div class="relative w-full cursor-pointer">
<div
title={configUrl()}
class="w-full truncate rounded-md border border-gray-300 px-3 py-0.5 text-left text-sm italic focus:outline-none dark:border-dark-light dark:bg-dark-light dark:text-white dark:focus:bg-dark-dark"
>
{configUrl()}
</div>
<button
type="button"
onClick={() => invokeCommand(InvokeCommand.OpenFolder, { location: FolderLocation.Config })}
class="group absolute inset-y-0 right-1 my-1 flex items-center space-x-1 rounded bg-gray-600 px-2 text-xs text-white group-hover:bg-gray-400"
>
<AiTwotoneFolderOpen class="dark:text-white" />
<div>Open</div>
</button>
</div>
</div>
</TextBlock>
</>
);
};
61 changes: 35 additions & 26 deletions src/components/pages/settings/settings-history.tsx
Original file line number Diff line number Diff line change
@@ -1,45 +1,54 @@
import { BsDeviceHdd } from "solid-icons/bs";
import { FiTrash2 } from "solid-icons/fi";
import { Component, createSignal, onMount } from "solid-js";
import { DatabaseInfo } from "../../../types";
import { SiSqlite } from "solid-icons/si";
import { Component, createResource } from "solid-js";
import { ClipboardType } from "../../../types/enums";
import { InvokeCommand } from "../../../types/tauri-invoke";
import { formatBytes } from "../../../utils/helpers";
import { invokeCommand } from "../../../utils/tauri";
import { TextBlock } from "../../elements/text-block";

interface SettingsHistoryProps {}
const CLIPBOARD_TYPES: { type: ClipboardType | null; label: string }[] = [
{ type: null, label: "Clear All" },
{ type: ClipboardType.Text, label: "Clear Text" },
{ type: ClipboardType.Html, label: "Clear Html" },
{ type: ClipboardType.Rtf, label: "Clear Rtf" },
{ type: ClipboardType.Image, label: "Clear Image" },
{ type: ClipboardType.File, label: "Clear File" },
];

export const SettingsHistory: Component<SettingsHistoryProps> = ({}) => {
const [databaseInfo, setDatabaseInfo] = createSignal<DatabaseInfo>({
records: 0,
size: 0,
});
export const SettingsHistory: Component = () => {
const [databaseInfo, { refetch }] = createResource(() => invokeCommand(InvokeCommand.GetDbInfo));

onMount(async () => setDatabaseInfo(await invokeCommand(InvokeCommand.GetDbInfo)));
const handleClear = async (type: ClipboardType | null) => {
await invokeCommand(InvokeCommand.ClearClipboards, { type });
refetch();
};

return (
<>
<TextBlock Icon={BsDeviceHdd} title="Local Storage">
<TextBlock Icon={SiSqlite} title="SQL Database Info">
<ul class="mx-5 list-disc px-5 pb-5">
<li>{`${databaseInfo().records} local items (${formatBytes(
databaseInfo().size
)}) are saved on this computer`}</li>
<li>
{`${databaseInfo()?.records} local items (${formatBytes(databaseInfo()?.size)}) are saved on this computer`}
</li>
</ul>
</TextBlock>

<div class="flex w-full justify-end">
<button
type="button"
onClick={async () => {
await invokeCommand(InvokeCommand.ClearClipboards);
setDatabaseInfo(await invokeCommand(InvokeCommand.GetDbInfo));
}}
class="inline-flex items-center space-x-2 rounded bg-zinc-600 px-4 py-2 text-sm font-bold text-white hover:bg-zinc-700"
>
<FiTrash2 />
<span>Clear...</span>
</button>
</div>
<TextBlock Icon={BsDeviceHdd} title="Storage Actions">
<div class="flex w-full flex-wrap justify-center gap-2 px-5 pb-5">
{CLIPBOARD_TYPES.map(({ type, label }) => (
<button
type="button"
onClick={() => handleClear(type)}
class="inline-flex items-center space-x-2 rounded bg-zinc-600 px-1 py-1 text-xs font-bold text-white hover:bg-zinc-700"
>
<FiTrash2 />
<span>{label}</span>
</button>
))}
</div>
</TextBlock>
</>
);
};
Loading

0 comments on commit 936c98d

Please sign in to comment.