feat: update config flow, use emoji
This commit is contained in:
@@ -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]
|
||||||
|
|||||||
@@ -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
@@ -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))
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user