Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ Package this feature once with `pnpm tauri build --bundles app`, then open
`src-tauri/target/release/bundle/macos/Leaflet.app` or copy it into Applications.
An older installed version must be replaced once to gain the rebuild control.

Click **Rebuild app** at the bottom of the sidebar, or use **Cmd+K → Rebuild app**.
Use **Leaflet → Rebuild app…**, the hammer icon at the bottom of the sidebar,
or **Cmd+K → Rebuild app**.
Choose the Leaflet workspace with the native folder picker, then
click **Rebuild & restart**. The folder is remembered by the native app. Rebuilds
only use this selection; a webview cannot submit a different build path. The build uses the current
Expand Down
44 changes: 43 additions & 1 deletion src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ mod watch;

use serde::Serialize;
use std::{fs, path::PathBuf};
use tauri::Manager;
#[cfg(target_os = "macos")]
use tauri::menu::{Menu, MenuItem, PredefinedMenuItem};
use tauri::{Emitter, Manager};

#[derive(Serialize)]
struct Entry {
Expand Down Expand Up @@ -115,6 +117,46 @@ pub fn run() {
.manage(rebuild::RebuildState::default())
.plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_opener::init())
.setup(|app| {
#[cfg(target_os = "macos")]
{
let menu = Menu::default(app.handle())?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nit: The Leaflet submenu is found by comparing its text to app.package_info().name, and the item is inserted at a hard-coded index 2. If the name doesn't match, or the Tauri default menu layout changes, the Rebuild item silently disappears with no log. Consider logging when the submenu isn't found, or adding a comment explaining that index 2 sits just after About and the separator.

let mut added_rebuild_item = false;
for item in menu.items()? {
if let Some(submenu) = item.as_submenu() {
if submenu.text()? == app.package_info().name {
let rebuild = MenuItem::with_id(
app,
"rebuild",
"Rebuild app…",
true,
None::<&str>,
)?;
// The default Leaflet menu starts with About and a separator.
submenu.insert_items(
&[&rebuild, &PredefinedMenuItem::separator(app)?],
2,
)?;
added_rebuild_item = true;
break;
}
}
}
if !added_rebuild_item {
eprintln!("Could not add Rebuild app to the Leaflet menu: submenu not found");
}
app.set_menu(menu)?;
}
Ok(())
})
.on_menu_event(|app, event| {
if event.id().as_ref() == "rebuild" {
if let Some(window) = app.get_webview_window("main") {
let _ = window.set_focus();
let _ = window.emit("open-rebuild", ());
}
}
})
.invoke_handler(tauri::generate_handler![
load_archive,
watch::watch_archive,
Expand Down
23 changes: 17 additions & 6 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
X,
} from 'lucide-react';
import { getCurrentWindow } from '@tauri-apps/api/window';
import { listen } from '@tauri-apps/api/event';
import {
chooseArchive,
desktop,
Expand Down Expand Up @@ -149,6 +150,13 @@ export default function App() {
useEffect(() => {
void load(readPreference<string>('root', ''));
}, [load]);
useEffect(() => {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

should-fix: The new open-rebuild listener, which is the only path the native menu uses, has no automated test. The PR says it was checked by hand with the IPC harness. tests/fixtures/desktop.ts already imports emit from @tauri-apps/api/event, so a small case in tests/rebuild.spec.ts could emit open-rebuild and assert the dialog opens. That would stop this from regressing silently. The Rust side (menu insertion at index 2 and the event id match) is also untested, but that's harder to cover.

if (!desktop) return;
const unlisten = listen('open-rebuild', () => setRebuildOpen(true));
return () => {
void unlisten.then((stop) => stop());
};
}, []);
useEffect(() => {
if (!desktop || !rootKey || busy) return;
setSyncError(null);
Expand Down Expand Up @@ -433,12 +441,6 @@ export default function App() {
})}
</div>
<div className="sidebar-bottom">
{desktop && (
<button className="surprise" onClick={() => setRebuildOpen(true)}>
<Hammer size={16} />
Rebuild app
</button>
)}
<button
className="surprise"
onClick={randomEntry}
Expand Down Expand Up @@ -467,6 +469,15 @@ export default function App() {
: 'Auto-refresh · 1 min'
: 'Demo journal'}
</span>
{desktop && (
<button
title="Rebuild app"
aria-label="Rebuild app"
onClick={() => setRebuildOpen(true)}
>
<Hammer size={14} />
</button>
)}
<button
title="Refresh journal"
aria-label="Refresh journal"
Expand Down
3 changes: 3 additions & 0 deletions tests/fixtures/desktop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ const harness = {
get subscriptions() {
return subscriptions.size;
},
async openRebuildFromMenu() {
await emit('open-rebuild');
},
};
Object.assign(window, { journalTest: harness });
declare global {
Expand Down
10 changes: 10 additions & 0 deletions tests/rebuild.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@ test('rebuild remembers the workspace and stays busy across closing and reopenin
.toBe(2);
});

test('native rebuild menu event opens the rebuild dialog', async ({ page }) => {
await expect(
page.getByRole('button', { name: 'Rebuild app', exact: true }),
).toBeVisible();
await page.evaluate(() => window.journalTest.openRebuildFromMenu());
await expect(
page.getByRole('heading', { name: 'Rebuild app', exact: true }),
).toBeVisible();
});

test('command palette opens rebuild and unavailable runtimes cannot start it', async ({
page,
}) => {
Expand Down
Loading