Skip to content

Commit 31838df

Browse files
committed
feat: add clear history functionality and UI for clipboard management
1 parent 5df49ac commit 31838df

7 files changed

Lines changed: 85 additions & 15 deletions

File tree

src/main/database.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export class DatabaseManager {
1616
log.info("Opening database...");
1717
this.db = new Database(dbPath);
1818
log.info("Database opened successfully");
19-
19+
2020
log.info("Setting journal mode...");
2121
this.db.pragma("journal_mode = WAL");
2222
log.info("Journal mode set");
@@ -26,10 +26,14 @@ export class DatabaseManager {
2626
let loadablePath = sqliteVec.getLoadablePath();
2727

2828
// Fix path for Electron asar packaging
29-
if (loadablePath.includes('.asar')) {
29+
if (loadablePath.includes(".asar")) {
3030
loadablePath = loadablePath.replace(
31-
'app.asar' + (process.platform === 'win32' ? '\\' : '/') + 'node_modules',
32-
'app.asar.unpacked' + (process.platform === 'win32' ? '\\' : '/') + 'node_modules'
31+
"app.asar" +
32+
(process.platform === "win32" ? "\\" : "/") +
33+
"node_modules",
34+
"app.asar.unpacked" +
35+
(process.platform === "win32" ? "\\" : "/") +
36+
"node_modules"
3337
);
3438
}
3539

@@ -162,6 +166,11 @@ export class DatabaseManager {
162166
return stmt.all(`%${query}%`, limit) as ClipboardItem[];
163167
}
164168

169+
clearAllHistory(): void {
170+
this.db.exec("DELETE FROM clipboard_items");
171+
log.info("Clipboard history cleared");
172+
}
173+
165174
semanticSearch(
166175
queryEmbedding: number[],
167176
limit: number = 10

src/main/main.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,22 @@ ipcMain.handle("set-openai-api-key", (_event, apiKey: string) => {
303303
}
304304
});
305305

306+
ipcMain.handle("clear-history", () => {
307+
try {
308+
if (!databaseManager) {
309+
log.error("Database manager not initialized");
310+
return { success: false, error: "Database not initialized" };
311+
}
312+
databaseManager.clearAllHistory();
313+
clipboardManager?.clear();
314+
log.info("History cleared by user");
315+
return { success: true };
316+
} catch (error) {
317+
log.error("Failed to clear history:", error);
318+
return { success: false, error: String(error) };
319+
}
320+
});
321+
306322
function registerGlobalShortcut(shortcut: string = "CommandOrControl+Shift+V") {
307323
globalShortcut.unregisterAll();
308324

src/main/preload.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,5 @@ contextBridge.exposeInMainWorld("electronAPI", {
2222
ipcRenderer.invoke("set-global-shortcut", shortcut),
2323
setOpenAIApiKey: (apiKey: string) =>
2424
ipcRenderer.invoke("set-openai-api-key", apiKey),
25+
clearHistory: () => ipcRenderer.invoke("clear-history"),
2526
});

src/renderer/pages/ClipboardHistory.tsx

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -243,17 +243,9 @@ export default function ClipboardHistory({}: ClipboardHistoryProps) {
243243
</button>
244244
)}
245245
</div>
246-
{hasApiKey ? (
247-
<p className="search-hint">
248-
Press Enter to search • ↑↓ Navigate • Enter/C to copy • / to
249-
search
250-
</p>
251-
) : (
252-
<p className="search-warning">
253-
OpenAI API key required. Configure in Settings to enable semantic
254-
search.
255-
</p>
256-
)}
246+
<p className="search-hint">
247+
{hasApiKey && "Press Enter to search • "}↑↓ Navigate • Enter/C to copy{hasApiKey && " • / to search"}
248+
</p>
257249
</div>
258250
<main className="content">
259251
{history.length === 0 ? (

src/renderer/pages/Settings.css

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,30 @@ body.opaque .settings {
468468
background: rgba(255, 255, 255, 0.08);
469469
}
470470

471+
/* Danger Button */
472+
.btn-danger {
473+
background: rgba(239, 68, 68, 0.2);
474+
border: 1px solid rgba(239, 68, 68, 0.3);
475+
color: #ef4444;
476+
padding: 0.625rem 1rem;
477+
border-radius: 8px;
478+
font-size: 0.8125rem;
479+
font-weight: 500;
480+
cursor: pointer;
481+
transition: all 0.2s ease;
482+
}
483+
484+
.btn-danger:hover {
485+
background: rgba(239, 68, 68, 0.3);
486+
border-color: rgba(239, 68, 68, 0.5);
487+
transform: translateY(-1px);
488+
}
489+
490+
.btn-danger:active {
491+
transform: translateY(0);
492+
background: rgba(239, 68, 68, 0.4);
493+
}
494+
471495
/* Shortcut Keys (for display) */
472496
.shortcut-keys {
473497
display: flex;

src/renderer/pages/Settings.tsx

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,33 @@ export default function Settings({
296296
</div>
297297
</div>
298298
</div>
299+
300+
<div className="setting-group">
301+
<h2>Data</h2>
302+
<div className="setting-item">
303+
<div className="setting-info">
304+
<label>Clear History</label>
305+
<p>Delete all clipboard history permanently</p>
306+
</div>
307+
<div className="shortcut-control">
308+
<button
309+
className="btn-danger"
310+
onClick={async () => {
311+
if (window.confirm("Are you sure you want to delete all clipboard history? This action cannot be undone.")) {
312+
const result = await window.electronAPI.clearHistory();
313+
if (result.success) {
314+
alert("History cleared successfully!");
315+
} else {
316+
alert("Failed to clear history: " + result.error);
317+
}
318+
}
319+
}}
320+
>
321+
Clear All History
322+
</button>
323+
</div>
324+
</div>
325+
</div>
299326
</main>
300327
</div>
301328
</>

src/renderer/types.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export interface ElectronAPI {
1717
getConfig: () => Promise<AppConfig>;
1818
setGlobalShortcut: (shortcut: string) => Promise<{ success: boolean; error?: string }>;
1919
setOpenAIApiKey: (apiKey: string) => Promise<{ success: boolean; error?: string }>;
20+
clearHistory: () => Promise<{ success: boolean; error?: string }>;
2021
}
2122

2223
declare global {

0 commit comments

Comments
 (0)