fix: browser item style
This commit is contained in:
@@ -91,9 +91,19 @@ HTML-макеты → PNG: **headless Edge** (`--headless --screenshot`), он
|
|||||||
Примечание: мок-пути (firefox.exe, chrome.exe, zen.exe) вне PATH — запуск вернёт
|
Примечание: мок-пути (firefox.exe, chrome.exe, zen.exe) вне PATH — запуск вернёт
|
||||||
ошибку в stderr до этапа E (автодетект/конфиг). Клик-выбор проверяется визуально.
|
ошибку в stderr до этапа E (автодетект/конфиг). Клик-выбор проверяется визуально.
|
||||||
|
|
||||||
|
### Этап D2 — UX-полировка списка
|
||||||
|
|
||||||
|
- [x] Отступ списка слева/справа 12px (карточки не прилипают к краям)
|
||||||
|
- [x] Индикатор выбора без синего круга — синяя SVG-галочка 16px;
|
||||||
|
у невыбранных — шеврон «›»
|
||||||
|
- [x] Клик по карточке = немедленный запуск (`launch-browser(BrowserConfig)`);
|
||||||
|
«Открыть» в футере остаётся (запуск выбранного)
|
||||||
|
|
||||||
## Этап E — конфиг и настройки
|
## Этап E — конфиг и настройки
|
||||||
|
|
||||||
- [ ] `config.toml` рядом с exe / `%APPDATA%\bropicker` (крейс `toml`), serde-структура BrowserConfig
|
- [ ] `config.toml` рядом с exe / `%APPDATA%\bropicker` (крейс `toml`), serde-структура BrowserConfig
|
||||||
|
- [ ] Логика запуска с учётом галочек: remember-choice → записать выбор для домена;
|
||||||
|
always-ask → показывать пикер несмотря на запомненное
|
||||||
- [ ] Страница настроек: TabWidget + LineEdit/SpinBox/ComboBox/CheckBox std-widgets;
|
- [ ] Страница настроек: TabWidget + LineEdit/SpinBox/ComboBox/CheckBox std-widgets;
|
||||||
вход по кнопке cog из футера (колбэк settings-clicked уже есть)
|
вход по кнопке cog из футера (колбэк settings-clicked уже есть)
|
||||||
- [ ] Автодетект установленных браузеров (реестр Windows) как fallback при отсутствии конфига
|
- [ ] Автодетект установленных браузеров (реестр Windows) как fallback при отсутствии конфига
|
||||||
|
|||||||
+17
-3
@@ -65,7 +65,7 @@ fn init() -> State {
|
|||||||
main_window.set_remember_choice(true);
|
main_window.set_remember_choice(true);
|
||||||
main_window.set_always_ask(true);
|
main_window.set_always_ask(true);
|
||||||
|
|
||||||
main_window.on_browser_selected({
|
main_window.on_launch_browser({
|
||||||
let main_window = main_window.clone_strong();
|
let main_window = main_window.clone_strong();
|
||||||
let browser_model = browser_model.clone();
|
let browser_model = browser_model.clone();
|
||||||
move |browser: BrowserConfig| {
|
move |browser: BrowserConfig| {
|
||||||
@@ -77,10 +77,24 @@ fn init() -> State {
|
|||||||
})
|
})
|
||||||
.unwrap_or(0);
|
.unwrap_or(0);
|
||||||
main_window.set_selected_index(index as i32);
|
main_window.set_selected_index(index as i32);
|
||||||
|
|
||||||
|
let url = main_window.get_current_url().to_string();
|
||||||
println!(
|
println!(
|
||||||
"Selected [{}]: {:?} {:?}",
|
"Launching [{}]: {:?} {:?} {}",
|
||||||
index, browser.path, browser.flags
|
index, browser.path, browser.flags, url
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let mut cmd = std::process::Command::new(browser.path.to_string());
|
||||||
|
if !browser.flags.is_empty() {
|
||||||
|
cmd.args(browser.flags.split_whitespace());
|
||||||
|
}
|
||||||
|
|
||||||
|
match cmd.arg(url).spawn() {
|
||||||
|
Ok(_) => {
|
||||||
|
let _ = main_window.window().hide();
|
||||||
|
}
|
||||||
|
Err(e) => eprintln!("launch failed: {e}"),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+7
-14
@@ -81,29 +81,22 @@ export component BrowserItem inherits Rectangle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
VerticalLayout {
|
||||||
width: 24px;
|
width: 20px;
|
||||||
border-radius: 12px;
|
alignment: center;
|
||||||
background: root.selected ? #3b82f6 : Theme.surface-elevated;
|
|
||||||
|
|
||||||
Image {
|
Image {
|
||||||
x: (parent.width - self.width) / 2;
|
width: 16px;
|
||||||
y: (parent.height - self.height) / 2;
|
height: 16px;
|
||||||
width: 12px;
|
|
||||||
height: 12px;
|
|
||||||
source: @image-url("../icons/check.svg");
|
source: @image-url("../icons/check.svg");
|
||||||
colorize: #ffffff;
|
colorize: #3b82f6;
|
||||||
visible: root.selected;
|
visible: root.selected;
|
||||||
}
|
}
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
horizontal-alignment: center;
|
|
||||||
vertical-alignment: center;
|
|
||||||
text: "›";
|
text: "›";
|
||||||
color: Theme.text-muted;
|
color: Theme.text-muted;
|
||||||
font-size: 14px;
|
font-size: 16px;
|
||||||
visible: !root.selected;
|
visible: !root.selected;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-2
@@ -62,7 +62,7 @@ export component MainWindow inherits Window {
|
|||||||
in-out property <bool> always-ask: true;
|
in-out property <bool> always-ask: true;
|
||||||
in property <int> selected-index: 0;
|
in property <int> selected-index: 0;
|
||||||
|
|
||||||
callback browser-selected(BrowserConfig);
|
callback launch-browser(BrowserConfig);
|
||||||
callback toggle-remember(bool);
|
callback toggle-remember(bool);
|
||||||
callback toggle-always-ask(bool);
|
callback toggle-always-ask(bool);
|
||||||
callback settings-clicked();
|
callback settings-clicked();
|
||||||
@@ -112,6 +112,10 @@ export component MainWindow inherits Window {
|
|||||||
request-drag => root.request-drag();
|
request-drag => root.request-drag();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HorizontalLayout {
|
||||||
|
padding-left: 12px;
|
||||||
|
padding-right: 12px;
|
||||||
|
|
||||||
ListView {
|
ListView {
|
||||||
vertical-stretch: 1;
|
vertical-stretch: 1;
|
||||||
|
|
||||||
@@ -121,7 +125,8 @@ export component MainWindow inherits Window {
|
|||||||
is-default: browser.is-default;
|
is-default: browser.is-default;
|
||||||
selected: i == root.selected-index;
|
selected: i == root.selected-index;
|
||||||
clicked => {
|
clicked => {
|
||||||
root.browser-selected(browser);
|
root.launch-browser(browser);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user