Tauri: Small style compatibility fixes (#6270)
This commit is contained in:
parent
6e3bbb7f12
commit
ad5bba3e6e
@ -1245,8 +1245,8 @@
|
|||||||
"AtDateAgo" = "on {date}";
|
"AtDateAgo" = "on {date}";
|
||||||
"AudioPause" = "Pause audio";
|
"AudioPause" = "Pause audio";
|
||||||
"AudioPlay" = "Play audio";
|
"AudioPlay" = "Play audio";
|
||||||
"ToggleUserNotifications" = "Toggle user notifications";
|
"AriaToggleUserNotifications" = "Toggle user notifications";
|
||||||
"ToggleChatNotifications" = "Toggle chat notifications";
|
"AriaToggleChatNotifications" = "Toggle chat notifications";
|
||||||
"ChannelInaccessible" = "channel is inaccessible";
|
"ChannelInaccessible" = "channel is inaccessible";
|
||||||
"GroupInaccessible" = "group is inaccessible";
|
"GroupInaccessible" = "group is inaccessible";
|
||||||
"AriaPasswordToggle" = "Toggle password visibility";
|
"AriaPasswordToggle" = "Toggle password visibility";
|
||||||
|
|||||||
@ -423,11 +423,11 @@ const ChatExtra: FC<OwnProps & StateProps> = ({
|
|||||||
</ListItem>
|
</ListItem>
|
||||||
)}
|
)}
|
||||||
{!isInSettings && (
|
{!isInSettings && (
|
||||||
<ListItem icon={isMuted ? 'unmute' : 'mute'} narrow ripple onClick={handleToggleNotifications}>
|
<ListItem icon={isMuted ? 'mute' : 'unmute'} narrow ripple onClick={handleToggleNotifications}>
|
||||||
<span>{oldLang('Notifications')}</span>
|
<span>{lang('Notifications')}</span>
|
||||||
<Switcher
|
<Switcher
|
||||||
id="group-notifications"
|
id="group-notifications"
|
||||||
label={userId ? 'Toggle User Notifications' : 'Toggle Chat Notifications'}
|
label={lang(userId ? 'AriaToggleUserNotifications' : 'AriaToggleChatNotifications')}
|
||||||
checked={!isMuted}
|
checked={!isMuted}
|
||||||
inactive
|
inactive
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -47,7 +47,7 @@
|
|||||||
|
|
||||||
body.is-tauri.is-macos #Main:not(.is-fullscreen) &:not(#TopicListHeader) {
|
body.is-tauri.is-macos #Main:not(.is-fullscreen) &:not(#TopicListHeader) {
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
padding: 0.5rem 0.5rem 0.5rem 4.5rem;
|
padding: 0.5rem 0.5rem 0.5rem var(--window-controls-width);
|
||||||
|
|
||||||
.SearchInput {
|
.SearchInput {
|
||||||
max-width: calc(100% - 2.75rem);
|
max-width: calc(100% - 2.75rem);
|
||||||
|
|||||||
@ -174,8 +174,8 @@ addCallback((global: GlobalState) => {
|
|||||||
if (IS_TAURI) {
|
if (IS_TAURI) {
|
||||||
document.body.classList.add('is-tauri');
|
document.body.classList.add('is-tauri');
|
||||||
}
|
}
|
||||||
if (IS_ELECTRON) { // Legacy
|
if (IS_ELECTRON) { // Legacy, pretend to be Tauri
|
||||||
document.body.classList.add('is-electron');
|
document.body.classList.add('is-tauri');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -92,7 +92,7 @@ body.is-ios {
|
|||||||
--border-radius-messages-small: 0.5rem;
|
--border-radius-messages-small: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
body.is-tauri, body.is-electron {
|
body.is-tauri {
|
||||||
--custom-cursor: default;
|
--custom-cursor: default;
|
||||||
--window-controls-width: 5rem;
|
--window-controls-width: 5rem;
|
||||||
}
|
}
|
||||||
|
|||||||
4
src/types/language.d.ts
vendored
4
src/types/language.d.ts
vendored
@ -1051,8 +1051,8 @@ export interface LangPair {
|
|||||||
'JustNowAgo': undefined;
|
'JustNowAgo': undefined;
|
||||||
'AudioPause': undefined;
|
'AudioPause': undefined;
|
||||||
'AudioPlay': undefined;
|
'AudioPlay': undefined;
|
||||||
'ToggleUserNotifications': undefined;
|
'AriaToggleUserNotifications': undefined;
|
||||||
'ToggleChatNotifications': undefined;
|
'AriaToggleChatNotifications': undefined;
|
||||||
'ChannelInaccessible': undefined;
|
'ChannelInaccessible': undefined;
|
||||||
'GroupInaccessible': undefined;
|
'GroupInaccessible': undefined;
|
||||||
'AriaPasswordToggle': undefined;
|
'AriaPasswordToggle': undefined;
|
||||||
|
|||||||
52
tauri/Cargo.lock
generated
52
tauri/Cargo.lock
generated
@ -1605,6 +1605,16 @@ dependencies = [
|
|||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gethostname"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fc257fdb4038301ce4b9cd1b3b51704509692bb3ff716a410cbd07925d9dae55"
|
||||||
|
dependencies = [
|
||||||
|
"rustix",
|
||||||
|
"windows-targets 0.52.6",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.1.16"
|
version = "0.1.16"
|
||||||
@ -3221,6 +3231,18 @@ dependencies = [
|
|||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "os_info"
|
||||||
|
version = "3.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d0e1ac5fde8d43c34139135df8ea9ee9465394b2d8d20f032d38998f64afffc3"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"plist",
|
||||||
|
"serde",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "os_pipe"
|
name = "os_pipe"
|
||||||
version = "1.2.2"
|
version = "1.2.2"
|
||||||
@ -4838,6 +4860,15 @@ dependencies = [
|
|||||||
"syn 2.0.106",
|
"syn 2.0.106",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sys-locale"
|
||||||
|
version = "0.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "system-deps"
|
name = "system-deps"
|
||||||
version = "6.2.2"
|
version = "6.2.2"
|
||||||
@ -5142,6 +5173,24 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tauri-plugin-os"
|
||||||
|
version = "2.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77a1c77ebf6f20417ab2a74e8c310820ba52151406d0c80fbcea7df232e3f6ba"
|
||||||
|
dependencies = [
|
||||||
|
"gethostname",
|
||||||
|
"log",
|
||||||
|
"os_info",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"serialize-to-javascript",
|
||||||
|
"sys-locale",
|
||||||
|
"tauri",
|
||||||
|
"tauri-plugin",
|
||||||
|
"thiserror 2.0.16",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-plugin-process"
|
name = "tauri-plugin-process"
|
||||||
version = "2.3.0"
|
version = "2.3.0"
|
||||||
@ -5351,7 +5400,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "telegram_air"
|
name = "telegram_air"
|
||||||
version = "2.8.8"
|
version = "2.8.9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ab_glyph",
|
"ab_glyph",
|
||||||
"cocoa",
|
"cocoa",
|
||||||
@ -5368,6 +5417,7 @@ dependencies = [
|
|||||||
"tauri-plugin-fs",
|
"tauri-plugin-fs",
|
||||||
"tauri-plugin-log",
|
"tauri-plugin-log",
|
||||||
"tauri-plugin-notification",
|
"tauri-plugin-notification",
|
||||||
|
"tauri-plugin-os",
|
||||||
"tauri-plugin-process",
|
"tauri-plugin-process",
|
||||||
"tauri-plugin-shell",
|
"tauri-plugin-shell",
|
||||||
"tauri-plugin-single-instance",
|
"tauri-plugin-single-instance",
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "telegram_air"
|
name = "telegram_air"
|
||||||
version = "2.8.8"
|
version = "2.8.9"
|
||||||
description = "Telegram Air"
|
description = "Telegram Air"
|
||||||
authors = ["Alexander Zinchuk"]
|
authors = ["Alexander Zinchuk"]
|
||||||
license = "GPLv3"
|
license = "GPLv3"
|
||||||
@ -31,6 +31,7 @@ url = "2.5.7"
|
|||||||
image = "0.25.6"
|
image = "0.25.6"
|
||||||
imageproc = "0.25.0"
|
imageproc = "0.25.0"
|
||||||
ab_glyph = "0.2.31"
|
ab_glyph = "0.2.31"
|
||||||
|
tauri-plugin-os = "2"
|
||||||
|
|
||||||
[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\"))".dependencies]
|
[target."cfg(any(target_os = \"macos\", windows, target_os = \"linux\"))".dependencies]
|
||||||
tauri-plugin-single-instance = { version = "2.3.3", features = ["deep-link"] }
|
tauri-plugin-single-instance = { version = "2.3.3", features = ["deep-link"] }
|
||||||
|
|||||||
@ -1,3 +1,3 @@
|
|||||||
fn main() {
|
fn main() {
|
||||||
tauri_build::build()
|
tauri_build::build()
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,46 +5,46 @@ use tauri_plugin_deep_link::DeepLinkExt;
|
|||||||
pub struct Deeplink;
|
pub struct Deeplink;
|
||||||
|
|
||||||
impl Deeplink {
|
impl Deeplink {
|
||||||
pub fn init() -> Self {
|
pub fn init() -> Self {
|
||||||
Self {}
|
Self {}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn setup(&self, app: &tauri::AppHandle) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn setup(&self, app: &tauri::AppHandle) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
// Clone the app handle for use in the closure
|
// Clone the app handle for use in the closure
|
||||||
let app_handle = app.clone();
|
let app_handle = app.clone();
|
||||||
|
|
||||||
// Set up the deep link event handler
|
// Set up the deep link event handler
|
||||||
app.deep_link().on_open_url(move |event| {
|
app.deep_link().on_open_url(move |event| {
|
||||||
// Store URLs to avoid calling event.urls() multiple times (it consumes the event)
|
// Store URLs to avoid calling event.urls() multiple times (it consumes the event)
|
||||||
let urls = event.urls();
|
let urls = event.urls();
|
||||||
info!("Deep link received: {:?}", urls);
|
info!("Deep link received: {:?}", urls);
|
||||||
|
|
||||||
// Get the main window
|
// Get the main window
|
||||||
if let Some(window) = app_handle.get_webview_window("main") {
|
if let Some(window) = app_handle.get_webview_window("main") {
|
||||||
// Emit the deep link event to the frontend
|
// Emit the deep link event to the frontend
|
||||||
if let Err(err) = window.emit("deeplink", &urls) {
|
if let Err(err) = window.emit("deeplink", &urls) {
|
||||||
info!("Error emitting deeplink event: {:?}", err);
|
info!("Error emitting deeplink event: {:?}", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Request user attention and focus the window
|
// Request user attention and focus the window
|
||||||
if let Err(err) = window.request_user_attention(Some(UserAttentionType::Informational)) {
|
if let Err(err) = window.request_user_attention(Some(UserAttentionType::Informational)) {
|
||||||
info!("Error requesting user attention: {:?}", err);
|
info!("Error requesting user attention: {:?}", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(err) = window.show() {
|
if let Err(err) = window.show() {
|
||||||
info!("Error showing window: {:?}", err);
|
info!("Error showing window: {:?}", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(err) = window.unminimize() {
|
if let Err(err) = window.unminimize() {
|
||||||
info!("Error unminimizing window: {:?}", err);
|
info!("Error unminimizing window: {:?}", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(err) = window.set_focus() {
|
if let Err(err) = window.set_focus() {
|
||||||
info!("Error setting focus: {:?}", err);
|
info!("Error setting focus: {:?}", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,9 +33,19 @@ impl Default for AppStateStruct {
|
|||||||
|
|
||||||
pub type AppState = Mutex<AppStateStruct>;
|
pub type AppState = Mutex<AppStateStruct>;
|
||||||
|
|
||||||
pub const TRAFFIC_LIGHT_POSITION_OVERLAY: LogicalPosition<f64> = LogicalPosition::new(12.0, 26.0);
|
pub const TRAFFIC_LIGHT_POSITION_OVERLAY_LEGACY: LogicalPosition<f64> = LogicalPosition::new(12.0, 26.0);
|
||||||
|
pub const TRAFFIC_LIGHT_POSITION_OVERLAY_26: LogicalPosition<f64> = LogicalPosition::new(12.0, 30.0);
|
||||||
pub const TRAFFIC_LIGHT_POSITION_DEFAULT: LogicalPosition<f64> = LogicalPosition::new(12.0, 12.0);
|
pub const TRAFFIC_LIGHT_POSITION_DEFAULT: LogicalPosition<f64> = LogicalPosition::new(12.0, 12.0);
|
||||||
|
|
||||||
|
pub static TRAFFIC_LIGHT_POSITION_OVERLAY: LazyLock<LogicalPosition<f64>> = LazyLock::new(|| {
|
||||||
|
if let tauri_plugin_os::Version::Semantic(major, _, _) = tauri_plugin_os::version() {
|
||||||
|
if major >= 26 {
|
||||||
|
return TRAFFIC_LIGHT_POSITION_OVERLAY_26;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TRAFFIC_LIGHT_POSITION_OVERLAY_LEGACY
|
||||||
|
});
|
||||||
|
|
||||||
pub const WINDOW_WIDTH: f64 = 1088.0;
|
pub const WINDOW_WIDTH: f64 = 1088.0;
|
||||||
pub const WINDOW_HEIGHT: f64 = 700.0;
|
pub const WINDOW_HEIGHT: f64 = 700.0;
|
||||||
pub const WINDOW_MIN_WIDTH: f64 = 360.0;
|
pub const WINDOW_MIN_WIDTH: f64 = 360.0;
|
||||||
@ -90,6 +100,7 @@ pub fn run() {
|
|||||||
open_new_window(app.clone(), BASE_URL.to_string()).unwrap();
|
open_new_window(app.clone(), BASE_URL.to_string()).unwrap();
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
|
.plugin(tauri_plugin_os::init())
|
||||||
.plugin(tauri_plugin_fs::init())
|
.plugin(tauri_plugin_fs::init())
|
||||||
.plugin(tauri_plugin_shell::init())
|
.plugin(tauri_plugin_shell::init())
|
||||||
.plugin(tauri_plugin_notification::init())
|
.plugin(tauri_plugin_notification::init())
|
||||||
@ -124,7 +135,7 @@ pub fn run() {
|
|||||||
state.title.clone()
|
state.title.clone()
|
||||||
};
|
};
|
||||||
let traffic_position = if state.is_overlay {
|
let traffic_position = if state.is_overlay {
|
||||||
TRAFFIC_LIGHT_POSITION_OVERLAY
|
*TRAFFIC_LIGHT_POSITION_OVERLAY
|
||||||
} else {
|
} else {
|
||||||
TRAFFIC_LIGHT_POSITION_DEFAULT
|
TRAFFIC_LIGHT_POSITION_DEFAULT
|
||||||
};
|
};
|
||||||
@ -199,7 +210,7 @@ fn mark_title_bar_overlay(window: tauri::WebviewWindow, is_overlay: bool) {
|
|||||||
mac::update_window_title(
|
mac::update_window_title(
|
||||||
base_window.clone(),
|
base_window.clone(),
|
||||||
"".to_string(),
|
"".to_string(),
|
||||||
TRAFFIC_LIGHT_POSITION_OVERLAY,
|
*TRAFFIC_LIGHT_POSITION_OVERLAY,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -297,7 +308,10 @@ pub(crate) fn open_new_window(
|
|||||||
.inner_size(WINDOW_WIDTH, WINDOW_HEIGHT)
|
.inner_size(WINDOW_WIDTH, WINDOW_HEIGHT)
|
||||||
.min_inner_size(WINDOW_MIN_WIDTH, WINDOW_MIN_HEIGHT)
|
.min_inner_size(WINDOW_MIN_WIDTH, WINDOW_MIN_HEIGHT)
|
||||||
.disable_drag_drop_handler() // Required for Drag & Drop on Windows
|
.disable_drag_drop_handler() // Required for Drag & Drop on Windows
|
||||||
.initialization_script(&format!("window.tauri = {{ version: '{}' }};", env!("CARGO_PKG_VERSION")))
|
.initialization_script(&format!(
|
||||||
|
"window.tauri = {{ version: '{}' }};",
|
||||||
|
env!("CARGO_PKG_VERSION")
|
||||||
|
))
|
||||||
.on_download(|window, event| {
|
.on_download(|window, event| {
|
||||||
match event {
|
match event {
|
||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
@ -345,7 +359,7 @@ pub(crate) fn open_new_window(
|
|||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
if let Some(base_window) = app.get_window(&window_label) {
|
if let Some(base_window) = app.get_window(&window_label) {
|
||||||
mac::setup_traffic_light_positioner(&base_window, TRAFFIC_LIGHT_POSITION_OVERLAY);
|
mac::setup_traffic_light_positioner(&base_window, *TRAFFIC_LIGHT_POSITION_OVERLAY);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply stored notification count to the new window
|
// Apply stored notification count to the new window
|
||||||
|
|||||||
@ -2,5 +2,5 @@
|
|||||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
app_lib::run();
|
app_lib::run();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
use image::{Rgba, RgbaImage, imageops};
|
|
||||||
use imageproc::drawing::{draw_filled_rect_mut, draw_filled_circle_mut, draw_text_mut, text_size};
|
|
||||||
use imageproc::rect::Rect;
|
|
||||||
use imageproc::filter::gaussian_blur_f32;
|
|
||||||
use ab_glyph::{FontRef, PxScale};
|
use ab_glyph::{FontRef, PxScale};
|
||||||
|
use image::{Rgba, RgbaImage, imageops};
|
||||||
|
use imageproc::drawing::{draw_filled_circle_mut, draw_filled_rect_mut, draw_text_mut, text_size};
|
||||||
|
use imageproc::filter::gaussian_blur_f32;
|
||||||
|
use imageproc::rect::Rect;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
use tauri::image::Image;
|
use tauri::image::Image;
|
||||||
|
|
||||||
@ -47,21 +47,25 @@ pub fn set_badge_count_icon(window: &tauri::WebviewWindow, amount: i32, is_muted
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_counter_png(size: u32, count: i32, is_muted: bool) -> Vec<u8> {
|
pub fn generate_counter_png(size: u32, count: i32, is_muted: bool) -> Vec<u8> {
|
||||||
let background_color = if is_muted { BADGE_BACKGROUND_COLOR_MUTED } else { BADGE_BACKGROUND_COLOR };
|
let background_color = if is_muted {
|
||||||
|
BADGE_BACKGROUND_COLOR_MUTED
|
||||||
|
} else {
|
||||||
|
BADGE_BACKGROUND_COLOR
|
||||||
|
};
|
||||||
|
|
||||||
// Prepare text properties
|
// Prepare text properties
|
||||||
let (text, font, scale, text_width, text_height) = if count >= 0 {
|
let (text, font, scale, text_width, text_height) = if count >= 0 {
|
||||||
let text = if count < 100 {
|
let text = if count < 100 {
|
||||||
count.to_string()
|
count.to_string()
|
||||||
} else {
|
} else {
|
||||||
format!("..{:02}", count % 100)
|
format!("..{:02}", count % 100)
|
||||||
};
|
};
|
||||||
|
|
||||||
let font = FontRef::try_from_slice(FONT).expect("Invalid font");
|
let font = FontRef::try_from_slice(FONT).expect("Invalid font");
|
||||||
let scale = {
|
let scale = {
|
||||||
let base = if text.len() < 3 { 0.9 } else { 0.75 };
|
let base = if text.len() < 3 { 0.9 } else { 0.75 };
|
||||||
let calculated_scale = (base * size as f32).ceil();
|
let calculated_scale = (base * size as f32).ceil();
|
||||||
PxScale::from(calculated_scale)
|
PxScale::from(calculated_scale)
|
||||||
};
|
};
|
||||||
|
|
||||||
let (text_width, text_height) = text_size(scale, &font, &text);
|
let (text_width, text_height) = text_size(scale, &font, &text);
|
||||||
@ -102,7 +106,15 @@ pub fn generate_counter_png(size: u32, count: i32, is_muted: bool) -> Vec<u8> {
|
|||||||
badge_height / 2
|
badge_height / 2
|
||||||
};
|
};
|
||||||
|
|
||||||
draw_rounded_rect(&mut img, edge_space, edge_space, badge_width, badge_height, corner_radius, background_color);
|
draw_rounded_rect(
|
||||||
|
&mut img,
|
||||||
|
edge_space,
|
||||||
|
edge_space,
|
||||||
|
badge_width,
|
||||||
|
badge_height,
|
||||||
|
corner_radius,
|
||||||
|
background_color,
|
||||||
|
);
|
||||||
|
|
||||||
// Apply gaussian blur for antialiasing effect
|
// Apply gaussian blur for antialiasing effect
|
||||||
img = gaussian_blur_f32(&img, 0.75);
|
img = gaussian_blur_f32(&img, 0.75);
|
||||||
@ -111,15 +123,25 @@ pub fn generate_counter_png(size: u32, count: i32, is_muted: bool) -> Vec<u8> {
|
|||||||
let x = edge_space as f32 + ((badge_width as f32 - text_width as f32) / 2.0).ceil();
|
let x = edge_space as f32 + ((badge_width as f32 - text_width as f32) / 2.0).ceil();
|
||||||
|
|
||||||
let baseline_offset = scale.y * 0.15;
|
let baseline_offset = scale.y * 0.15;
|
||||||
let y = edge_space as f32 + ((badge_height as f32 - text_height as f32) / 2.0 - baseline_offset).ceil();
|
let y = edge_space as f32
|
||||||
|
+ ((badge_height as f32 - text_height as f32) / 2.0 - baseline_offset).ceil();
|
||||||
|
|
||||||
draw_text_mut(&mut img, BADGE_TEXT_COLOR, x as i32, y as i32, scale, &font, &text);
|
draw_text_mut(
|
||||||
|
&mut img,
|
||||||
|
BADGE_TEXT_COLOR,
|
||||||
|
x as i32,
|
||||||
|
y as i32,
|
||||||
|
scale,
|
||||||
|
&font,
|
||||||
|
&text,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut buffer = Vec::new();
|
let mut buffer = Vec::new();
|
||||||
let mut cursor = Cursor::new(&mut buffer);
|
let mut cursor = Cursor::new(&mut buffer);
|
||||||
img.write_to(&mut cursor, image::ImageFormat::Png)
|
img
|
||||||
.expect("PNG encode failed");
|
.write_to(&mut cursor, image::ImageFormat::Png)
|
||||||
|
.expect("PNG encode failed");
|
||||||
buffer
|
buffer
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,8 +152,9 @@ pub fn overlay_tray_icon(icon: &Image, counter: &Image) -> Image<'static> {
|
|||||||
let icon_img = image::RgbaImage::from_raw(icon.width(), icon.height(), icon_rgba.to_vec())
|
let icon_img = image::RgbaImage::from_raw(icon.width(), icon.height(), icon_rgba.to_vec())
|
||||||
.expect("Failed to create RgbaImage from icon data");
|
.expect("Failed to create RgbaImage from icon data");
|
||||||
|
|
||||||
let counter_img = image::RgbaImage::from_raw(counter.width(), counter.height(), counter_rgba.to_vec())
|
let counter_img =
|
||||||
.expect("Failed to create RgbaImage from counter data");
|
image::RgbaImage::from_raw(counter.width(), counter.height(), counter_rgba.to_vec())
|
||||||
|
.expect("Failed to create RgbaImage from counter data");
|
||||||
|
|
||||||
let mut result = icon_img.clone();
|
let mut result = icon_img.clone();
|
||||||
|
|
||||||
@ -150,7 +173,8 @@ pub fn overlay_tray_icon(icon: &Image, counter: &Image) -> Image<'static> {
|
|||||||
// Convert back to tauri Image
|
// Convert back to tauri Image
|
||||||
let mut buffer = Vec::new();
|
let mut buffer = Vec::new();
|
||||||
let mut cursor = Cursor::new(&mut buffer);
|
let mut cursor = Cursor::new(&mut buffer);
|
||||||
result.write_to(&mut cursor, image::ImageFormat::Png)
|
result
|
||||||
|
.write_to(&mut cursor, image::ImageFormat::Png)
|
||||||
.expect("PNG encode failed");
|
.expect("PNG encode failed");
|
||||||
|
|
||||||
Image::from_bytes(&buffer).expect("Failed to create Image from bytes")
|
Image::from_bytes(&buffer).expect("Failed to create Image from bytes")
|
||||||
@ -163,33 +187,80 @@ fn draw_rounded_rect(
|
|||||||
width: u32,
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
radius: u32,
|
radius: u32,
|
||||||
color: Rgba<u8>
|
color: Rgba<u8>,
|
||||||
) {
|
) {
|
||||||
let radius = radius.min(width / 2).min(height / 2);
|
let radius = radius.min(width / 2).min(height / 2);
|
||||||
|
|
||||||
if radius == 0 {
|
if radius == 0 {
|
||||||
draw_filled_rect_mut(img, Rect::at(x as i32, y as i32).of_size(width, height), color);
|
draw_filled_rect_mut(
|
||||||
|
img,
|
||||||
|
Rect::at(x as i32, y as i32).of_size(width, height),
|
||||||
|
color,
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if width > 2 * radius && height > 2 * radius {
|
if width > 2 * radius && height > 2 * radius {
|
||||||
draw_filled_rect_mut(img, Rect::at((x + radius) as i32, (y + radius) as i32).of_size(width - 2 * radius, height - 2 * radius), color);
|
draw_filled_rect_mut(
|
||||||
|
img,
|
||||||
|
Rect::at((x + radius) as i32, (y + radius) as i32)
|
||||||
|
.of_size(width - 2 * radius, height - 2 * radius),
|
||||||
|
color,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if width > 2 * radius {
|
if width > 2 * radius {
|
||||||
draw_filled_rect_mut(img, Rect::at((x + radius) as i32, y as i32).of_size(width - 2 * radius, radius), color);
|
draw_filled_rect_mut(
|
||||||
draw_filled_rect_mut(img, Rect::at((x + radius) as i32, (y + height - radius) as i32).of_size(width - 2 * radius, radius), color);
|
img,
|
||||||
|
Rect::at((x + radius) as i32, y as i32).of_size(width - 2 * radius, radius),
|
||||||
|
color,
|
||||||
|
);
|
||||||
|
draw_filled_rect_mut(
|
||||||
|
img,
|
||||||
|
Rect::at((x + radius) as i32, (y + height - radius) as i32)
|
||||||
|
.of_size(width - 2 * radius, radius),
|
||||||
|
color,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if height > 2 * radius {
|
if height > 2 * radius {
|
||||||
draw_filled_rect_mut(img, Rect::at(x as i32, (y + radius) as i32).of_size(radius, height - 2 * radius), color);
|
draw_filled_rect_mut(
|
||||||
draw_filled_rect_mut(img, Rect::at((x + width - radius) as i32, (y + radius) as i32).of_size(radius, height - 2 * radius), color);
|
img,
|
||||||
|
Rect::at(x as i32, (y + radius) as i32).of_size(radius, height - 2 * radius),
|
||||||
|
color,
|
||||||
|
);
|
||||||
|
draw_filled_rect_mut(
|
||||||
|
img,
|
||||||
|
Rect::at((x + width - radius) as i32, (y + radius) as i32)
|
||||||
|
.of_size(radius, height - 2 * radius),
|
||||||
|
color,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let radius_i32 = radius as i32;
|
let radius_i32 = radius as i32;
|
||||||
|
|
||||||
draw_filled_circle_mut(img, ((x + radius) as i32, (y + radius) as i32), radius_i32, color);
|
draw_filled_circle_mut(
|
||||||
draw_filled_circle_mut(img, ((x + width - radius) as i32, (y + radius) as i32), radius_i32, color);
|
img,
|
||||||
draw_filled_circle_mut(img, ((x + radius) as i32, (y + height - radius) as i32), radius_i32, color);
|
((x + radius) as i32, (y + radius) as i32),
|
||||||
draw_filled_circle_mut(img, ((x + width - radius) as i32, (y + height - radius) as i32), radius_i32, color);
|
radius_i32,
|
||||||
|
color,
|
||||||
|
);
|
||||||
|
draw_filled_circle_mut(
|
||||||
|
img,
|
||||||
|
((x + width - radius) as i32, (y + radius) as i32),
|
||||||
|
radius_i32,
|
||||||
|
color,
|
||||||
|
);
|
||||||
|
draw_filled_circle_mut(
|
||||||
|
img,
|
||||||
|
((x + radius) as i32, (y + height - radius) as i32),
|
||||||
|
radius_i32,
|
||||||
|
color,
|
||||||
|
);
|
||||||
|
draw_filled_circle_mut(
|
||||||
|
img,
|
||||||
|
((x + width - radius) as i32, (y + height - radius) as i32),
|
||||||
|
radius_i32,
|
||||||
|
color,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user