Skip to content

feat(history): inline edit of transcriptions with edited indicator#4

Merged
ibrahimshadev merged 1 commit into
mainfrom
feat/history-inline-edit
Jun 19, 2026
Merged

feat(history): inline edit of transcriptions with edited indicator#4
ibrahimshadev merged 1 commit into
mainfrom
feat/history-inline-edit

Conversation

@ibrahimshadev

Copy link
Copy Markdown
Owner

Summary

Implements #3: edit a transcription directly on the History page, then copy the corrected text to paste elsewhere — useful when the paste destination isn't edit-friendly.

What's new

UI (HistoryPage.tsx)

  • Pencil action on each entry opens an inline, auto-growing textarea (Save / Cancel; ⌘/Ctrl+Enter to save, Esc to cancel).
  • Edited entries show an "edited" badge (tooltip = exact edit time).
  • The existing Copy button picks up the edited text. Edits patch in place — no reload or scroll jump.

Backend (transcription_history.rs, commands.rs, db.rs, main.rs)

  • New update_transcription_history_item(id, text) command stamps a new nullable edited_at_ms column.
  • The original recognizer output is preserved into original_text on the first edit (COALESCE), so "Show original" can always recover it; later edits don't overwrite it.
  • edited_at_ms is added to existing databases via an idempotent ALTER TABLE guarded by a column-existence check (the schema uses CREATE TABLE IF NOT EXISTS, which can't alter existing tables).

This all lives in the settings window (normal, non-transparent), so the WebView2 transparent-window reflow issues from the pill overlay don't apply to the inline textarea.

Verification

  • npx tsc --noEmit — clean
  • cargo check — clean
  • Rust unit tests — pass, including:
    • edit preserves the first original text and stamps edited_at_ms (not overwritten by re-edits)
    • empty-edit rejection leaves the row untouched
    • editing a missing id errors
    • ensure_history_columns adds the column to a legacy table and is idempotent

Closes #3

Let a mis-transcribed entry be corrected in place on the History page,
then copied and pasted elsewhere — useful when the paste destination is
not edit-friendly.

- Pencil action opens an auto-growing textarea (Save / Cancel, with
  Cmd/Ctrl+Enter to save and Esc to cancel); Copy then picks up the edit.
- New nullable `edited_at_ms` column doubles as the "was edited" flag and
  timestamp; an "edited" badge appears in the entry metadata.
- The original recognizer output is preserved into `original_text` on the
  first edit (COALESCE), so "Show original" can always recover it.
- `edited_at_ms` is added to pre-existing databases via an idempotent
  ALTER TABLE guarded by a column-existence check.
- Sync Cargo.lock dikt version to 1.26.0 (matches Cargo.toml).

Closes #3

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for manually editing transcription history items, updating the SQLite database schema with an edited_at_ms column, introducing a new Tauri command to handle updates, and implementing an inline editing UI in the SolidJS frontend. Feedback focuses on improving robustness: disabling keyboard shortcuts in the editing UI while a save is in progress, adding defensive checks to the textarea ref callback to prevent runtime errors in SolidJS, and using unwrap_or_default() when retrieving the system time to handle potential clock desynchronization issues.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +110 to +118
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === 'Escape') {
event.preventDefault();
cancelEdit();
} else if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {
event.preventDefault();
void saveEdit();
}
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The keyboard shortcuts for saving (Ctrl+Enter / ⌘+Enter) and cancelling (Escape) are not disabled while a save operation is in progress (saving() is true). This allows users to trigger multiple concurrent save requests or discard their edits mid-flight, potentially leading to race conditions or data loss if the save fails.

We should guard the keyboard event handler to ignore inputs while saving() is active.

Suggested change
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === 'Escape') {
event.preventDefault();
cancelEdit();
} else if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {
event.preventDefault();
void saveEdit();
}
};
const handleKeyDown = (event: KeyboardEvent) => {
if (saving()) return;
if (event.key === 'Escape') {
event.preventDefault();
cancelEdit();
} else if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {
event.preventDefault();
void saveEdit();
}
};

Comment on lines +154 to +164
ref={(el) => {
// Solid runs ref callbacks before the node is attached, so defer
// to a microtask: focus only works and scrollHeight is only
// measurable once the textarea is in the DOM.
queueMicrotask(() => {
autosize(el);
el.focus();
const end = el.value.length;
el.setSelectionRange(end, end);
});
}}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

In SolidJS, ref callbacks can occasionally be called with null or undefined during unmounting or reactive updates depending on the context. Additionally, if the component is unmounted or the element is disconnected from the DOM before the microtask runs, calling el.focus() or autosize(el) (which accesses scrollHeight) can cause layout issues or silent failures.

Adding a defensive check to ensure el is defined and connected to the DOM before executing the microtask prevents these potential runtime errors.

Suggested change
ref={(el) => {
// Solid runs ref callbacks before the node is attached, so defer
// to a microtask: focus only works and scrollHeight is only
// measurable once the textarea is in the DOM.
queueMicrotask(() => {
autosize(el);
el.focus();
const end = el.value.length;
el.setSelectionRange(end, end);
});
}}
ref={(el) => {
if (!el) return;
queueMicrotask(() => {
if (!el.isConnected) return;
autosize(el);
el.focus();
const end = el.value.length;
el.setSelectionRange(end, end);
});
}}

Comment on lines +194 to +197
let now_ms = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map_err(|e| e.to_string())?
.as_millis() as i64;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

If the system clock is misconfigured or set to a time before the UNIX epoch (e.g., during early system boot or due to clock desynchronization), SystemTime::now().duration_since(UNIX_EPOCH) will return an Err. This will cause the entire manual edit operation to fail, potentially causing the user to lose their edited text.

Using unwrap_or_default() provides a safe fallback of 0 (or epoch time) and ensures the edit can always be saved successfully regardless of system clock anomalies.

Suggested change
let now_ms = SystemTime::now()
.duration_since(UNIX_EPOCH)
.map_err(|e| e.to_string())?
.as_millis() as i64;
let now_ms = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap_or_default()
.as_millis() as i64;

@ibrahimshadev
ibrahimshadev merged commit 36032b2 into main Jun 19, 2026
2 checks passed
@ibrahimshadev
ibrahimshadev deleted the feat/history-inline-edit branch June 19, 2026 16:17
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 1.28.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request - Add an option to edit text in History Page.

1 participant