Skip to content
Open
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
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ See your usage at a glance from your menu bar. No digging through dashboards.

[**Download the latest release**](https://github.com/robinebers/openusage/releases/latest) (macOS, Apple Silicon & Intel)

The app auto-updates. Install once and you're set.
Released macOS builds auto-update. Install once and you're set.

Windows support is available from source. See [Windows setup](docs/windows-setup.md) for prerequisites and build instructions.

## What It Does

Expand Down Expand Up @@ -44,6 +46,11 @@ Community contributions welcome.

Want a provider that's not listed? [Open an issue.](https://github.com/robinebers/openusage/issues/new)

## Supported Platforms

- macOS (released builds)
- Windows (source builds)

## Open Source, Community Driven

OpenUsage is built by its users. Hundreds of people use it daily, and the project grows through community contributions: new providers, bug fixes, and ideas.
Expand Down
74 changes: 74 additions & 0 deletions docs/windows-setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Windows Setup

OpenUsage can be built and run on Windows with the standard Tauri 2 Windows toolchain.

## Prerequisites

- Windows 10 or Windows 11, 64-bit
- Rust and Cargo from [rustup.rs](https://rustup.rs/)
- Bun from [bun.sh](https://bun.sh/)
- Visual Studio Build Tools 2022 with the **Desktop development with C++** workload
- Microsoft Edge WebView2 Runtime
- LLVM, so `rquickjs-sys` can find `libclang.dll`
- Git

On a fresh machine, install the native dependencies first:

1. Install Visual Studio Build Tools 2022 from <https://visualstudio.microsoft.com/visual-cpp-build-tools/>.
2. Select **Desktop development with C++**.
3. Install LLVM from <https://github.com/llvm/llvm-project/releases> or with `winget install LLVM.LLVM`.
4. Install Rust with rustup and Bun with the Bun installer.
5. Confirm WebView2 is installed in Windows Apps settings, or install it from <https://developer.microsoft.com/en-us/microsoft-edge/webview2/>.

## Build Environment

Run Rust/Tauri commands from a Visual Studio developer environment, and expose LLVM's `libclang.dll`:

```powershell
$vswhere = "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe"
$vsinstall = & $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath
$devcmd = Join-Path $vsinstall "Common7\Tools\VsDevCmd.bat"
$cargoPath = "$env:USERPROFILE\.cargo\bin"
$llvmBin = "C:\Program Files\LLVM\bin"

cmd.exe /d /s /c "call `"$devcmd`" -arch=x64 -host_arch=x64 && set `"PATH=$cargoPath;$llvmBin;%PATH%`" && set `"LIBCLANG_PATH=$llvmBin`" && cargo check --manifest-path src-tauri/Cargo.toml"
```

## Development

```powershell
bun install
bun run bundle:plugins
bun run tauri dev
```

The Windows tray behavior differs from macOS:

- Left-click toggles the usage panel.
- Right-click opens the tray menu.
- The panel is positioned near the Windows taskbar and clamped to the current monitor.
- Application data is stored under the Windows app data directory managed by Tauri.

## Production Build

```powershell
bun run tauri build --no-sign
```

The Windows bundles are emitted under:

```text
src-tauri/target/release/bundle/
```

The project has updater signing enabled. Local unsigned installer builds should pass `--no-sign`, which produces MSI/NSIS bundles and skips updater signing. Maintainer release builds should omit `--no-sign` and provide `TAURI_SIGNING_PRIVATE_KEY` so updater artifacts are signed.

## Tested Windows Configuration

- Windows Pro, build 26200.8328, 64-bit
- Rust `1.95.0`
- Cargo `1.95.0`
- Bun `1.3.11`
- Git `2.52.0.windows.1`
- LLVM/clang `22.1.5`
- WebView2 Runtime `147.0.3912.98`
2 changes: 1 addition & 1 deletion src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ tauri = { version = "2", features = ["macos-private-api", "tray-icon", "image-pn
tauri-plugin-opener = "2"
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tauri-nspanel = { git = "https://github.com/ahkohd/tauri-nspanel", branch = "v2.1" }
time = { version = "0.3.47", features = ["formatting"] }
dirs = "6"
log = "0.4"
Expand All @@ -44,6 +43,7 @@ aes-gcm = "0.10.3"
sha2 = "0.10"

[target.'cfg(target_os = "macos")'.dependencies]
tauri-nspanel = { git = "https://github.com/ahkohd/tauri-nspanel", branch = "v2.1" }
objc2 = "0.6"
objc2-foundation = { version = "0.3", features = ["NSProcessInfo", "NSString"] }
objc2-app-kit = { version = "0.3", features = ["NSEvent", "NSScreen", "NSGraphics"] }
Expand Down
1 change: 1 addition & 0 deletions src-tauri/capabilities/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"core:window:allow-outer-size",
"core:window:allow-inner-size",
"core:window:allow-scale-factor",
"core:window:allow-start-dragging",
"opener:default",
"store:default",
"aptabase:allow-track-event",
Expand Down
42 changes: 30 additions & 12 deletions src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use std::sync::atomic::{AtomicUsize, Ordering};
use std::sync::{Arc, Mutex, OnceLock};

use serde::Serialize;
use tauri::Emitter;
use tauri::{Emitter, Manager};
use tauri_plugin_aptabase::EventTracker;
use tauri_plugin_log::{Target, TargetKind};
use uuid::Uuid;
Expand Down Expand Up @@ -138,6 +138,16 @@ pub struct AppState {
pub app_version: String,
}

#[cfg(target_os = "macos")]
fn add_platform_plugins<R: tauri::Runtime>(builder: tauri::Builder<R>) -> tauri::Builder<R> {
builder.plugin(tauri_nspanel::init())
}

#[cfg(not(target_os = "macos"))]
fn add_platform_plugins<R: tauri::Runtime>(builder: tauri::Builder<R>) -> tauri::Builder<R> {
builder
}

#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct PluginMeta {
Expand Down Expand Up @@ -195,10 +205,7 @@ fn init_panel(app_handle: tauri::AppHandle) {

#[tauri::command]
fn hide_panel(app_handle: tauri::AppHandle) {
use tauri_nspanel::ManagerExt;
if let Ok(panel) = app_handle.get_webview_panel("main") {
panel.hide();
}
panel::hide_panel(&app_handle);
}

#[tauri::command]
Expand Down Expand Up @@ -346,10 +353,20 @@ async fn start_probe_batch(

#[tauri::command]
fn get_log_path(app_handle: tauri::AppHandle) -> Result<String, String> {
// macOS log directory: ~/Library/Logs/{bundleIdentifier}
let home = dirs::home_dir().ok_or("no home dir")?;
let bundle_id = app_handle.config().identifier.clone();
let log_dir = home.join("Library").join("Logs").join(&bundle_id);
#[cfg(target_os = "macos")]
let log_dir = {
// macOS log directory: ~/Library/Logs/{bundleIdentifier}
let home = dirs::home_dir().ok_or("no home dir")?;
let bundle_id = app_handle.config().identifier.clone();
home.join("Library").join("Logs").join(&bundle_id)
};

#[cfg(not(target_os = "macos"))]
let log_dir = app_handle
.path()
.app_log_dir()
.map_err(|error| error.to_string())?;

let log_file = log_dir.join(format!("{}.log", app_handle.package_info().name));
Ok(log_file.to_string_lossy().to_string())
}
Expand Down Expand Up @@ -470,11 +487,12 @@ pub fn run() {
let runtime = tokio::runtime::Runtime::new().expect("Failed to create Tokio runtime");
let _guard = runtime.enter();

tauri::Builder::default()
let builder = tauri::Builder::default()
.plugin(tauri_plugin_aptabase::Builder::new("A-US-6435241436").build())
.plugin(tauri_plugin_opener::init())
.plugin(tauri_plugin_store::Builder::default().build())
.plugin(tauri_nspanel::init())
.plugin(tauri_plugin_store::Builder::default().build());

add_platform_plugins(builder)
.plugin(
tauri_plugin_log::Builder::new()
.targets([
Expand Down
Loading
Loading