Android build v1.0.50

This commit is contained in:
Warren H
2026-06-21 00:27:07 -04:00
parent f7b041f86f
commit c1e2c6d8b5
7 changed files with 156 additions and 7 deletions
+66 -3
View File
@@ -1,4 +1,5 @@
import starterProfile from './offline-starter-profile.json'
import { bundledCatalogHash } from './offline-catalog-meta'
import type {
Account,
AuthSession,
@@ -82,6 +83,12 @@ type OnlineCache = {
dirty: boolean
}
type CatalogCache = {
version: 1
hash: string
profile: CharacterProfile
}
export type CloudSyncStatus = {
available: boolean
dirty: boolean
@@ -102,6 +109,8 @@ type LocalSaveStore = {
const modeKey = 'chronicle.repositoryMode'
const offlineSaveKey = 'chronicle.offlineSave.v1'
const onlineCacheKey = 'chronicle.onlineCache.v1'
const catalogCacheKey = 'chronicle.catalog.v1'
const catalogBundleKey = 'chronicle.catalog.bundleHash.v1'
const authTokenKey = 'chronicle.authToken.v1'
const offlineAccount = { id: -1, username: 'Offline' }
const ABILITY_SLOT_COUNT = 6
@@ -281,8 +290,42 @@ function clearOnlineCache() {
localStorage.removeItem(onlineCacheKey)
}
function bundledCatalog(): CatalogCache {
return {
version: 1,
hash: bundledCatalogHash,
profile: starterProfile as CharacterProfile,
}
}
function readCatalogCache(): CatalogCache | null {
if (localStorage.getItem(catalogBundleKey) !== bundledCatalogHash) {
localStorage.removeItem(catalogCacheKey)
localStorage.setItem(catalogBundleKey, bundledCatalogHash)
return null
}
const serialized = localStorage.getItem(catalogCacheKey)
if (!serialized) return null
try {
const raw = JSON.parse(serialized) as CatalogCache
if (raw.version !== 1 || typeof raw.hash !== 'string' || !raw.profile) return null
return raw
} catch {
return null
}
}
function writeCatalogCache(cache: CatalogCache) {
localStorage.setItem(catalogBundleKey, bundledCatalogHash)
localStorage.setItem(catalogCacheKey, JSON.stringify(cache))
}
function activeCatalog(): CatalogCache {
return readCatalogCache() ?? bundledCatalog()
}
function buildProfile(save: OfflineSave): CharacterProfile {
const static_ = clone(starterProfile) as CharacterProfile
const static_ = clone(activeCatalog().profile)
const cd = save.characters[save.activeClassId]
const gameClass = static_.classes.find((c) => c.id === save.activeClassId)!
@@ -657,6 +700,23 @@ function isNetworkError(reason: unknown): reason is NetworkError {
return reason instanceof Error && Boolean((reason as NetworkError).network)
}
async function loadServerCatalog(): Promise<CatalogCache> {
return requestJson('/api/catalog')
}
async function refreshCatalogFromServer(): Promise<CatalogCache | null> {
try {
const catalog = await loadServerCatalog()
if (catalog.version !== 1 || !catalog.hash || !catalog.profile) return null
if (catalog.hash !== activeCatalog().hash || !readCatalogCache()) {
writeCatalogCache(catalog)
}
return catalog
} catch {
return null
}
}
function cachedOnlineSession(): AuthSession | null {
const cache = readOnlineCache()
if (!cache) return null
@@ -698,6 +758,7 @@ async function pushServerSyncSave(save: OfflineSave): Promise<{ profile: Charact
async function finalizeOnlineSession(session: AuthSession): Promise<AuthSession> {
const cache = readOnlineCache()
if (session.token) writeAuthToken(session.token)
await refreshCatalogFromServer()
if (!session.account || !session.profile) {
if (session.account && cache?.account.id === session.account.id) {
return {
@@ -848,7 +909,7 @@ const serverRepository: GameRepository = {
}
function emptyCharacterData(classId: number): CharacterData {
const static_ = clone(starterProfile) as CharacterProfile
const static_ = clone(activeCatalog().profile)
const gc = static_.classes.find((c) => c.id === classId)!
const talentRanks: Record<string, number> = {}
for (const t of gc.talents) talentRanks[String(t.id)] = 0
@@ -1544,7 +1605,9 @@ export async function syncCloudSave(): Promise<CharacterProfile> {
if (!cache) {
throw new Error('No signed-in save is available for cloud sync.')
}
await refreshCatalogFromServer()
const synced = await pushServerSyncSave(cache.save)
await refreshCatalogFromServer()
writeOnlineCache({
version: 1,
account: cache.account,
@@ -1552,7 +1615,7 @@ export async function syncCloudSave(): Promise<CharacterProfile> {
dirty: false,
})
writeMode('online')
return synced.profile
return buildProfile(synced.save)
}
export function selectOnlineMode() {
+1
View File
@@ -0,0 +1 @@
export const bundledCatalogHash = '07506c52bab428c439f09a9b82e39e6eff2b243fb972d664da48852059bcd937'