feat: update config flow, use emoji

This commit is contained in:
2026-08-26 14:17:57 +05:00
parent 55e30ecfe6
commit 381fc5c049
7 changed files with 63 additions and 12 deletions
+5
View File
@@ -6,6 +6,8 @@
# path — полный путь к exe (или имя из PATH) # path — полный путь к exe (или имя из PATH)
# flags — аргументы запуска; пробелы внутри значения — в кавычках # flags — аргументы запуска; пробелы внутри значения — в кавычках
# icon — необязательно: путь к png/svg, иначе подбирается по имени # icon — необязательно: путь к png/svg, иначе подбирается по имени
# emoji — необязательно: эмодзи вместо иконки (удобно различать профили);
# имеет приоритет над icon
[[browsers]] [[browsers]]
name = "Firefox" name = "Firefox"
@@ -20,16 +22,19 @@ flags = ""
name = "Chrome — Work" name = "Chrome — Work"
path = 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe' path = 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
flags = '--profile-directory="Default"' flags = '--profile-directory="Default"'
emoji = "💼"
[[browsers]] [[browsers]]
name = "Chrome — Personal" name = "Chrome — Personal"
path = 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe' path = 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'
flags = '--profile-directory="Profile 1"' flags = '--profile-directory="Profile 1"'
emoji = "🏠"
[[browsers]] [[browsers]]
name = "Firefox — Work" name = "Firefox — Work"
path = 'C:\Program Files\Mozilla Firefox\firefox.exe' path = 'C:\Program Files\Mozilla Firefox\firefox.exe'
flags = '-P "Work"' flags = '-P "Work"'
emoji = "🦊"
# Запомненные домены: домен = имя записи из [[browsers]] # Запомненные домены: домен = имя записи из [[browsers]]
[remembered] [remembered]
+4
View File
@@ -155,6 +155,10 @@ HTML-макеты → PNG: **headless Edge** (`--headless --screenshot`), он
- [x] Парсер флагов понимает кавычки (`split_flags`) — профили браузеров: - [x] Парсер флагов понимает кавычки (`split_flags`) — профили браузеров:
`flags = '--profile-directory="Profile 1"'` (Chrome), `-P "Work"` (Firefox); `flags = '--profile-directory="Profile 1"'` (Chrome), `-P "Work"` (Firefox);
пример: docs/config.example.toml пример: docs/config.example.toml
- [x] Эмодзи-иконка для записи: поле `emoji` в конфиге (приоритет над icon) —
различение профилей одного браузера; фолбэк-глобус colorize по теме
(был чёрным на тёмной), цветные PNG логотипов не трогаются
(`icon-mask` только для генерик-глобуса)
- [x] Cold start release: 131 ms (после добавления файлового лога) - [x] Cold start release: 131 ms (после добавления файлового лога)
## Этап F — релиз ## Этап F — релиз
+23 -11
View File
@@ -30,6 +30,8 @@ pub struct BrowserEntry {
pub flags: String, pub flags: String,
#[serde(default)] #[serde(default)]
pub icon: String, pub icon: String,
#[serde(default)]
pub emoji: String,
} }
#[derive(Serialize, Deserialize, Clone, Debug)] #[derive(Serialize, Deserialize, Clone, Debug)]
@@ -165,6 +167,7 @@ pub fn detect_browsers() -> Vec<BrowserEntry> {
path, path,
flags: String::new(), flags: String::new(),
icon: String::new(), icon: String::new(),
emoji: String::new(),
}); });
} }
} }
@@ -173,18 +176,27 @@ pub fn detect_browsers() -> Vec<BrowserEntry> {
} }
pub fn icon_for(name: &str) -> &'static str { pub fn icon_for(name: &str) -> &'static str {
let n = name.to_lowercase(); if is_known_browser(name) {
if n.contains("firefox") { KNOWN_ICONS
"logos/firefox_48x48.png" .iter()
} else if n.contains("chrome") { .find(|(kw, _)| name.to_lowercase().contains(kw))
"logos/chrome_48x48.png" .map(|(_, path)| *path)
} else if n.contains("opera") { .unwrap_or("icons/globe.svg")
"logos/opera_48x48.png"
} else if n.contains("brave") {
"logos/brave_48x48.png"
} else if n.contains("яндекс") || n.contains("yandex") {
"logos/yandex_48x48.png"
} else { } else {
"icons/globe.svg" "icons/globe.svg"
} }
} }
const KNOWN_ICONS: &[(&str, &str)] = &[
("firefox", "logos/firefox_48x48.png"),
("chrome", "logos/chrome_48x48.png"),
("opera", "logos/opera_48x48.png"),
("brave", "logos/brave_48x48.png"),
("яндекс", "logos/yandex_48x48.png"),
("yandex", "logos/yandex_48x48.png"),
];
pub fn is_known_browser(name: &str) -> bool {
let n = name.to_lowercase();
KNOWN_ICONS.iter().any(|(kw, _)| n.contains(kw))
}
+6
View File
@@ -54,6 +54,10 @@ fn to_ui_config(entry: &BrowserEntry) -> BrowserConfig {
}; };
BrowserConfig { BrowserConfig {
icon: load_icon(icon_rel), icon: load_icon(icon_rel),
emoji: entry.emoji.clone().into(),
icon_mask: entry.icon.is_empty()
&& entry.emoji.is_empty()
&& !config::is_known_browser(&entry.name),
name: entry.name.clone().into(), name: entry.name.clone().into(),
path: entry.path.clone().into(), path: entry.path.clone().into(),
flags: entry.flags.clone().into(), flags: entry.flags.clone().into(),
@@ -142,6 +146,7 @@ fn init(cfg: Config, url: Option<String>) -> State {
path: entry.path.to_string(), path: entry.path.to_string(),
flags: entry.flags.to_string(), flags: entry.flags.to_string(),
icon: String::new(), icon: String::new(),
emoji: String::new(),
}; };
let url = main_window.get_current_url().to_string(); let url = main_window.get_current_url().to_string();
@@ -180,6 +185,7 @@ fn init(cfg: Config, url: Option<String>) -> State {
path: ui_entry.path.to_string(), path: ui_entry.path.to_string(),
flags: ui_entry.flags.to_string(), flags: ui_entry.flags.to_string(),
icon: String::new(), icon: String::new(),
emoji: String::new(),
}; };
let url = main_window.get_current_url().to_string(); let url = main_window.get_current_url().to_string();
+21 -1
View File
@@ -2,6 +2,8 @@ import { Theme } from "./theme.slint";
export component BrowserItem inherits Rectangle { export component BrowserItem inherits Rectangle {
in property <image> browser-icon; in property <image> browser-icon;
in property <string> emoji;
in property <bool> icon-mask;
in property <string> browser-name; in property <string> browser-name;
in property <bool> is-default; in property <bool> is-default;
in property <bool> selected; in property <bool> selected;
@@ -37,7 +39,25 @@ export component BrowserItem inherits Rectangle {
border-radius: 12px; border-radius: 12px;
background: Theme.surface-elevated; background: Theme.surface-elevated;
Image { if root.emoji != "": Text {
width: 100%;
height: 100%;
text: root.emoji;
font-size: 26px;
horizontal-alignment: center;
vertical-alignment: center;
}
if root.emoji == "" && root.icon-mask: Image {
x: (parent.width - self.width) / 2;
y: (parent.height - self.height) / 2;
width: 30px;
height: 30px;
source: root.browser-icon;
colorize: Theme.text-muted;
}
if root.emoji == "" && !root.icon-mask: Image {
x: (parent.width - self.width) / 2; x: (parent.width - self.width) / 2;
y: (parent.height - self.height) / 2; y: (parent.height - self.height) / 2;
width: 30px; width: 30px;
+2
View File
@@ -129,6 +129,8 @@ export component MainWindow inherits Window {
for browser[i] in root.browser-model: BrowserItem { for browser[i] in root.browser-model: BrowserItem {
browser-icon: browser.icon; browser-icon: browser.icon;
emoji: browser.emoji;
icon-mask: browser.icon-mask;
browser-name: browser.name; browser-name: browser.name;
is-default: browser.is-default; is-default: browser.is-default;
selected: i == root.selected-index; selected: i == root.selected-index;
+2
View File
@@ -1,5 +1,7 @@
export struct BrowserConfig { export struct BrowserConfig {
icon: image, icon: image,
emoji: string,
icon-mask: bool,
name: string, name: string,
path: string, path: string,
flags: string, flags: string,