Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 4 additions & 9 deletions src/github.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,9 @@ pub(crate) const CONNECT_TIMEOUT: Duration = Duration::from_secs(10);
/// cannot fire an unbounded burst of requests at the GitHub API at once.
const MAX_CONCURRENT_REPO_FETCHES: usize = 8;

// Storage and download/self-update now live in dedicated modules; re-export
// their public API so existing `github::` call sites keep working unchanged.
pub use crate::download::{apply_launcher_update, download_launcher_asset, download_release_asset};
use crate::persistence::save_repo_doc;
use crate::persistence::save_repo_icon;
pub use crate::persistence::{
colony_apps_dir, colony_data_dir, installed_app_path, load_favorites, load_installed_version,
load_preferences, load_repos_cache, load_scan_cache, read_repo_doc, save_favorites,
save_preferences, save_repos_cache, save_scan_cache, CachedApp, UserPreferences,
};
use crate::persistence::{load_installed_version, load_repos_cache};

// --- HTTP ETag Cache ---

Expand Down Expand Up @@ -909,7 +902,9 @@ pub async fn check_update_available(
pinned_tag.to_string()
};

if target == installed {
// Case-insensitive: "Nightly" vs "nightly" must not read as an update
// (with non-semver tags the string fallback below would flag it forever).
if target.eq_ignore_ascii_case(&installed) {
return None;
}

Expand Down
17 changes: 13 additions & 4 deletions src/i18n.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ impl Locale {
strings.insert("rescan".into(), "Rescan".into());

// GitHub panel
strings.insert("github_connect_desc".into(), "Connectez-vous à GitHub pour détecter les dépôts Colony (colony.json) du compte MotherSphere.".into());
strings.insert("github_connect_desc".into(), "Connectez-vous à GitHub pour détecter les dépôts Colony (colony.json) de l'organisation Project-Colony.".into());
strings.insert("github_login".into(), "Se connecter avec GitHub".into());
strings.insert(
"github_public_api".into(),
Expand Down Expand Up @@ -162,7 +162,7 @@ impl Locale {

// First launch — carousel (3 steps)
strings.insert("welcome_title".into(), "Bienvenue dans Colony".into());
strings.insert("welcome_desc".into(), "Le lanceur centralisé de l'écosystème MotherSphere. Découvrez, installez et lancez vos apps en un clic.".into());
strings.insert("welcome_desc".into(), "Le lanceur centralisé de l'écosystème Project-Colony. Découvrez, installez et lancez vos apps en un clic.".into());
// Step 1 — interface tour
strings.insert(
"welcome_step1_title".into(),
Expand Down Expand Up @@ -701,6 +701,12 @@ impl Locale {
strings.insert("launch_action".into(), "Lancer".into());
strings.insert("section_security".into(), "Sécurité".into());
strings.insert("language_changed".into(), "Langue changée".into());
strings.insert("clear_caches".into(), "Vider les caches du store".into());
strings.insert("clear_caches_desc".into(), "Supprime les descriptions et icônes mises en cache (elles se re-téléchargent au prochain rafraîchissement). Les applications installées ne sont pas touchées.".into());
strings.insert(
"caches_cleared".into(),
"{count} cache(s) supprimé(s)".into(),
);
strings.insert("launcher_update_system_managed".into(), "Mise à jour {version} disponible - cette installation est gérée par le gestionnaire de paquets, mettez à jour via « pacman -Syu » (colony-bin)".into());
// Detail tabs
strings.insert("tab_readme".into(), "ReadMe".into());
Expand All @@ -716,7 +722,7 @@ impl Locale {
strings.insert("rescan".into(), "Rescan".into());

// GitHub panel
strings.insert("github_connect_desc".into(), "Connect to GitHub to detect Colony repos (colony.json) from the MotherSphere account.".into());
strings.insert("github_connect_desc".into(), "Connect to GitHub to detect Colony repos (colony.json) from the Project-Colony organization.".into());
strings.insert("github_login".into(), "Sign in with GitHub".into());
strings.insert(
"github_public_api".into(),
Expand Down Expand Up @@ -844,7 +850,7 @@ impl Locale {

// First launch — carousel (3 steps)
strings.insert("welcome_title".into(), "Welcome to Colony".into());
strings.insert("welcome_desc".into(), "The centralized launcher for the MotherSphere ecosystem. Discover, install and launch apps in one click.".into());
strings.insert("welcome_desc".into(), "The centralized launcher for the Project-Colony ecosystem. Discover, install and launch apps in one click.".into());
// Step 1 — interface tour
strings.insert(
"welcome_step1_title".into(),
Expand Down Expand Up @@ -1337,6 +1343,9 @@ impl Locale {
strings.insert("launch_action".into(), "Launch".into());
strings.insert("section_security".into(), "Security".into());
strings.insert("language_changed".into(), "Language changed".into());
strings.insert("clear_caches".into(), "Clear store caches".into());
strings.insert("clear_caches_desc".into(), "Removes cached descriptions and icons (they re-download on the next refresh). Installed applications are not touched.".into());
strings.insert("caches_cleared".into(), "{count} cache(s) removed".into());
strings.insert("launcher_update_system_managed".into(), "Update {version} is available - this install is managed by the package manager, update via 'pacman -Syu' (colony-bin)".into());
// Detail tabs
strings.insert("tab_readme".into(), "ReadMe".into());
Expand Down
10 changes: 5 additions & 5 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub fn main() -> iced::Result {

// Honor the saved language preference over environment locale detection,
// and reopen at the last persisted window size (clamped to sanity).
let prefs = github::load_preferences();
let prefs = crate::persistence::load_preferences();
i18n::init(prefs.language.clone());
let width = prefs.window_width.unwrap_or(1000.0).clamp(640.0, 7680.0);
let height = prefs.window_height.unwrap_or(700.0).clamp(480.0, 4320.0);
Expand Down Expand Up @@ -67,7 +67,7 @@ fn load_fonts() -> Task<Message> {

impl App {
fn boot() -> (Self, Task<Message>) {
let prefs = github::load_preferences();
let prefs = crate::persistence::load_preferences();

// The filesystem application scan and its cache write are deferred off
// the boot path (dispatched as a Rescan task below) so the window
Expand All @@ -79,7 +79,7 @@ impl App {
// The startup scan is disabled: restore the last scan from cache
// (which was written on every scan but never read back) instead of
// greeting the user with a permanently empty local-apps grid.
github::load_scan_cache()
crate::persistence::load_scan_cache()
.unwrap_or_default()
.into_iter()
.map(|c| scan::Application {
Expand All @@ -106,7 +106,7 @@ impl App {

let font = default_font();

let favorites = github::load_favorites();
let favorites = crate::persistence::load_favorites();

// Determine initial section: if restore_session is on use last section,
// otherwise use default_view to pick "favorites" section if configured.
Expand Down Expand Up @@ -141,7 +141,7 @@ impl App {
// refresh over the network - anonymously when no token is saved (the
// unauthenticated GitHub API allows 60 req/h, plenty for one boot
// fetch). Signing in is optional, exactly as the welcome flow promises.
let colony_repo_list = github::load_repos_cache().unwrap_or_default();
let colony_repo_list = crate::persistence::load_repos_cache().unwrap_or_default();
let startup_task = {
let token = match &github_state {
GitHubState::Connected { session } => Some(session.access_token.clone()),
Expand Down
2 changes: 2 additions & 0 deletions src/message.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ pub enum Message {
FetchReleaseNotes(String),
/// (repo, Ok((tag, body_markdown))) - notes fetched (or failed).
ReleaseNotesFetched(String, Result<(String, String), String>),
/// Manual "clear store caches" from Settings > Storage.
ClearStoreCaches,
WindowResized(f32, f32),
/// Debounced save of the window size (fires 1s after the LAST resize).
PersistWindowSize(u64),
Expand Down
2 changes: 1 addition & 1 deletion src/oauth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ const KEYRING_SERVICE: &str = "colony-launcher";
const KEYRING_USER: &str = "github-oauth";

fn token_path() -> PathBuf {
match crate::github::colony_data_dir() {
match crate::persistence::colony_data_dir() {
Ok(dir) => {
let auth_dir = dir.join("auth");
let _ = std::fs::create_dir_all(&auth_dir);
Expand Down
21 changes: 21 additions & 0 deletions src/persistence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,27 @@ fn desktop_entry_filename(repo_name: &str) -> String {
format!("colony-{}.desktop", repo_name.to_lowercase())
}

/// Remove ALL store caches (docs + icons for every repo). Manual cache
/// management from Settings > Storage; installs and preferences are NOT
/// touched. Returns the number of cache directories removed.
pub fn clear_store_caches() -> usize {
let Ok(base) = colony_data_dir() else {
return 0;
};
let mut removed = 0;
for parent in ["repo-docs", "repo-icons"] {
let Ok(entries) = std::fs::read_dir(base.join(parent)) else {
continue;
};
for entry in entries.flatten() {
if std::fs::remove_dir_all(entry.path()).is_ok() {
removed += 1;
}
}
}
removed
}

/// Remove doc/icon caches for repos that are NO LONGER in the catalog, so a
/// deleted or renamed repo does not leave its caches behind forever. Runs
/// after each successful catalog fetch (never on a cache fallback, where a
Expand Down
2 changes: 1 addition & 1 deletion src/ui/detail.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ impl App {
.align_y(iced::Alignment::End);

// Action row: Launch if installed, Download if not
let installed_path = github::installed_app_path(repo);
let installed_path = crate::persistence::installed_app_path(repo);
let current_platform = github::current_platform_key();

let action_row = if let Some(app_path) = installed_path {
Expand Down
25 changes: 17 additions & 8 deletions src/ui/github_panel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -279,15 +279,24 @@ impl App {
.font(self.app_font_with_weight(Weight::Medium))
.color(Palette::TEXT_PRIMARY());

let card = container(name)
// Clickable: opens the repo's detail page (the panel used to render an
// inert list that duplicated the grid without its function).
button(name)
.on_press(Message::ColonyRepoSelected(repo.name.clone()))
.padding([10, 14])
.width(Fill)
.style(|_theme| container::Style {
background: Some(Palette::BG_CARD().into()),
border: iced::Border::default().rounded(8),
..Default::default()
});

card.into()
.style(|_theme, status| {
let bg = match status {
button::Status::Hovered => Palette::BG_CARD_HOVER(),
_ => Palette::BG_CARD(),
};
button::Style {
background: Some(bg.into()),
text_color: Palette::TEXT_PRIMARY(),
border: iced::Border::default().rounded(8),
..Default::default()
}
})
.into()
}
}
24 changes: 24 additions & 0 deletions src/ui/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,30 @@ impl App {

sections = sections.push(container(text("")).height(6));

// Section: Caches
sections = sections.push(
self.view_collapsible_section(
"caches",
&i18n::t("clear_caches"),
column![
text(i18n::t("clear_caches_desc"))
.size(self.sz(12))
.font(self.app_font())
.color(Palette::TEXT_MUTED()),
container(text("")).height(12),
self.action_button(
"\u{f1f8}",
i18n::t("clear_caches"),
Message::ClearStoreCaches,
),
]
.spacing(0)
.into(),
),
);

sections = sections.push(container(text("")).height(6));

// Section: Installation
let apps_count = self.applications.len().to_string();
let repos_count = self.colony_repos().len().to_string();
Expand Down
Loading