Skip to content

Commit ad35806

Browse files
fix: allow starting offline
1 parent 48dd0d2 commit ad35806

File tree

4 files changed

+84
-12
lines changed

4 files changed

+84
-12
lines changed

resources/dist.rc

2.12 MB
Binary file not shown.

src/celemod-ui/src/context/modManage.tsx

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ import {
88
useCurrentEverestVersion,
99
initModComments,
1010
} from '../states';
11-
import { useEffect, useMemo } from 'preact/hooks';
12-
import { createPopup } from 'src/components/Popup';
11+
import { useEffect, useMemo, useContext } from 'preact/hooks';
12+
import { createPopup, PopupContext } from 'src/components/Popup';
1313
import { Fragment, h } from 'preact';
1414
import { ProgressIndicator } from 'src/components/Progress';
1515

1616
let lastGamePath = '';
1717
export const createModManageContext = () => {
1818
initModComments();
19-
19+
2020
const { setInstalledMods } = useInstalledMods();
2121

2222
const [gamePath] = useGamePath();
@@ -80,16 +80,36 @@ export const createModManageContext = () => {
8080
);
8181
ctx
8282
.reloadMods()
83-
.then(() => popup.hide())
83+
.then((mods) => {
84+
popup.hide();
85+
const is_using_cache = callRemote('is_using_cache');
86+
if (is_using_cache)
87+
createPopup(() => {
88+
const { hide } = useContext(PopupContext);
89+
return (
90+
<div className="popup-content">
91+
<div className="title">{_i18n.t('离线模式')}</div>
92+
<div className="content">{_i18n.t('正在使用缓存的 Mod 数据,可能已过期或不完整')}</div>
93+
<div className="buttons">
94+
<button onClick={hide}>{_i18n.t('确定')}</button>
95+
</div>
96+
</div>
97+
);
98+
});
99+
})
84100
.catch((e) => {
85101
popup.hide();
86-
createPopup(() => {
102+
const p = createPopup(() => {
87103
return (
88-
<div className="loading-popup">
89-
<h1>{_i18n.t('加载 Mod 列表失败')}</h1>
90-
<p>{_i18n.t('请检查游戏路径是否正确,或网络连接是否正常')}</p>
91-
<p>{_i18n.t('部分功能将不可用')}</p>
92-
<p>{e}</p>
104+
<div className="popup-content">
105+
<div className="title">{_i18n.t('加载 Mod 列表失败')}</div> <div className="content">
106+
<p>{_i18n.t('请检查游戏路径是否正确,或网络连接是否正常')}</p>
107+
<p>{_i18n.t('部分功能将不可用')}</p>
108+
<p>{e}</p></div><div className="buttons">
109+
<button onClick={() => {
110+
p.hide()
111+
}}>{_i18n.t('确定')}</button>
112+
</div>
93113
</div>
94114
);
95115
});

src/everest.rs

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::{
88
io::{BufRead, BufReader},
99
path::{Path, PathBuf},
1010
process::{Command, Stdio},
11-
sync::Arc,
11+
sync::{atomic::AtomicBool, Arc},
1212
};
1313

1414
#[derive(Serialize, Deserialize)]
@@ -21,20 +21,60 @@ pub struct ModInfoCached {
2121
pub download_url: String,
2222
}
2323

24+
static USING_CACHE: AtomicBool = AtomicBool::new(false);
25+
26+
pub fn is_using_cache() -> bool {
27+
USING_CACHE.load(std::sync::atomic::Ordering::Relaxed)
28+
}
29+
2430
lazy_static! {
2531
static ref MOD_INFO_CACHED: Arc<HashMap<String, ModInfoCached>> = {
26-
let mods = get_mod_online_wegfan().unwrap();
32+
let mods = match get_mod_online_wegfan() {
33+
Ok(fetched) => {
34+
save_mod_cache(&fetched);
35+
USING_CACHE.store(false, std::sync::atomic::Ordering::Relaxed);
36+
fetched
37+
}
38+
Err(e) => {
39+
eprintln!("Failed to fetch mod list: {}", e);
40+
if let Some(cached) = load_mod_cache() {
41+
println!("Using cached mod list");
42+
USING_CACHE.store(true, std::sync::atomic::Ordering::Relaxed);
43+
cached
44+
} else {
45+
eprintln!("No cache available");
46+
USING_CACHE.store(false, std::sync::atomic::Ordering::Relaxed);
47+
vec![]
48+
}
49+
}
50+
};
2751
let mods = mods.into_iter().map(|v| (v.name.clone(), v)).collect();
2852
Arc::new(mods)
2953
};
3054
}
3155

56+
fn load_mod_cache() -> Option<Vec<ModInfoCached>> {
57+
let cache_path = std::env::current_dir().ok()?.join("mod_cache.json");
58+
let data = std::fs::read_to_string(cache_path).ok()?;
59+
serde_json::from_str(&data).ok()
60+
}
61+
62+
fn save_mod_cache(mods: &[ModInfoCached]) {
63+
if let Ok(dir) = std::env::current_dir() {
64+
let cache_path = dir.join("mod_cache.json");
65+
if let Ok(data) = serde_json::to_string(mods) {
66+
let _ = std::fs::write(cache_path, data);
67+
}
68+
}
69+
}
70+
3271
pub fn get_mod_online_wegfan() -> anyhow::Result<Vec<ModInfoCached>> {
3372
let mut response: serde_json::Value = ureq::get("https://celeste.weg.fan/api/v2/mod/list")
3473
.set(
3574
"User-Agent",
3675
&format!("CeleMod/{}-{}", env!("VERSION"), &env!("GIT_HASH")[..6]),
3776
)
77+
.timeout(std::time::Duration::from_secs(20))
3878
.set("Accept-Encoding", "gzip, deflate, br")
3979
.call()?
4080
.into_json()?;

src/main.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,6 +667,10 @@ impl Handler {
667667
}
668668
}
669669

670+
fn is_using_cache(&self) -> bool {
671+
everest::is_using_cache()
672+
}
673+
670674
fn sync_blacklist_profile_from_file(&self, game_path: String, profile_name: String) -> String {
671675
let result = blacklist::sync_blacklist_profile_from_file(&game_path, &profile_name);
672676
if let Err(e) = result {
@@ -869,6 +873,7 @@ impl sciter::EventHandler for Handler {
869873
fn show_log_window();
870874
fn get_current_blacklist_content(String);
871875
fn sync_blacklist_profile_from_file(String, String);
876+
fn is_using_cache();
872877
}
873878
}
874879

@@ -888,6 +893,13 @@ fn main() {
888893
return;
889894
}
890895

896+
// set cwd to exe directory
897+
if let Ok(exe) = std::env::current_exe() {
898+
if let Some(dir) = exe.parent() {
899+
std::env::set_current_dir(dir).unwrap();
900+
}
901+
}
902+
891903
println!("CeleMod v{} ({})", env!("VERSION"), env!("GIT_HASH"));
892904

893905
// windows only

0 commit comments

Comments
 (0)