Skip to content

Commit cc59e93

Browse files
authored
Merge pull request #41 from taroj1205/feat/information
2 parents e665055 + de74d58 commit cc59e93

16 files changed

+237
-97
lines changed

.changeset/cuddly-pumpkins-pretend.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"clippr": minor
3+
---
4+
5+
Added information section and support multiple type display

.changeset/good-singers-invent.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"clippr": minor
3+
---
4+
5+
Added information section and added multiple type display

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
"license": "MIT",
1717
"dependencies": {
1818
"@tauri-apps/api": "^2",
19-
"@tauri-apps/plugin-fs": "~2",
19+
"@tauri-apps/plugin-fs": "~2.0.2",
2020
"@tauri-apps/plugin-global-shortcut": "^2.0.0",
2121
"@tauri-apps/plugin-shell": "^2",
2222
"@tauri-apps/plugin-sql": "~2",

pnpm-lock.yaml

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/sync-version.js

+10-5
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
import { readFileSync, writeFileSync } from 'fs';
22
import { join } from 'path';
3+
import toml from '@iarna/toml';
34

45
// Read package.json
56
const packageJson = JSON.parse(readFileSync('package.json', 'utf8'));
67
const version = packageJson.version;
78

8-
// Read tauri.conf.json
9+
// Update tauri.conf.json
910
const tauriConfigPath = join('src-tauri', 'tauri.conf.json');
1011
const tauriConfig = JSON.parse(readFileSync(tauriConfigPath, 'utf8'));
11-
12-
// Update version in tauri.conf.json
1312
tauriConfig.version = version;
14-
15-
// Write back to tauri.conf.json
1613
writeFileSync(tauriConfigPath, JSON.stringify(tauriConfig, null, 2) + '\n');
14+
15+
// Update Cargo.toml
16+
const cargoTomlPath = join('src-tauri', 'Cargo.toml');
17+
const cargoToml = toml.parse(readFileSync(cargoTomlPath, 'utf8'));
18+
cargoToml.package.version = version;
19+
writeFileSync(cargoTomlPath, toml.stringify(cargoToml));
20+
21+
console.log(`Updated version to ${version} in package.json, tauri.conf.json, and Cargo.toml`);

src-tauri/capabilities/default.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
"clipboard:read-all",
2929
"clipboard:write-all",
3030
"clipboard:allow-read-text",
31-
"fs:default"
31+
"fs:default",
32+
"fs:write-files",
33+
"fs:read-files"
3234
]
3335
}

src-tauri/src/api/db.rs

+10-14
Original file line numberDiff line numberDiff line change
@@ -49,34 +49,30 @@ pub async fn save_clipboard_to_db(
4949
let existing_id: Option<i64> = if type_ == "image" {
5050
// For images, check the image column
5151
if let Some(img) = &image {
52-
let mut stmt = conn.prepare("SELECT id FROM clipboard WHERE image = ?")
52+
let mut stmt = conn
53+
.prepare("SELECT id FROM clipboard WHERE image = ?")
5354
.map_err(|e| e.to_string())?;
54-
stmt.query_row(params![img], |row| row.get(0))
55-
.ok()
55+
stmt.query_row(params![img], |row| row.get(0)).ok()
5656
} else {
5757
None
5858
}
5959
} else {
6060
// For other types, check the content column
61-
let mut stmt = conn.prepare("SELECT id FROM clipboard WHERE content = ?")
61+
let mut stmt = conn
62+
.prepare("SELECT id FROM clipboard WHERE content = ?")
6263
.map_err(|e| e.to_string())?;
63-
stmt.query_row(params![content], |row| row.get(0))
64-
.ok()
64+
stmt.query_row(params![content], |row| row.get(0)).ok()
6565
};
6666

6767
println!("Existing ID: {:?}", existing_id);
6868

6969
if let Some(id) = existing_id {
7070
// Update existing entry
7171
conn.execute(
72-
"UPDATE clipboard SET count = count + 1, last_copied_date = ?, window_title = ?, window_exe = ? WHERE id = ?",
73-
params![
74-
date,
75-
window_title,
76-
window_exe,
77-
id
78-
],
79-
).map_err(|e| e.to_string())?;
72+
"UPDATE clipboard SET count = count + 1, last_copied_date = ? WHERE id = ?",
73+
params![date, id],
74+
)
75+
.map_err(|e| e.to_string())?;
8076
Ok(id)
8177
} else {
8278
// Insert new entry

src-tauri/src/api/window.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
use active_win_pos_rs::get_active_window;
12
use serde::Serialize;
23
use tauri::{LogicalPosition, WebviewWindow};
3-
use active_win_pos_rs::get_active_window;
44

55
#[tauri::command]
66
pub fn center_window_on_current_monitor(window: &WebviewWindow) {
@@ -30,9 +30,14 @@ pub struct WindowInfo {
3030
pub fn get_current_window() -> Option<WindowInfo> {
3131
get_active_window().ok().map(|window| WindowInfo {
3232
title: window.title,
33-
process_path: window.process_path.file_name().and_then(|n| n.to_str()).unwrap_or("").to_string(),
33+
process_path: window
34+
.process_path
35+
.file_name()
36+
.and_then(|n| n.to_str())
37+
.unwrap_or("")
38+
.to_string(),
3439
app_name: window.app_name,
3540
window_id: window.window_id,
36-
process_id: window.process_id
41+
process_id: window.process_id,
3742
})
38-
}
43+
}

src/App.tsx

+13-12
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { createSignal, For, onCleanup, onMount } from "solid-js";
22
import { emit, listen } from "@tauri-apps/api/event";
33
import { getCurrentWindow } from "@tauri-apps/api/window";
44
import {
5+
writeFiles,
56
writeHtml,
67
writeImageBase64,
78
writeText,
@@ -17,7 +18,6 @@ import { ClipboardItem } from "./components/clipboard-item";
1718

1819
export const App = ({ db_path }: { db_path: string }) => {
1920
const [activeIndex, setActiveIndex] = createSignal(0);
20-
const [isInitialLoading, setIsInitialLoading] = createSignal(true);
2121
const [isLoadingMore, setIsLoadingMore] = createSignal(false);
2222
const [clipboardHistory, setClipboardHistory] = createSignal<
2323
ClipboardHistory[]
@@ -73,9 +73,7 @@ export const App = ({ db_path }: { db_path: string }) => {
7373
block: "center",
7474
});
7575
// Only load more if we have at least 20 items in the current history
76-
if (
77-
activeIndex() >= totalLength - 5
78-
) {
76+
if (activeIndex() >= totalLength - 5) {
7977
setOffset((prev) => prev + limit);
8078
updateHistory(offset(), limit);
8179
}
@@ -86,7 +84,13 @@ export const App = ({ db_path }: { db_path: string }) => {
8684
behavior: "smooth",
8785
block: "center",
8886
});
89-
} else if (event.key === "Enter") {
87+
} else if (
88+
event.key === "Enter" ||
89+
event.key === "NumpadEnter" ||
90+
(event.ctrlKey &&
91+
event.key === "c" &&
92+
!window.getSelection()?.toString())
93+
) {
9094
const item = clipboardHistory()[activeIndex()];
9195
handleCopy(item);
9296
getCurrentWindow().hide();
@@ -100,7 +104,7 @@ export const App = ({ db_path }: { db_path: string }) => {
100104
} else {
101105
getCurrentWindow().hide();
102106
}
103-
} else {
107+
} else if (!event.ctrlKey) {
104108
inputRef?.focus();
105109
}
106110
} catch (error) {
@@ -130,7 +134,6 @@ export const App = ({ db_path }: { db_path: string }) => {
130134
}).then((history) => {
131135
if (offset === 0) {
132136
setClipboardHistory(history);
133-
setIsInitialLoading(false);
134137
} else {
135138
setClipboardHistory((prev) => [...prev, ...history]);
136139
setIsLoadingMore(false);
@@ -142,8 +145,8 @@ export const App = ({ db_path }: { db_path: string }) => {
142145
emit("copy-from-app");
143146
if (item.type === "image") {
144147
writeImageBase64(item.image);
145-
} else if (item.type === "html") {
146-
writeHtml(item.content);
148+
} else if (item.type === "files") {
149+
writeFiles(item.content.split(","));
147150
} else {
148151
writeText(item.content);
149152
}
@@ -196,8 +199,6 @@ export const App = ({ db_path }: { db_path: string }) => {
196199
limit: 20,
197200
});
198201

199-
console.log(newHistory);
200-
201202
// Compare with current history
202203
const currentHistory = clipboardHistory().slice(0, 20);
203204

@@ -274,7 +275,7 @@ export const App = ({ db_path }: { db_path: string }) => {
274275
class="h-full pb-2 overflow-y-auto invisible hover:visible max-h-[calc(100svh-4.5rem)] hover:overflow-y-auto select-none scroll-area"
275276
>
276277
<ul ref={listRef} class="visible w-full h-full">
277-
{ clipboardHistory().length === 0 ? (
278+
{clipboardHistory().length === 0 ? (
278279
<EmptyState searchQuery={inputRef?.value || ""} />
279280
) : (
280281
<>

src/components/clipboard-item.tsx

+47-6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { cn } from "../utils/tailwind";
44
import { DocumentIcon } from "../icons";
55
import { ImageIcon } from "../icons/image";
66
import { CodeIcon } from "../icons/code";
7+
import { FileIcon } from "../icons/file";
78
import { highlightText } from "../utils/highlight";
89

910
interface ClipboardItemProps {
@@ -13,16 +14,23 @@ interface ClipboardItemProps {
1314
searchQuery: string;
1415
onDoubleClick: () => void;
1516
onClick: () => void;
16-
// onContextMenu: (e: MouseEvent) => void;
1717
}
1818

1919
export const ClipboardItem: Component<ClipboardItemProps> = (props) => {
20+
const getFaviconUrl = (url: string) => {
21+
try {
22+
const parsedUrl = new URL(url);
23+
return `https://www.google.com/s2/favicons?domain=${parsedUrl.hostname}`;
24+
} catch {
25+
return null;
26+
}
27+
};
28+
2029
return (
2130
<button
2231
type="button"
2332
onDblClick={props.onDoubleClick}
2433
onClick={props.onClick}
25-
// onContextMenu={props.onContextMenu}
2634
class={cn(
2735
"cursor-pointer w-full grid grid-cols-[auto_1fr] gap-2 p-2 h-10 rounded truncate overflow-hidden place-items-center",
2836
{
@@ -32,7 +40,7 @@ export const ClipboardItem: Component<ClipboardItemProps> = (props) => {
3240
>
3341
{props.item.type === "image" ? (
3442
<>
35-
<ImageIcon class="size-4" />
43+
<ImageIcon class="size-4 text-gray-400" />
3644
<img
3745
src={`data:image/png;base64,${props.item.image}`}
3846
alt="clipboard content"
@@ -41,17 +49,50 @@ export const ClipboardItem: Component<ClipboardItemProps> = (props) => {
4149
</>
4250
) : props.item.type === "html" ? (
4351
<>
44-
<CodeIcon class="size-4" />
52+
<CodeIcon class="size-4 text-gray-400" />
4553
<p class="w-full overflow-hidden text-left text-ellipsis">
4654
{highlightText(
4755
props.item.content.trim().split("\n")[0],
4856
props.searchQuery
4957
)}
5058
</p>
5159
</>
52-
) : (
60+
) : props.item.type === "files" ? (
61+
<>
62+
<FileIcon class="size-4 text-gray-400" />
63+
<p class="w-full overflow-hidden text-left text-ellipsis">
64+
{highlightText(props.item.content.split(",")[0], props.searchQuery)}
65+
</p>
66+
</>
67+
) : props.item.type === "url" ? (
68+
<>
69+
<img
70+
src={getFaviconUrl(props.item.content) || ""}
71+
alt="favicon"
72+
class="size-4"
73+
onError={(e) => {
74+
e.currentTarget.src = "";
75+
e.currentTarget.alt = "🌐";
76+
}}
77+
/>
78+
<p class="w-full overflow-hidden text-left text-ellipsis">
79+
{highlightText(props.item.content, props.searchQuery)}
80+
</p>
81+
</>
82+
) : props.item.type === "color" ? (
83+
<>
84+
<div
85+
style={{ background: props.item.content }}
86+
class="size-4 rounded"
87+
/>
88+
<p class="w-full overflow-hidden text-left text-ellipsis">
89+
{highlightText(props.item.content, props.searchQuery)}
90+
</p>
91+
</>
92+
) :
93+
(
5394
<>
54-
<DocumentIcon class="size-4" />
95+
<DocumentIcon class="size-4 text-gray-400" />
5596
<p class="w-full overflow-hidden text-left text-ellipsis">
5697
{highlightText(
5798
props.item.content.trim().split("\n")[0],

0 commit comments

Comments
 (0)