Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
284d016
feat(native): replace kibo UI diffs with monaco diff editor showing f…
CasLinden Apr 30, 2026
6550a4d
Merge develop into cas/monaco-diffs to resolve conflicts
czxtm May 4, 2026
fc0d8b4
chore(native): merge develop into branch
CasLinden May 5, 2026
8e59a0c
fix(widget) improve highlighting for monaco diff editors, add a nixma…
CasLinden May 5, 2026
099a0ef
chore(widget): remove problematic error handling hook
CasLinden May 5, 2026
58017d6
chore: merge error hook removal into this branch
CasLinden May 5, 2026
f41f741
chore(widget): update editor stories, add mocks and improve testability
CasLinden May 5, 2026
4409723
chore(widget): remove unused util and add monaco dep in native
CasLinden May 5, 2026
01814f5
chore: merge develop into monaco-diffs
CasLinden May 8, 2026
1dbbea8
chore(monaco-editors): rename components to avoid confusion
CasLinden May 8, 2026
54bd08d
fix(monaco-editor): eagerly initiate nix grammar and add file specici…
CasLinden May 8, 2026
13cf534
chore(diff-editors): prefetch diff data, smoothen UX
CasLinden May 8, 2026
32c2c2c
chore: remove kibo folder after dev merge
CasLinden May 8, 2026
886e3d6
chore(storybook): stub monaco and update snapshots
CasLinden May 8, 2026
8a59905
chore(storybook): separate stories for monaco editor wrappers
CasLinden May 8, 2026
a651a22
Merge branch 'develop' into cas/monaco-diffs
CasLinden May 12, 2026
00bea3d
chore(types): commit auto generated search package added by scott on …
CasLinden May 15, 2026
ea824bb
fix(diffs): read diff file content from repo root
CasLinden May 15, 2026
0670c13
fix(diffs): refetch file diff content when changed files change with …
CasLinden May 15, 2026
6e769c4
feat(diffs): prefer the diff tab, if it please
CasLinden May 15, 2026
82af891
Merge branch 'develop' into cas/monaco-diffs
CasLinden May 15, 2026
ed81e1a
Merge branch 'develop' into cas/monaco-diffs
CasLinden May 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions apps/native/.storybook/mocks/tauri-runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,14 @@ export const storybookDarwinAPI = {
cached: async () => baseGitStatus(),
commit: async () => ({ hash: "mock123", evolveState: baseEvolveState() }),
stash: async () => okResult(),
fileDiffContents: async (_filenames: string[]) => ({}),
stageAll: async () => undefined,
unstageAll: async () => undefined,
restoreAll: async () => undefined,
checkoutNewBranch: async (branchName: string) => ({ ok: true, branch: branchName }),
checkoutBranch: async () => undefined,
checkoutMainBranch: async () => undefined,
mergeBranch: async () => undefined,
},
darwin: {
evolve: async () => ({
Expand Down
14 changes: 13 additions & 1 deletion apps/native/.storybook/vitest.setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,19 @@ function normalizeSnapshotRoot(root: Element): string {
editor.appendChild(placeholder);
}

return normalizeAnimations(clone.innerHTML);
for (const editor of clone.querySelectorAll(".monaco-diff-editor, .monaco-editor")) {
editor.replaceChildren();
const placeholder = document.createElement("div");
placeholder.setAttribute("data-slot", "monaco-editor-placeholder");
editor.appendChild(placeholder);
}

let html = normalizeAnimations(clone.innerHTML);
// Monaco assigns auto-incrementing model IDs that vary by test-suite order.
html = html.replace(/inmemory:\/\/model\/\d+/g, "inmemory://model/N");
// data-keybinding-context values are similarly auto-incremented.
html = html.replace(/data-keybinding-context="\d+"/g, 'data-keybinding-context="N"');
return html;
}

// Automatically snapshot every story after it renders
Expand Down
2 changes: 2 additions & 0 deletions apps/native/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,12 @@
"cmdk": "^1.1.1",
"execa": "^9.6.0",
"lucide-react": "^1.14.0",
"@monaco-editor/react": "^4.7.0",
"monaco-editor": "^0.55.1",
"monaco-editor-textmate": "^4.0.0",
"monaco-textmate": "^3.0.1",
"motion": "^12.35.2",
"onigasm": "^2.2.5",
"react": "^19.2.3",
"react-dom": "^19.1.0",
"react-icons": "^5.5.0",
Expand Down
1 change: 1 addition & 0 deletions apps/native/src-tauri/examples/specta_gen_ts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ fn main() {
.register::<shared_types::RollbackResult>()
.register::<shared_types::SetDirResult>()
.register::<shared_types::UiPrefs>()
.register::<shared_types::FileDiffContents>()
.register::<shared_types::UiPrefsUpdate>()
.register::<shared_types::OkResult>()
.register::<shared_types::NixCheckResult>()
Expand Down
25 changes: 25 additions & 0 deletions apps/native/src-tauri/src/commands/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,31 @@ use crate::storage::store;
use crate::{db, git, shared_types};
use tauri::AppHandle;

/// Initializes a git repository in the config directory if one doesn't exist.
#[tauri::command]
pub async fn git_init_repo(app: AppHandle) -> Result<shared_types::OkResult, String> {
let dir = store::ensure_config_dir_exists(&app).map_err(|e| capture_err("git_init_repo", e))?;
git::init_repo(&dir).map_err(|e| capture_err("git_init_repo", e))?;
Ok(shared_types::OkResult::yes())
}

/// Returns original (HEAD) and modified (working-tree) content for each requested file.
#[tauri::command]
pub async fn git_file_diff_contents(
app: AppHandle,
filenames: Vec<String>,
) -> Result<std::collections::HashMap<String, shared_types::FileDiffContents>, String> {
let dir =
store::get_config_dir(&app).map_err(|e| capture_err("git_file_diff_contents", e))?;
Ok(filenames
.into_iter()
.map(|f| {
let (original, modified) = git::exec::file_diff_contents(&dir, &f);
(f, shared_types::FileDiffContents { original, modified })
})
.collect())
}

/// Returns the current git status of the config directory.
#[tauri::command]
pub async fn git_status(app: AppHandle) -> Result<shared_types::GitStatus, String> {
Expand Down
9 changes: 9 additions & 0 deletions apps/native/src-tauri/src/commands/ui_prefs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ pub async fn ui_get_prefs(app: AppHandle) -> Result<shared_types::UiPrefs, Strin
"ui_get_prefs",
store::get_bool_pref(&app, store::SCAN_HOMEBREW_ON_STARTUP_KEY, true),
)?;
let default_to_diff_tab = wrap_result_and_capture_err(
"ui_get_prefs",
store::get_bool_pref(&app, store::DEFAULT_TO_DIFF_TAB_KEY, false),
)?;
let developer_mode = wrap_result_and_capture_err(
"ui_get_prefs",
store::get_bool_pref(&app, store::DEVELOPER_MODE_KEY, false),
Expand Down Expand Up @@ -88,6 +92,7 @@ pub async fn ui_get_prefs(app: AppHandle) -> Result<shared_types::UiPrefs, Strin
confirm_rollback,
auto_summarize_on_focus,
scan_homebrew_on_startup,
default_to_diff_tab,
developer_mode,
pinned_version,
})
Expand Down Expand Up @@ -173,6 +178,10 @@ pub async fn ui_set_prefs(
)
.map_err(|e| capture_err("ui_set_prefs", e))?;
}
if let Some(default_to_diff_tab) = prefs.default_to_diff_tab {
store::set_bool_pref(&app, store::DEFAULT_TO_DIFF_TAB_KEY, default_to_diff_tab)
.map_err(|e| capture_err("ui_set_prefs", e))?;
}
if let Some(developer_mode) = prefs.developer_mode {
store::set_bool_pref(&app, store::DEVELOPER_MODE_KEY, developer_mode)
.map_err(|e| capture_err("ui_set_prefs", e))?;
Expand Down
3 changes: 3 additions & 0 deletions apps/native/src-tauri/src/editor/lsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ pub async fn start(app: &AppHandle) -> Result<(), String> {
}
}
}
// Clear state for next open
*lsp_state().lock().await = None;
let _ = app_handle.emit("lsp:exit", ());
});

// Spawn stderr reader — log for debugging.
Expand Down
23 changes: 23 additions & 0 deletions apps/native/src-tauri/src/git/exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,29 @@ pub fn get_nix_diff(dir: &str) -> Result<String> {
Ok(diff)
}

pub fn repo_root(dir: &str) -> String {
git_command()
.args(["rev-parse", "--show-toplevel"])
.current_dir(dir)
.output()
.map(|o| String::from_utf8_lossy(&o.stdout).trim().to_string())
.unwrap_or_else(|_| dir.to_string())
}

/// Returns (original, modified) file content for a single file: HEAD content and working-tree content.
/// Returns empty strings for new files (no HEAD) or deleted files (not on disk).
pub fn file_diff_contents(dir: &str, filename: &str) -> (String, String) {
let original = git_command()
.args(["show", &format!("HEAD:{filename}")])
.current_dir(dir)
.output()
.map(|o| String::from_utf8_lossy(&o.stdout).into_owned())
.unwrap_or_default();
let modified = std::fs::read_to_string(std::path::Path::new(&repo_root(dir)).join(filename))
.unwrap_or_default();
(original, modified)
}

/// Returns a diff of tracked changes, optionally restricted to a path glob.
/// Falls back to staged+unstaged when HEAD is unborn (fresh repo with no commits).
fn get_tracked_diff(dir: &str, path_filter: Option<&str>) -> Result<String> {
Expand Down
2 changes: 2 additions & 0 deletions apps/native/src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -490,11 +490,13 @@ fn run_gui_mode(
commands::homebrew::homebrew_apply_diff,
commands::homebrew::homebrew_get_state_diff,
// Git
commands::git::git_init_repo,
commands::git::git_status,
commands::git::git_status_and_cache,
commands::git::git_cached,
commands::git::git_commit,
commands::git::git_stash,
commands::git::git_file_diff_contents,
// Darwin/Nix
commands::evolve::darwin_evolve,
commands::evolve::darwin_evolve_cancel,
Expand Down
8 changes: 8 additions & 0 deletions apps/native/src-tauri/src/shared_types/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ use specta::Type;
use super::evolve::EvolveState;
use crate::sqlite_types::{Change, ChangeSet, ChangeSummary};

/// HEAD content vs working-tree content for a file, used by the diff tab Monaco DiffEditor.
#[derive(Debug, Clone, Serialize, Deserialize, Type)]
#[serde(rename_all = "camelCase")]
pub struct FileDiffContents {
pub original: String,
pub modified: String,
}

/// Type of change for a file in git status.
#[derive(Debug, Clone, Copy, Serialize, Deserialize, Type)]
#[serde(rename_all = "camelCase")]
Expand Down
4 changes: 4 additions & 0 deletions apps/native/src-tauri/src/shared_types/prefs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ pub struct UiPrefs {
pub auto_summarize_on_focus: bool,
/// Whether Homebrew state should be scanned on app startup.
pub scan_homebrew_on_startup: bool,
/// Whether the change view defaults to the Diff tab instead of Summary.
pub default_to_diff_tab: bool,
/// Whether developer-only UI/actions are enabled.
pub developer_mode: bool,
/// Version pinned by the user, when update pinning is active.
Expand Down Expand Up @@ -84,6 +86,8 @@ pub struct UiPrefsUpdate {
pub auto_summarize_on_focus: Option<bool>,
/// Startup Homebrew scan preference update.
pub scan_homebrew_on_startup: Option<bool>,
/// Default-to-diff-tab preference update.
pub default_to_diff_tab: Option<bool>,
/// Developer mode preference update.
pub developer_mode: Option<bool>,
/// `None` -> field not sent; `Some(None)` -> clear the pinned version.
Expand Down
3 changes: 3 additions & 0 deletions apps/native/src-tauri/src/storage/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ pub const AUTO_SUMMARIZE_ON_FOCUS_KEY: &str = "autoSummarizeOnFocus";
// Startup scan preference keys
pub const SCAN_HOMEBREW_ON_STARTUP_KEY: &str = "scanHomebrewOnStartup";

// Default-tab preference keys
pub const DEFAULT_TO_DIFF_TAB_KEY: &str = "defaultToDiffTab";

// Developer-mode preference keys
pub const DEVELOPER_MODE_KEY: &str = "developerMode";
pub const PINNED_VERSION_KEY: &str = "pinnedVersion";
Expand Down
4 changes: 2 additions & 2 deletions apps/native/src-tauri/src/summarize/sumlog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
pub const FIND_EXISTING: bool = false;
pub const GROUP_EXISTING: bool = false;
pub const SIMPLIFY_GROUP: bool = false;
pub const FRESH_CHANGESET: bool = false;
pub const EVOLVED_CHANGESET: bool = false;
pub const FRESH_CHANGESET: bool = true;
pub const EVOLVED_CHANGESET: bool = true;
pub const QUEUE_SUMMARIZER: bool = false;

// ── Imports ───────────────────────────────────────────────────────────────────
Expand Down

This file was deleted.

This file was deleted.

Loading
Loading