mirror of
https://github.com/tiennm99/claude-code-usage-bubble.git
synced 2026-10-25 16:16:20 +00:00
build: scaffold the Tauri v2 crate
Turn the package into a lib plus thin bin on Tauri v2 with a root-level tauri.conf.json, capabilities, generated icons (keeping the hand-tuned icon.ico) and a placeholder bubble page. The Win32 modules leave the module tree until each one is ported; their sources stay on disk. tauri-build now embeds the icon, a VERSIONINFO from the Cargo version and a PerMonitorV2 manifest, replacing res/icon.rc and its stale 0.1.0.
This commit is contained in:
1 parent
bb09765be5
commit
f64d81e6a1
18 files changed
+4656
-415
No files matched your search
+71
@@ -0,0 +1,71 @@
|
||||
//! Claude Code Usage Bubble on Tauri v2.
|
||||
//!
|
||||
//! The binary in `src/main.rs` only calls [`run`]. Every module is `pub` so
|
||||
//! that items wired up incrementally do not trip `dead_code`.
|
||||
|
||||
pub mod diag;
|
||||
|
||||
use tauri::{RunEvent, WebviewUrl, WebviewWindowBuilder, WindowEvent};
|
||||
|
||||
/// Label of the scaffold window that proves the webview pipeline works.
|
||||
const TEST_WINDOW_LABEL: &str = "bubble-test";
|
||||
|
||||
/// Starts the application and blocks until it exits.
|
||||
pub fn run() {
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
let diagnose_enabled = args.iter().any(|a| a == "--diagnose");
|
||||
match diag::init(diagnose_enabled) {
|
||||
Ok(Some(path)) => log::info!("startup args={args:?} log_path={}", path.display()),
|
||||
Ok(None) => {}
|
||||
Err(err) => eprintln!("diagnostic log could not be opened: {err}"),
|
||||
}
|
||||
|
||||
let app = tauri::Builder::default()
|
||||
.setup(|app| {
|
||||
let window = WebviewWindowBuilder::new(
|
||||
app,
|
||||
TEST_WINDOW_LABEL,
|
||||
WebviewUrl::App("bubble.html".into()),
|
||||
)
|
||||
.title("Claude Code Usage Bubble")
|
||||
.inner_size(220.0, 66.0)
|
||||
.transparent(true)
|
||||
.decorations(false)
|
||||
.always_on_top(true)
|
||||
.skip_taskbar(true)
|
||||
.resizable(false)
|
||||
.build()?;
|
||||
|
||||
// The process otherwise outlives its windows (see the exit
|
||||
// handler below), so closing the only window must exit
|
||||
// explicitly.
|
||||
let handle = app.handle().clone();
|
||||
window.on_window_event(move |event| {
|
||||
if let WindowEvent::CloseRequested { .. } = event {
|
||||
handle.exit(0);
|
||||
}
|
||||
});
|
||||
Ok(())
|
||||
})
|
||||
.build(tauri::generate_context!());
|
||||
|
||||
let app = match app {
|
||||
Ok(app) => app,
|
||||
Err(err) => {
|
||||
log::error!("tauri builder failed: {err}");
|
||||
eprintln!("Claude Code Usage Bubble failed to start: {err}");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
app.run(|_app, event| {
|
||||
// Destroying the last window must not end the process; only an
|
||||
// explicit `exit` (which carries an exit code) does.
|
||||
if let RunEvent::ExitRequested {
|
||||
code: None, api, ..
|
||||
} = event
|
||||
{
|
||||
api.prevent_exit();
|
||||
}
|
||||
});
|
||||
}
|
||||
+4
-67
@@ -1,70 +1,7 @@
|
||||
#![windows_subsystem = "windows"]
|
||||
// Several modules (creds, usage, update, os::dpi, …) expose API that the
|
||||
// app surface doesn't fully call yet — they're scaffolding for in-progress
|
||||
// port phases. Allow at the crate root rather than scattering attributes.
|
||||
#![allow(dead_code)]
|
||||
|
||||
// Original infrastructure.
|
||||
mod creds;
|
||||
mod diag;
|
||||
mod i18n;
|
||||
mod net;
|
||||
mod os;
|
||||
mod tray;
|
||||
mod update;
|
||||
mod usage;
|
||||
mod usage_color;
|
||||
|
||||
// Application surface.
|
||||
mod app;
|
||||
mod bubble;
|
||||
mod panel;
|
||||
mod settings;
|
||||
// Release builds use the GUI subsystem so no console window opens with the
|
||||
// app. Debug builds keep the console for log output.
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
let diagnose_enabled = args.iter().any(|a| a == "--diagnose");
|
||||
if diagnose_enabled {
|
||||
if let Ok(Some(path)) = diag::init(true) {
|
||||
log::info!("startup args={args:?} log_path={}", path.display());
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(exit_code) = update::run_cli(&args) {
|
||||
if diagnose_enabled {
|
||||
log::info!("cli mode exited with code {exit_code}");
|
||||
}
|
||||
std::process::exit(exit_code);
|
||||
}
|
||||
|
||||
let wait_pid = args
|
||||
.iter()
|
||||
.position(|a| a == "--wait-pid")
|
||||
.and_then(|i| args.get(i + 1))
|
||||
.and_then(|s| s.parse::<u32>().ok());
|
||||
if let Some(pid) = wait_pid {
|
||||
if diagnose_enabled {
|
||||
log::info!("waiting up to 5s for parent pid {pid} to exit");
|
||||
}
|
||||
update::handoff::wait_for_parent_exit(pid, 5_000);
|
||||
}
|
||||
|
||||
let updated_to = args
|
||||
.iter()
|
||||
.position(|a| a == "--updated-to")
|
||||
.and_then(|i| args.get(i + 1))
|
||||
.cloned();
|
||||
|
||||
if diagnose_enabled {
|
||||
log::info!("entering app::run (wait_pid={wait_pid:?} updated_to={updated_to:?})");
|
||||
}
|
||||
app::run(AppArgs {
|
||||
wait_pid_present: wait_pid.is_some(),
|
||||
updated_to,
|
||||
});
|
||||
}
|
||||
|
||||
pub struct AppArgs {
|
||||
pub wait_pid_present: bool,
|
||||
pub updated_to: Option<String>,
|
||||
claude_code_usage_bubble_lib::run();
|
||||
}
|
||||
Reference in new issue
Block a user