diff --git a/src/setup.rs b/src/setup.rs index 36fdfc1..a6ba418 100644 --- a/src/setup.rs +++ b/src/setup.rs @@ -3,7 +3,7 @@ use anyhow::Result; use iced::widget::{ button, column, container, pick_list, progress_bar, row, scrollable, text, text_input, Column, }; -use iced::{Color, Element, Length, Subscription, Task, Theme}; +use iced::{Alignment, Background, Border, Color, Element, Length, Padding, Subscription, Task, Theme}; use std::ffi::OsString; use std::io::{BufRead, BufReader, Read, Write}; use std::path::{Path, PathBuf}; @@ -352,10 +352,40 @@ fn view(state: &State) -> Element<'_, Message> { view_install(state) } -fn view_picking(state: &State) -> Element<'_, Message> { - let header = text("Add a Launcher").size(24); - let sub = text("Choose a launcher and where to install it.").size(13); +fn section_card<'a>(content: impl Into>) -> Element<'a, Message> { + container(content) + .padding(Padding::from([12, 16])) + .width(Length::Fill) + .style(|theme: &Theme| { + let p = theme.extended_palette(); + container::Style { + background: Some(Background::Color(p.background.weak.color)), + border: Border { + color: p.background.strong.color, + width: 1.0, + radius: 6.0.into(), + }, + ..Default::default() + } + }) + .into() +} +fn view_picking(state: &State) -> Element<'_, Message> { + // ── Header ─────────────────────────────────────────────────────────────── + let header = container( + column![ + text("Add a Launcher").size(26), + text("Choose a launcher and set its install location.").size(13) + .style(|_: &Theme| text::Style { + color: Some(Color::from_rgb(0.6, 0.6, 0.6)), + }), + ] + .spacing(4), + ) + .padding(Padding { top: 24.0, right: 24.0, bottom: 8.0, left: 24.0 }); + + // ── Launcher picker card ────────────────────────────────────────────────── let picker = pick_list( state.template_options.as_slice(), state.selected_template.clone(), @@ -364,7 +394,18 @@ fn view_picking(state: &State) -> Element<'_, Message> { .placeholder("Select a launcher…") .width(Length::Fill); - let prefix_input = text_input("/home/user/Games/battlenet", &state.prefix_input) + let launcher_card = section_card( + column![ + text("Launcher").size(12).style(|_: &Theme| text::Style { + color: Some(Color::from_rgb(0.55, 0.75, 1.0)), + }), + picker, + ] + .spacing(6), + ); + + // ── Install location card ───────────────────────────────────────────────── + let prefix_input = text_input("e.g. /home/user/Games/battlenet", &state.prefix_input) .on_input(Message::PrefixChanged) .padding(8) .width(Length::Fill); @@ -373,30 +414,62 @@ fn view_picking(state: &State) -> Element<'_, Message> { .on_press(Message::BrowsePrefix) .style(button::secondary); + let location_card = section_card( + column![ + text("Install Location").size(12).style(|_: &Theme| text::Style { + color: Some(Color::from_rgb(0.55, 0.75, 1.0)), + }), + row![prefix_input, browse_btn] + .spacing(8) + .align_y(Alignment::Center), + text("The folder where the launcher's Wine prefix will be created.") + .size(11) + .style(|_: &Theme| text::Style { + color: Some(Color::from_rgb(0.45, 0.45, 0.45)), + }), + ] + .spacing(6), + ); + + // ── Status / error ──────────────────────────────────────────────────────── + let status_el: Element = if !state.status.is_empty() { + container( + text(&state.status).size(13).style(|_: &Theme| text::Style { + color: Some(Color::from_rgb(1.0, 0.55, 0.45)), + }), + ) + .padding(Padding::from([6, 0])) + .into() + } else { + text("").into() + }; + + // ── Next button ─────────────────────────────────────────────────────────── let can_confirm = state.selected_template.is_some() && !state.prefix_input.trim().is_empty(); - let confirm_btn = button(text("Next →")) - .on_press_maybe(can_confirm.then_some(Message::ConfirmLauncher)) - .style(button::primary); + let next_btn = container( + button(text("Next →").size(14)) + .on_press_maybe(can_confirm.then_some(Message::ConfirmLauncher)) + .style(button::primary), + ) + .padding(Padding { top: 4.0, right: 0.0, bottom: 0.0, left: 0.0 }) + .width(Length::Fill) + .align_x(Alignment::End); - let mut body = column![ - header, - sub, - text("Launcher:").size(13), - picker, - text("Install location (Wine prefix):").size(13), - row![prefix_input, browse_btn].spacing(8).align_y(iced::Alignment::Center), - confirm_btn, - ] - .spacing(10) - .padding(20); - - if !state.status.is_empty() { - body = body.push(text(state.status.clone()).size(13)); - } - - container(body).into() + container( + column![ + header, + container( + column![launcher_card, location_card, status_el, next_btn] + .spacing(12) + .padding(Padding { top: 8.0, right: 24.0, bottom: 24.0, left: 24.0 }), + ), + ] + ) + .width(Length::Fill) + .height(Length::Fill) + .into() } fn view_install(state: &State) -> Element<'_, Message> {