feat: add way to select game dir

This commit is contained in:
lucasdpt
2026-06-17 20:43:27 +02:00
parent b8204c80bd
commit 161ea50234
7 changed files with 212 additions and 18 deletions
+75 -6
View File
@@ -5,7 +5,8 @@ import type {
GameLogLine,
DeviceCodeInfo,
UpdateStatus,
PackMeta
PackMeta,
DataDirInfo
} from '../../shared/ipc'
/** Découpe une chaîne d'args JVM en tableau (espaces, vides ignorés). */
@@ -13,7 +14,7 @@ function parseArgs(s: string): string[] {
return s.split(/\s+/).filter(Boolean)
}
type Status = 'loading' | 'logged-out' | 'logged-in' | 'working' | 'running'
type Status = 'loading' | 'setup' | 'logged-out' | 'logged-in' | 'working' | 'running'
export default function App(): JSX.Element {
const [status, setStatus] = useState<Status>('loading')
@@ -27,23 +28,34 @@ export default function App(): JSX.Element {
const [appVersion, setAppVersion] = useState('')
const [update, setUpdate] = useState<UpdateStatus | null>(null)
const [pack, setPack] = useState<PackMeta | null>(null)
const [dataDir, setDataDir] = useState<DataDirInfo | null>(null)
const [setupDir, setSetupDir] = useState('')
const consoleRef = useRef<HTMLDivElement>(null)
// Restaure la session + réglages au démarrage.
useEffect(() => {
;(async () => {
const [p, s, v] = await Promise.all([
window.api.getProfile(),
const [firstLaunch, dirInfo, s, v] = await Promise.all([
window.api.isFirstLaunch(),
window.api.getDataDir(),
window.api.getSettings(),
window.api.getAppVersion()
])
setDataDir(dirInfo)
setMaxMemoryMb(s.maxMemoryMb)
setJvmArgs(s.extraJvmArgs.join(' '))
setAppVersion(v)
if (firstLaunch) {
setSetupDir(dirInfo.defaultSuggestion)
setStatus('setup')
return
}
const p = await window.api.getProfile()
setProfile(p)
setStatus(p ? 'logged-in' : 'logged-out')
})()
// Récupère le nom/version réels du pack (tolérant au offline).
void window.api.getPackMeta().then((m) => m && setPack(m))
}, [])
@@ -129,6 +141,30 @@ export default function App(): JSX.Element {
}
}
async function handleSetupBrowse(): Promise<void> {
const picked = await window.api.browseDataDir()
if (picked) setSetupDir(picked)
}
async function handleSetupConfirm(): Promise<void> {
const dir = setupDir.trim()
if (!dir) return
await window.api.setDataDir(dir, false)
const updated = await window.api.getDataDir()
setDataDir(updated)
const p = await window.api.getProfile()
setProfile(p)
setStatus(p ? 'logged-in' : 'logged-out')
}
async function handleChangeDataDir(): Promise<void> {
const picked = await window.api.browseDataDir()
if (!picked) return
// Relaunch = true : les fichiers existants restent dans l'ancien dossier,
// le launcher redémarre et tout se retélécharge dans le nouveau.
await window.api.setDataDir(picked, true)
}
if (status === 'loading') {
return (
<div className="app">
@@ -137,6 +173,36 @@ export default function App(): JSX.Element {
)
}
if (status === 'setup') {
return (
<div className="app">
<div className="center setup">
<h1>OFLauncher</h1>
<p className="muted">Bienvenue ! Choisis seront stockés les fichiers du jeu.</p>
<p className="muted" style={{ fontSize: 12 }}>
Minecraft, Java, mods et sauvegardes iront dans ce dossier.
</p>
<div className="datadir-row">
<input
type="text"
className="datadir-input"
value={setupDir}
onChange={(e) => setSetupDir(e.target.value)}
spellCheck={false}
/>
<button className="linkbtn" onClick={() => void handleSetupBrowse()}>
Parcourir
</button>
</div>
<button className="play" onClick={() => void handleSetupConfirm()} disabled={!setupDir.trim()}>
Continuer
</button>
<div className="muted" style={{ fontSize: 12 }}>v{appVersion}</div>
</div>
</div>
)
}
if (status === 'logged-out') {
return (
<div className="app">
@@ -157,7 +223,7 @@ export default function App(): JSX.Element {
</p>
<div className="code">{authCode.userCode}</div>
<p className="muted" style={{ fontSize: 12 }}>
La page sest ouverte dans ton navigateur. Reviens ici une fois connecté.
La page s'est ouverte dans ton navigateur. Reviens ici une fois connecté.
</p>
</div>
)}
@@ -258,6 +324,9 @@ export default function App(): JSX.Element {
<button className="linkbtn" onClick={handleOpenLogs}>
Ouvrir les logs
</button>
<button className="linkbtn" onClick={() => void handleChangeDataDir()} disabled={busy} title={dataDir?.current}>
Dossier de données
</button>
</div>
{status === 'running' ? (
+24
View File
@@ -283,3 +283,27 @@ button.play.stop:hover:not(:disabled) {
display: inline-block;
user-select: all;
}
.setup {
max-width: 560px;
margin: 0 auto;
text-align: center;
}
.datadir-row {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
}
.datadir-input {
flex: 1;
background: var(--bg-soft);
border: 1px solid var(--border);
color: var(--text);
border-radius: 6px;
padding: 8px 10px;
font-size: 13px;
font-family: 'Cascadia Code', 'Consolas', monospace;
}