feat: add register flow, update to use correct config file

This commit is contained in:
2026-08-26 10:21:41 +05:00
parent 9534c6b1e3
commit 9dfb72f0ea
4 changed files with 114 additions and 10 deletions
+5
View File
@@ -15,3 +15,8 @@ winreg = "0.56.0"
[build-dependencies] [build-dependencies]
slint-build = "1.16.1" slint-build = "1.16.1"
[profile.release]
lto = true
codegen-units = 1
strip = true
+34 -1
View File
@@ -129,10 +129,43 @@ HTML-макеты → PNG: **headless Edge** (`--headless --screenshot`), он
- [x] env `BP_VIEW=settings` — запуск сразу с окном настроек (без пикера); - [x] env `BP_VIEW=settings` — запуск сразу с окном настроек (без пикера);
нюанс: `run()` авто-показывает своё окно, поэтому в этом режиме цикл нюанс: `run()` авто-показывает своё окно, поэтому в этом режиме цикл
крутится на settings_window крутится на settings_window
- [ ] Редактирование браузера (имя/путь/флаги через LineEdit) — следующий шаг - [ ] Редактирование браузера (имя/путь/флаги через LineEdit) — ОТЛОЖЕНО (решено:
cog в пикере открывает `config.toml` в редакторе — `subl`, fallback `notepad`;
если файла нет — создаётся с автодетектом). Окно SettingsWindow осталось
в коде (недоступно из UI), dev-доступ: env `BP_VIEW=settings`
- [ ] Чтение флагов из .lnk ярлыков (крейс `lnk`) — по желанию - [ ] Чтение флагов из .lnk ярлыков (крейс `lnk`) — по желанию
- [ ] Добавить логотипы Edge/Zen в logos/ (пересоздать набор из alrrr/browser-logos) - [ ] Добавить логотипы Edge/Zen в logos/ (пересоздать набор из alrrr/browser-logos)
### E3 — доведение до ежедневного использования — ГОТОВО
- [x] cog → открыть конфиг в редакторе (subl → notepad)
- [x] Замер cold start: Instant в main → печать при старте event loop
- [x] `tools/register.ps1` (+ `-Uninstall`): **ставит пакет в
`%LOCALAPPDATA%\bropicker\` (exe + logos + icons)** и регистрирует
ProgId/Capabilities/RegisteredApplications в HKCU на путь из LOCALAPPDATA
(не target\ — переживает cargo clean и перенос репо), открывает
ms-settings:defaultapps
- [x] Иконки резолвятся от папки exe (иначе при запуске обработчиком ссылок
cwd = system32 и иконки бы отвалились); проверено запуском из
LOCALAPPDATA с cwd=System32
- [x] Release-профиль: lto + codegen-units=1 + strip
## Этап F — релиз
- [x] `[profile.release]`: lto, codegen-units=1, strip
- [x] Замер cold start (release, до старта event loop): **183 ms холодный /
120-122 ms тёплый**; из LOCALAPPDATA первый запуск 153 ms.
Цель <100 ms чуть не достигнута; варианты оптимизации, если захочется:
renderer-femtovg вместо skia (быстрее init GPU), отложенная загрузка
конфига. Пока считаем приемлемым
- [ ] Иконка exe (.ico через build.rs winres)
- [ ] Выбрать лицензию проекта: GPLv3 (опенсорс) или Royalty-free Slint (закрытый десктоп,
атрибуция AboutSlint) — зафиксировать в README и LICENSE
- [ ] Скриншоты в README из tools/out
- [ ] Ручной сценарий приёмки: register → клик ссылки в другом приложении →
пикер → выбор → вкладка открылась; повторный клик того же домена при
always_ask=off → сразу браузер
## Этап F — релиз ## Этап F — релиз
- [ ] `[profile.release]`: lto, codegen-units=1, strip - [ ] `[profile.release]`: lto, codegen-units=1, strip
+23 -9
View File
@@ -12,6 +12,14 @@ use config::{BrowserEntry, Config};
slint::include_modules!(); slint::include_modules!();
fn load_icon(rel: &str) -> slint::Image { fn load_icon(rel: &str) -> slint::Image {
if let Ok(exe) = std::env::current_exe() {
if let Some(dir) = exe.parent() {
let p = dir.join(rel);
if p.exists() {
return slint::Image::load_from_path(&p).unwrap_or_default();
}
}
}
slint::Image::load_from_path(std::path::Path::new(rel)).unwrap_or_default() slint::Image::load_from_path(std::path::Path::new(rel)).unwrap_or_default()
} }
@@ -202,16 +210,19 @@ fn init(cfg: Config, url: Option<String>) -> State {
}); });
main_window.on_settings_clicked({ main_window.on_settings_clicked({
let settings_window = settings_window.clone_strong();
move || { move || {
settings_window.show().unwrap(); let path = config::config_path();
let weak = settings_window.as_weak(); if !path.exists() {
let _ = slint::invoke_from_event_loop(move || { let mut c = config::load();
if let Some(sw) = weak.upgrade() { config::ensure_browsers(&mut c);
winit::center_window(sw.window()); }
sw.invoke_restore_focus(); let editor = std::process::Command::new("subl")
} .arg(&path)
}); .spawn()
.or_else(|_| std::process::Command::new("notepad").arg(&path).spawn());
if let Err(e) = editor {
eprintln!("[bp] cannot open editor: {e}");
}
} }
}); });
@@ -307,6 +318,8 @@ pub struct State {
} }
pub fn main() { pub fn main() {
let start = std::time::Instant::now();
let mut cfg = config::load(); let mut cfg = config::load();
config::ensure_browsers(&mut cfg); config::ensure_browsers(&mut cfg);
@@ -347,6 +360,7 @@ pub fn main() {
winit::center_window(mw.window()); winit::center_window(mw.window());
mw.invoke_restore_focus(); mw.invoke_restore_focus();
} }
eprintln!("[bp] cold start -> event loop: {:?}", start.elapsed());
}); });
state.main_window.run().unwrap(); state.main_window.run().unwrap();
+52
View File
@@ -0,0 +1,52 @@
param(
[switch]$Uninstall
)
$ErrorActionPreference = "Stop"
$installDir = Join-Path $env:LOCALAPPDATA "bropicker"
$classes = "HKCU:\Software\Classes\bropicker"
$caps = "HKCU:\Software\bropicker-Capabilities"
$regApps = "HKCU:\Software\RegisteredApplications"
if ($Uninstall) {
Remove-Item -Recurse -Force $classes -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force $caps -ErrorAction SilentlyContinue
Remove-ItemProperty -Path $regApps -Name "bropicker" -ErrorAction SilentlyContinue
Remove-Item -Recurse -Force $installDir -ErrorAction SilentlyContinue
Write-Host "bropicker unregistered and removed from $installDir"
exit 0
}
$src = Join-Path $PSScriptRoot "..\target\release\bropicker.exe"
if (-not (Test-Path $src)) {
Write-Error "target\release\bropicker.exe not found. Build first: cargo build --release"
exit 1
}
New-Item -ItemType Directory -Force -Path $installDir | Out-Null
Copy-Item $src (Join-Path $installDir "bropicker.exe") -Force
Copy-Item (Join-Path $PSScriptRoot "..\logos") (Join-Path $installDir "logos") -Recurse -Force
Copy-Item (Join-Path $PSScriptRoot "..\icons") (Join-Path $installDir "icons") -Recurse -Force
$exe = Join-Path $installDir "bropicker.exe"
Write-Host "Installed to: $exe"
New-Item -Path "$classes\shell\open\command" -Force | Out-Null
Set-ItemProperty -Path $classes -Name "(default)" -Value "bropicker"
Set-ItemProperty -Path $classes -Name "URL Protocol" -Value ""
Set-ItemProperty -Path "$classes\shell\open\command" -Name "(default)" -Value "`"$exe`" `"%1`""
New-Item -Path $caps -Force | Out-Null
Set-ItemProperty -Path $caps -Name "ApplicationName" -Value "bropicker"
Set-ItemProperty -Path $caps -Name "ApplicationDescription" -Value "Lightweight link picker: choose which browser opens the URL"
New-Item -Path "$caps\URLAssociations" -Force | Out-Null
Set-ItemProperty -Path "$caps\URLAssociations" -Name "https" -Value "bropicker"
Set-ItemProperty -Path "$caps\URLAssociations" -Name "http" -Value "bropicker"
New-Item -Path $regApps -Force | Out-Null
Set-ItemProperty -Path $regApps -Name "bropicker" -Value "Software\bropicker-Capabilities"
Write-Host "Registered. Now select bropicker for HTTP/HTTPS in the opened Settings window."
Start-Process "ms-settings:defaultapps"