gui: transition to tray on close, auto-download official installers in setup

This commit is contained in:
funman300
2026-04-19 00:36:22 -07:00
parent f645b58470
commit 20509fb488
3 changed files with 40 additions and 44 deletions
+7 -7
View File
@@ -12,7 +12,7 @@
pkgname=umutray
pkgver=0.1.0
pkgrel=2
pkgrel=4
pkgdesc='Tray-based Wine launcher manager for Linux via umu/Proton-GE'
arch=('x86_64')
url='https://git.aleshym.co/funman300/umutray'
@@ -48,13 +48,13 @@ build() {
package() {
cd "$pkgname"
# Binary
install -Dm755 target/release/umutray "$pkgdir/usr/bin/umutray"
# Binary — install to ~/.local/bin for user-local usage
install -Dm755 target/release/umutray "${HOME}/.local/bin/umutray"
# App menu entry (.desktop uses /usr/bin/umutray as the exec path)
install -Dm644 umutray.desktop "$pkgdir/usr/share/applications/umutray.desktop"
sed -i "s|Exec=umutray|Exec=/usr/bin/umutray|" \
"$pkgdir/usr/share/applications/umutray.desktop"
# App menu entry for the current user
install -Dm644 umutray.desktop "${HOME}/.local/share/applications/umutray.desktop"
sed -i "s|Exec=umutray|Exec=${HOME}/.local/bin/umutray|" \
"${HOME}/.local/share/applications/umutray.desktop"
# License
install -Dm644 LICENSE "$pkgdir/usr/share/licenses/$pkgname/LICENSE"
+6 -1
View File
@@ -321,7 +321,12 @@ fn main() -> Result<()> {
}
},
Commands::Gui => gui::run(&config)?,
Commands::Gui => {
gui::run(&config)?;
// After the GUI window closes, continue into the system tray.
let config = config::Config::load().unwrap_or(config);
tray::run(&config)?;
}
Commands::Detect { dir, apply } => {
detect::run(&config, &dir, apply)?;
+27 -36
View File
@@ -171,16 +171,31 @@ fn update(state: &mut State, message: Message) -> Task<Message> {
preset.prefix_dir = PathBuf::from(&prefix);
// If we know the official installer URL, pre-fill source and
// let the user confirm before downloading.
// start the download automatically.
if let Some(url) = preset.installer_url.clone() {
state.source = url;
state.stage = Stage::Idle;
state.status = format!(
"Ready to download the official {} installer. Press Download → to begin.",
preset.display
);
state.source = url.clone();
state.launcher = Some(preset);
return Task::none();
state.stage = Stage::Busy;
let display_name = state
.launcher
.as_ref()
.map(|l| l.display.clone())
.unwrap_or_else(|| "installer".to_string());
state.status = format!("Downloading {} installer…", display_name);
if let Ok(mut p) = state.download.lock() {
*p = DownloadProgress::default();
}
let name = state
.launcher
.as_ref()
.expect("launcher set")
.name
.clone();
let progress = state.download.clone();
return Task::perform(
async_blocking(move || download_blocking(&url, &name, progress)),
Message::PrepareDone,
);
}
state.status = format!(
@@ -583,32 +598,9 @@ fn view_install(state: &State) -> Element<'_, Message> {
]
.align_y(Alignment::Start);
// ── Source / installer card (only shown in Idle) ───────────────────────────
let source_card: Element<Message> = if matches!(state.stage, Stage::Idle) {
let inner: Element<Message> = if is_official {
column![
text("Installer").size(12).style(|_: &Theme| text::Style {
color: Some(Color::from_rgb(0.55, 0.75, 1.0)),
}),
row![
text("✓ Official installer").size(13).style(|_: &Theme| text::Style {
color: Some(Color::from_rgb(0.35, 0.85, 0.45)),
}),
iced::widget::horizontal_space(),
]
.align_y(Alignment::Center),
text("Using the official download. To use a different installer, paste a URL or path below.")
.size(11)
.style(|_: &Theme| text::Style { color: Some(Color::from_rgb(0.45, 0.45, 0.45)) }),
text_input("Custom URL or local .exe path (optional)", &state.source)
.on_input(Message::SourceChanged)
.padding(7)
.size(12),
]
.spacing(6)
.into()
} else {
column![
// ── Source / installer card (only shown in Idle, for custom URLs) ────────
let source_card: Element<Message> = if matches!(state.stage, Stage::Idle) && !is_official {
let inner: Element<Message> = column![
text("Installer").size(12).style(|_: &Theme| text::Style {
color: Some(Color::from_rgb(0.55, 0.75, 1.0)),
}),
@@ -617,8 +609,7 @@ fn view_install(state: &State) -> Element<'_, Message> {
.padding(8),
]
.spacing(6)
.into()
};
.into();
section_card(inner)
} else {
text("").into()