diff --git a/Cargo.lock b/Cargo.lock index 50b59989..2ff600ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9042,6 +9042,7 @@ dependencies = [ "notify-rust", "objc2 0.6.4", "objc2-app-kit 0.3.2", + "objc2-foundation 0.3.2", "plist", "portable-pty", "reqwest_client", diff --git a/Cargo.toml b/Cargo.toml index bf654808..4cef75ce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -172,7 +172,10 @@ winresource = "0.1" # so the native traffic-light buttons render in the right light/dark style. [target.'cfg(target_os = "macos")'.dependencies] objc2 = "0.6" -objc2-app-kit = { version = "0.3", features = ["NSApplication", "NSResponder", "NSAppearance", "NSGraphics"] } +objc2-app-kit = { version = "0.3", features = ["NSApplication", "NSResponder", "NSAppearance", "NSGraphics", "NSImage"] } +# NSData feeds the runtime Dock icon for bare (non-bundled) binaries — see +# `set_dock_icon_for_bare_binary` in main.rs. +objc2-foundation = { version = "0.3", features = ["NSData"] } # x11/wayland are the Linux windowing backends; only pull them on Linux. The # Windows backend (`gpui_windows`) and macOS backend are selected by gpui_platform diff --git a/README.md b/README.md index 7352b5cd..15278946 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@
[![CI](https://github.com/l0ng-ai/tty7/actions/workflows/ci.yml/badge.svg)](https://github.com/l0ng-ai/tty7/actions/workflows/ci.yml) -[![Version](https://img.shields.io/github/v/tag/l0ng-ai/tty7?label=version&color=ff8a5c)](https://github.com/l0ng-ai/tty7/releases) +[![Version](https://img.shields.io/github/v/tag/l0ng-ai/tty7?label=version&color=3FDD8C)](https://github.com/l0ng-ai/tty7/releases) [![License](https://img.shields.io/badge/license-Apache--2.0-blue)](LICENSE) [![Discord](https://img.shields.io/badge/Discord-join%20chat-5865F2?logo=discord&logoColor=white)](https://discord.gg/s3dethqz2V) diff --git a/README.zh-CN.md b/README.zh-CN.md index 4ef795ea..91be1423 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -11,7 +11,7 @@
[![CI](https://github.com/l0ng-ai/tty7/actions/workflows/ci.yml/badge.svg)](https://github.com/l0ng-ai/tty7/actions/workflows/ci.yml) -[![Version](https://img.shields.io/github/v/tag/l0ng-ai/tty7?label=version&color=ff8a5c)](https://github.com/l0ng-ai/tty7/releases) +[![Version](https://img.shields.io/github/v/tag/l0ng-ai/tty7?label=version&color=3FDD8C)](https://github.com/l0ng-ai/tty7/releases) [![License](https://img.shields.io/badge/license-Apache--2.0-blue)](LICENSE) [![Discord](https://img.shields.io/badge/Discord-%E5%8A%A0%E5%85%A5%E7%BE%A4%E7%BB%84-5865F2?logo=discord&logoColor=white)](https://discord.gg/s3dethqz2V) diff --git a/assets/app-icon.png b/assets/app-icon.png index 322eb4c7..1dfc4225 100644 Binary files a/assets/app-icon.png and b/assets/app-icon.png differ diff --git a/assets/app-icon.svg b/assets/app-icon.svg index 4bccf439..2b53f763 100644 --- a/assets/app-icon.svg +++ b/assets/app-icon.svg @@ -1,6 +1,11 @@ - - - - - + + + + + + + + diff --git a/assets/favicon.ico b/assets/favicon.ico index 0e500f7a..f4cbfc6d 100644 Binary files a/assets/favicon.ico and b/assets/favicon.ico differ diff --git a/assets/logo.png b/assets/logo.png index 29ee58aa..3c68a106 100644 Binary files a/assets/logo.png and b/assets/logo.png differ diff --git a/assets/logo.svg b/assets/logo.svg index a3f1d077..0ec488f2 100644 --- a/assets/logo.svg +++ b/assets/logo.svg @@ -1,5 +1,6 @@ - - - - + + + + + diff --git a/assets/logo@256.png b/assets/logo@256.png index eb844b0d..9f262685 100644 Binary files a/assets/logo@256.png and b/assets/logo@256.png differ diff --git a/assets/social-preview.png b/assets/social-preview.png index 68636648..8a05db4e 100644 Binary files a/assets/social-preview.png and b/assets/social-preview.png differ diff --git a/assets/tray.svg b/assets/tray.svg index 42e060bc..8abede4e 100644 --- a/assets/tray.svg +++ b/assets/tray.svg @@ -1,5 +1,16 @@ - - - - + + + + + + + + + + + + diff --git a/assets/tty7.icns b/assets/tty7.icns index 5ddf6e7e..75988eb0 100644 Binary files a/assets/tty7.icns and b/assets/tty7.icns differ diff --git a/src/main.rs b/src/main.rs index 13a48a18..efb02d23 100644 --- a/src/main.rs +++ b/src/main.rs @@ -246,6 +246,39 @@ fn enrich_path_from_login_shell() { unsafe { std::env::set_var("PATH", merged) }; } +/// A bare (non-bundled) binary — `cargo dev` / `cargo run` — has no +/// `Info.plist` pointing the Dock at `tty7.icns`, so macOS shows the generic +/// executable icon. Feed the Dock the bundled logo at runtime in that case; +/// launches from the real `.app` keep the `.icns` and skip this. +#[cfg(target_os = "macos")] +fn set_dock_icon_for_bare_binary() { + use objc2::{AnyThread, MainThreadMarker}; + use objc2_app_kit::{NSApplication, NSImage}; + use objc2_foundation::NSData; + + let bundled = std::env::current_exe().is_ok_and(|p| { + p.components() + .any(|c| c.as_os_str().to_string_lossy().ends_with(".app")) + }); + if bundled { + return; + } + // gpui's `run` closure executes on the main thread; bail defensively + // rather than panic if that ever stops holding. + let Some(mtm) = MainThreadMarker::new() else { + return; + }; + static ICON_PNG: &[u8] = include_bytes!("../assets/app-icon.png"); + let data = NSData::with_bytes(ICON_PNG); + if let Some(image) = NSImage::initWithData(NSImage::alloc(), &data) { + // SAFETY: passing a valid NSImage on the main thread; AppKit copies the + // reference, no ownership transferred. + unsafe { + NSApplication::sharedApplication(mtm).setApplicationIconImage(Some(&image)); + } + } +} + fn main() { // Agent-hook mode: `tty7 agent-hook ` is the tiny emitter // Claude Code's hooks invoke (see `core::agent_hooks`). It reads the hook @@ -323,6 +356,8 @@ fn main() { gpui_component::init(cx); register_bundled_fonts(cx); cx.activate(true); + #[cfg(target_os = "macos")] + set_dock_icon_for_bare_binary(); // Load user config once and stash it as a global for views to read. cx.set_global(Config::load()); // Build the theme registry (built-ins + user theme files) before the