OneLauncher-Cracked/packages/oneclient_app/src/view/relocating.rs

177 lines
5.5 KiB
Rust

use freya::prelude::*;
use freya::router::RouterContext;
use oneclient_core::relocate::{RelocationOutcome, RelocationPlan};
use oneclient_core::storage::format_bytes;
use crate::Route;
use crate::components::{Button, Icon, IconType, progress_track};
use crate::hooks::{Actions, use_dispatch, use_relocation};
use crate::theme::colors;
use crate::ui::{note, path_block};
use crate::utils::plural;
#[derive(PartialEq)]
pub struct Relocating;
impl Component for Relocating {
fn render(&self) -> impl IntoElement {
let relocation = use_relocation();
let actions = use_dispatch();
let Some(plan) = relocation.plan.clone() else {
// Landed here without a move in flight
let _ = RouterContext::get().replace(Route::SettingsLauncher {});
return rect().into_element();
};
let content = match &relocation.result {
None => copying(&plan, relocation.copied, relocation.total),
Some(Ok(outcome)) => moved(outcome, actions),
Some(Err(message)) => failed(message.clone(), actions),
};
rect()
.width(Size::fill())
.height(Size::fill())
.center()
.background(colors::page())
.window_drag()
.child(content)
.into_element()
}
}
fn copying(plan: &RelocationPlan, copied: u64, total: u64) -> Element {
// The plan's estimate stands in until the copy has counted the tree itself
let total = if total > 0 { total } else { plan.bytes }.max(1);
screen()
.child(heading(IconType::FolderDownload, "Moving your data folder", colors::fg_primary()))
.child(path_block("From", &plan.from))
.child(path_block("To", &plan.to))
.child(progress_track(
copied as f32 / total as f32 * 100.,
6.,
colors::brand(),
colors::component_bg(),
))
.child(
label()
.text(format!(
"{} of {}",
format_bytes(copied),
format_bytes(total)
))
.font_size(12.)
.color(colors::fg_secondary()),
)
.child(note(
"Leave OneClient open until this finishes. Nothing is removed from the old folder, \
and the launcher stays closed to everything else while files are copied."
.to_string(),
colors::brand(),
))
.into_element()
}
fn moved(outcome: &RelocationOutcome, actions: Actions) -> Element {
let mut body = format!(
"{} copied to {}. OneClient keeps running from the old folder until you restart it.",
format_bytes(outcome.bytes),
outcome.to.display()
);
if outcome.skipped_links > 0 {
body.push_str(&format!(
" {} shortcut{} pointing outside the folder were left behind.",
outcome.skipped_links,
plural(outcome.skipped_links as i64)
));
}
screen()
.child(heading(IconType::FolderCheck, "Game data moved", colors::brand()))
.child(note(body, colors::brand()))
.child(
label()
.text(
"The old copy is still there. Once you have restarted, Launcher Settings can \
remove it.",
)
.font_size(12.)
.max_lines(3)
.color(colors::fg_secondary()),
)
.child(
buttons()
.child(back_button(actions))
.child(
Button::new()
.primary()
.on_press(|_| {
let platform = Platform::get();
Platform::get().with_window(Platform::window_id(), move |window| {
platform.close_window(window.id());
});
})
.text("Quit OneClient"),
),
)
.into_element()
}
fn failed(message: String, actions: Actions) -> Element {
screen()
.child(heading(IconType::AlertTriangle, "The move didn't finish", colors::danger()))
.child(note(message, colors::danger()))
.child(
label()
.text("Nothing was changed. OneClient is still running from its current folder.")
.font_size(12.)
.max_lines(2)
.color(colors::fg_secondary()),
)
.child(buttons().child(back_button(actions)))
.into_element()
}
fn back_button(actions: Actions) -> Button {
Button::new()
.secondary()
.on_press(move |_| {
actions.end_relocation();
let _ = RouterContext::get().replace(Route::SettingsLauncher {});
})
.text("Back to settings")
}
fn screen() -> Rect {
rect()
.vertical()
.width(Size::px(460.))
.max_width(Size::window_percent(90.))
.spacing(14.)
}
fn heading(icon: IconType, title: &'static str, tint: Color) -> impl IntoElement {
rect()
.horizontal()
.cross_align(Alignment::Center)
.spacing(10.)
.child(Icon::new(icon).size(20.).color(tint))
.child(
label()
.text(title)
.font_size(18.)
.font_weight(FontWeight::SEMI_BOLD)
.color(colors::fg_primary()),
)
}
fn buttons() -> Rect {
rect()
.horizontal()
.width(Size::fill())
.main_align(Alignment::End)
.spacing(8.)
}