diff --git a/play.pokemonshowdown.com/src/client-main.ts b/play.pokemonshowdown.com/src/client-main.ts index ced0867a9..b857e0d59 100644 --- a/play.pokemonshowdown.com/src/client-main.ts +++ b/play.pokemonshowdown.com/src/client-main.ts @@ -163,6 +163,10 @@ class PSPrefs extends PSStreamModel { highlights: Record | null = null; logtimes: { [serverid: ID]: { [roomid: RoomID]: number } } | null = null; + avatar: string | null = null; + + serversettings: Record | null = null; + // PREFS END HERE storageEngine: 'localStorage' | 'iframeLocalStorage' | '' = ''; @@ -200,6 +204,25 @@ class PSPrefs extends PSStreamModel { this.update(key); this.save(); } + /** + * change multiple preferences with a single localstorage write. + */ + setMany(updates: { [key: string]: any }) { + for (const key in updates) { + if (!(key in PSPrefsDefaults)) continue; + const value = updates[key]; + if (value === undefined) continue; + if (value === null) { + delete this.storage[key]; + (this as any)[key] = PSPrefsDefaults[key]; + } else { + this.storage[key] = value; + (this as any)[key] = value; + } + this.update(key); + } + this.save(); + } load(newPrefs: object, noSave?: boolean) { this.fixPrefs(newPrefs); @@ -1312,6 +1335,7 @@ export class PSRoom extends PSStreamModel implements RoomOptions { if (/[^a-z0-9-]/.test(target)) target = toID(target); const avatar = window.BattleAvatarNumbers?.[target] || target; PS.user.avatar = avatar; + PS.prefs.set('avatar', String(avatar)); if (this.type !== 'chat' && this.type !== 'battle') { PS.send(`/avatar ${avatar}`); } else { diff --git a/play.pokemonshowdown.com/src/panel-mainmenu.tsx b/play.pokemonshowdown.com/src/panel-mainmenu.tsx index 142ac3da0..d4946bd10 100644 --- a/play.pokemonshowdown.com/src/panel-mainmenu.tsx +++ b/play.pokemonshowdown.com/src/panel-mainmenu.tsx @@ -125,6 +125,10 @@ export class MainMenuRoom extends PSRoom { case 'challstr': { const [, challstr] = args; PS.user.challstr = challstr; + if (PS.prefs.avatar != null) { + const avatar = String(PS.prefs.avatar).toLowerCase().replace(/[^a-z0-9-]/g, '').slice(0, 64); + if (avatar) PS.send(`/avatar ${avatar},1`); + } PSLoginServer.query( 'upkeep', { challstr } ).then(res => { @@ -141,10 +145,29 @@ export class MainMenuRoom extends PSRoom { }); return; } case 'updateuser': { - const [, fullName, namedCode, avatar] = args; + const [, fullName, namedCode, avatar, settingsJSON] = args; const named = namedCode === '1'; if (named) PS.user.initializing = false; PS.user.setName(fullName, named, avatar); + if (settingsJSON) { + try { + const settings = JSON.parse(settingsJSON); + if (settings && typeof settings === 'object' && !Array.isArray(settings)) { + const existing = PS.prefs.serversettings; + const merged = { + ...(existing && typeof existing === 'object' && !Array.isArray(existing) ? existing : {}), + ...settings, + }; + const batch: { [key: string]: any } = { serversettings: merged }; + if ('blockPMs' in settings) batch.blockPMs = settings.blockPMs == null ? null : Boolean(settings.blockPMs); + if ('blockChallenges' in settings) { + batch.blockChallenges = settings.blockChallenges == null ? null : Boolean(settings.blockChallenges); + } + if (typeof settings.language === 'string') batch.language = settings.language; + PS.prefs.setMany(batch); + } + } catch {} + } PS.teams.loadRemoteTeams(); return; } case 'updatechallenges': {