diff --git a/Synergism.css b/Synergism.css index 9a381b75c..e170d65e9 100644 --- a/Synergism.css +++ b/Synergism.css @@ -1834,7 +1834,6 @@ p#reincarnatehotkeys { display: flex; flex-direction: row; justify-content: center; - flex-flow: wrap; gap: 10px 15px; margin: 15px 0; } diff --git a/package.json b/package.json index 919689051..21609be40 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,7 @@ "description": "", "main": "dist/bundle.js", "dependencies": { + "@discord/embedded-app-sdk": "^1.4.3", "@ungap/custom-elements": "^1.3.0", "break_infinity.js": "^2.0.0", "clipboard": "^2.0.11", diff --git a/src/EventListeners.ts b/src/EventListeners.ts index 0c7634fd0..1945d5f31 100644 --- a/src/EventListeners.ts +++ b/src/EventListeners.ts @@ -53,6 +53,7 @@ import { promocodesPrompt, reloadDeleteGame, resetGame, + safeLocalStorage, updateSaveString } from './ImportExport' import { buyPlatonicUpgrades, createPlatonicDescription } from './Platonic' @@ -1108,7 +1109,7 @@ TODO: Fix this entire tab it's utter shit const element = event.target as HTMLInputElement if (!element.checked) { - localStorage.removeItem('copyToClipboard') + safeLocalStorage.removeItem('copyToClipboard') event.stopPropagation() return } @@ -1119,9 +1120,9 @@ TODO: Fix this entire tab it's utter shit if (confirmed) { element.checked = !element.checked - localStorage.setItem('copyToClipboard', '') + safeLocalStorage.setItem('copyToClipboard', '') } else { - localStorage.removeItem('copyToClipboard') + safeLocalStorage.removeItem('copyToClipboard') } }) diff --git a/src/ImportExport.ts b/src/ImportExport.ts index 27b8bd7ff..533f9c3de 100644 --- a/src/ImportExport.ts +++ b/src/ImportExport.ts @@ -246,8 +246,7 @@ export const exportSynergism = async ( : 1 if (+player.singularityUpgrades.goldenQuarks3.getEffect().bonus > 0) { player.goldenQuarks += Math.floor( - player.goldenQuarksTimer - / (3600 / +player.singularityUpgrades.goldenQuarks3.getEffect().bonus) + player.goldenQuarksTimer / (3600 / +player.singularityUpgrades.goldenQuarks3.getEffect().bonus) ) * bonusGQMultiplier player.goldenQuarksTimer = player.goldenQuarksTimer % (3600 / +player.singularityUpgrades.goldenQuarks3.getEffect().bonus) @@ -264,11 +263,9 @@ export const exportSynergism = async ( return } - const save = (await localforage.getItem('Synergysave2')) - ?? localStorage.getItem('Synergysave2') - const saveString = typeof save === 'string' ? save : await save?.text() + const saveString = await getSaveString() - if (saveString === undefined) { + if (saveString === null) { return Alert('How?') } @@ -357,11 +354,8 @@ export const importSynergism = async (input: string | null, reset = false) => { } saveCheck.canSave = false - const item = new Blob([saveString], { type: 'text/plain' }) - localStorage.setItem('Synergysave2', saveString) - await localforage.setItem('Synergysave2', item) - - localStorage.setItem('saveScumIsCheating', Date.now().toString()) + await setSave(saveString) + safeLocalStorage.setItem('saveScumIsCheating', Date.now().toString()) await reloadShit(reset) saveCheck.canSave = true @@ -852,11 +846,11 @@ export const promocodes = async (input: string | null, amount?: number) => { } else if (input === 'gamble') { if ( typeof player.skillCode === 'number' - || typeof localStorage.getItem('saveScumIsCheating') === 'string' + || typeof safeLocalStorage.getItem('saveScumIsCheating') === 'string' ) { if ( (Date.now() - player.skillCode!) / 1000 < 3600 - || (Date.now() - Number(localStorage.getItem('saveScumIsCheating'))) + || (Date.now() - Number(safeLocalStorage.getItem('saveScumIsCheating'))) / 1000 < 3600 ) { @@ -890,7 +884,7 @@ export const promocodes = async (input: string | null, amount?: number) => { )) } - localStorage.setItem('saveScumIsCheating', Date.now().toString()) + safeLocalStorage.setItem('saveScumIsCheating', Date.now().toString()) const dice = (window.crypto.getRandomValues(new Uint8Array(1))[0] % 6) + 1 // [1, 6] if (dice === 1) { @@ -1236,11 +1230,11 @@ const dailyCodeReward = () => { } export const handleLastModified = (lastModified: number) => { - const localStorageFirstPlayed = localStorage.getItem('firstPlayed') + const localStorageFirstPlayed = safeLocalStorage.getItem('firstPlayed') const lastModifiedDate = new Date(lastModified) if (localStorageFirstPlayed === null) { - localStorage.setItem('firstPlayed', lastModifiedDate.toISOString()) + safeLocalStorage.setItem('firstPlayed', lastModifiedDate.toISOString()) return } @@ -1251,6 +1245,66 @@ export const handleLastModified = (lastModified: number) => { // for the new file, set the oldest date to the last modified. if (localFirstPlayedDate.getTime() > lastModifiedDate.getTime()) { player.firstPlayed = lastModifiedDate.toISOString() - localStorage.setItem('firstPlayed', player.firstPlayed) + safeLocalStorage.setItem('firstPlayed', player.firstPlayed) + } +} + +export const getSaveString = async () => { + try { + const save = (await localforage.getItem('Synergysave2')) + ?? localStorage.getItem('Synergysave2') + + return typeof save === 'string' ? save : await save?.text() ?? null + } catch (e) { + const p = playerJsonSchema.parse(player) + return btoa(JSON.stringify(p)) + } +} + +export const setSave = async (saveString: string) => { + try { + const item = new Blob([saveString], { type: 'text/plain' }) + localStorage.setItem('Synergysave2', saveString) + await localforage.setItem('Synergysave2', item) + } catch {} +} + +export const safeLocalStorage = { + /** + * Same as localStorage.setItem, but errors are swallowed + */ + setItem (key: string, value: string) { + try { + localStorage.setItem(key, value) + } catch {} + }, + + /** + * Same as localStorage.removeItem, but errors are swallowed + */ + removeItem (key: string) { + try { + localStorage.removeItem(key) + } catch {} + }, + + /** + * Same as localStorage.getItem, but errors are swallowed + */ + getItem (key: string) { + try { + return localStorage.getItem(key) + } catch { + return null + } + }, + + /** + * Same as localStorage.clear, but errors are swallowed + */ + clear () { + try { + localStorage.clear() + } catch {} } } diff --git a/src/Login.ts b/src/Login.ts index 335d7df03..f246ada49 100644 --- a/src/Login.ts +++ b/src/Login.ts @@ -1,7 +1,6 @@ import i18next from 'i18next' -import localforage from 'localforage' import { DOMCacheGetOrSet } from './Cache/DOM' -import { importSynergism } from './ImportExport' +import { getSaveString, importSynergism } from './ImportExport' import { QuarkHandler, setQuarkBonus } from './Quark' import { player } from './Synergism' import { Alert } from './UpdateHTML' @@ -218,11 +217,9 @@ async function logout () { } async function saveToCloud () { - const save = (await localforage.getItem('Synergysave2') - .then((b) => b?.text()) - .catch(() => null)) ?? localStorage.getItem('Synergysave2') + const save = await getSaveString() - if (typeof save !== 'string') { + if (save === null) { console.log('Yeah, no save here.') return } diff --git a/src/Synergism.ts b/src/Synergism.ts index 7b06d47ef..200a23a60 100644 --- a/src/Synergism.ts +++ b/src/Synergism.ts @@ -135,7 +135,6 @@ import { // import { LegacyShopUpgrades } from './types/LegacySynergism'; import i18next from 'i18next' -import localforage from 'localforage' import { BlueberryUpgrade, blueberryUpgradeData, updateLoadoutHoverClasses } from './BlueberryUpgrades' import { DOMCacheGetOrSet } from './Cache/DOM' import { lastUpdated, prod, testing, version } from './Config' @@ -174,6 +173,8 @@ import { changeSubTab, changeTab, Tabs } from './Tabs' import { settingAnnotation, toggleIconSet, toggleTheme } from './Themes' import { clearTimeout, clearTimers, setInterval, setTimeout } from './Timers' import type { PlayerSave } from './types/LegacySynergism' +import { getSaveString, safeLocalStorage, setSave } from './ImportExport' +import { patchUrlMappings } from '@discord/embedded-app-sdk' export const player: Player = { firstPlayed: new Date().toISOString(), @@ -1515,15 +1516,12 @@ export const saveSynergy = async (button?: boolean): Promise => { const save = btoa(JSON.stringify(p)) if (save !== null) { - const saveBlob = new Blob([save], { type: 'text/plain' }) - // Should prevent overwritting of localforage that is currently used if (!saveCheck.canSave) { return false } - localStorage.setItem('Synergysave2', save) - await localforage.setItem('Synergysave2', saveBlob) + await setSave(save) } else { await Alert(i18next.t('testing.errorSaving')) return false @@ -1539,10 +1537,7 @@ export const saveSynergy = async (button?: boolean): Promise => { } const loadSynergy = async () => { - const save = (await localforage.getItem('Synergysave2')) - ?? localStorage.getItem('Synergysave2') - - const saveString = typeof save === 'string' ? save : await save?.text() + const saveString = await getSaveString() const data = saveString ? (JSON.parse(atob(saveString)) as PlayerSave & Record) : null @@ -6194,13 +6189,10 @@ export const reloadShit = async (reset = false) => { setTimeout(res, 0) }) - const save = (await localforage.getItem('Synergysave2')) - ?? localStorage.getItem('Synergysave2') + const saveString = await getSaveString() - const saveObject = typeof save === 'string' ? save : await save?.text() - - if (saveObject) { - const dec = LZString.decompressFromBase64(saveObject) + if (saveString) { + const dec = LZString.decompressFromBase64(saveString) const isLZString = dec !== '' if (isLZString) { @@ -6214,10 +6206,8 @@ export const reloadShit = async (reset = false) => { return Alert(i18next.t('save.loadFailed')) } - localStorage.clear() - const blob = new Blob([saveString], { type: 'text/plain' }) - localStorage.setItem('Synergysave2', saveString) - await localforage.setItem('Synergysave2', blob) + safeLocalStorage.clear() + await setSave(saveString) await Alert(i18next.t('main.transferredFromLZ')) } @@ -6284,9 +6274,9 @@ export const reloadShit = async (reset = false) => { setInterval(cacheReinitialize, 15000) - if (localStorage.getItem('pleaseStar') === null) { + if (safeLocalStorage.getItem('pleaseStar') === null) { void Alert(i18next.t('main.starRepo')) - localStorage.setItem('pleaseStar', '') + safeLocalStorage.setItem('pleaseStar', '') } // All versions of Chrome and Firefox supported by the game have this API, @@ -6309,7 +6299,7 @@ export const reloadShit = async (reset = false) => { } const saveType = DOMCacheGetOrSet('saveType') as HTMLInputElement - saveType.checked = localStorage.getItem('copyToClipboard') !== null + saveType.checked = safeLocalStorage.getItem('copyToClipboard') !== null } function playerNeedsReminderToExport () { @@ -6319,7 +6309,16 @@ function playerNeedsReminderToExport () { } window.addEventListener('load', async () => { - await i18nInit() + if (location.host.endsWith('.discordsays.com')) { + patchUrlMappings([ + { + prefix: '/', + target: 'discord-activities-suck.synergism-cus.pages.dev/' + } + ]) + } + + await i18nInit().catch((e) => console.error('error caught', e)) const ver = DOMCacheGetOrSet('versionnumber') const addZero = (n: number) => `${n}`.padStart(2, '0') @@ -6349,7 +6348,7 @@ window.addEventListener('load', async () => { corruptionButtonsAdd() corruptionLoadoutTableCreate() - handleLogin().catch(console.error) + handleLogin().catch((e) => console.error('caught error', e)) }) window.addEventListener('unload', () => { diff --git a/src/Themes.ts b/src/Themes.ts index eedc049eb..4c5481813 100644 --- a/src/Themes.ts +++ b/src/Themes.ts @@ -1,5 +1,6 @@ import i18next from 'i18next' import { DOMCacheGetOrSet } from './Cache/DOM' +import { safeLocalStorage } from './ImportExport' import { player } from './Synergism' export const toggleTheme = (initial = false, themeNumber = 1, change = false) => { @@ -7,11 +8,11 @@ export const toggleTheme = (initial = false, themeNumber = 1, change = false) => const body = document.body if (change) { - localStorage.setItem('theme', `${themeNumber}`) + safeLocalStorage.setItem('theme', `${themeNumber}`) body.style.setProperty('--transition', '750ms') body.style.setProperty('--transition-extra', '600ms') } else { - themeNumber = Number(localStorage.getItem('theme') ?? 1) + themeNumber = Number(safeLocalStorage.getItem('theme') ?? 1) } /* Full reset for easy out of order change */ @@ -107,7 +108,7 @@ export const toggleTheme = (initial = false, themeNumber = 1, change = false) => } if (themeNumber === 1) { - localStorage.removeItem('theme') + safeLocalStorage.removeItem('theme') themeButton.textContent = 'Dark Mode' } else if (themeNumber === 2) { // 'Darker Mode' body.style.setProperty('--header-color', 'black') diff --git a/src/i18n.ts b/src/i18n.ts index c9883522e..4f0f3ff7d 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -1,6 +1,7 @@ import i18next, { type Resource } from 'i18next' import { DOMCacheGetOrSet } from './Cache/DOM' import { prod } from './Config' +import { safeLocalStorage } from './ImportExport' import ColorTextPlugin from './Plugins/ColorText' import { Confirm } from './UpdateHTML' @@ -21,7 +22,7 @@ const languageCache = new Map() export const init = async (): Promise => { const resources: Record = {} - const language = localStorage.getItem('language') ?? 'en' + const language = safeLocalStorage.getItem('language') ?? 'en' const response = await fetch(`./translations/${language}.json`) const file = await response.json() as Resource @@ -71,7 +72,7 @@ function buildLanguageButton (langID: string, name: string, flag: string) { // i18next.addResourceBundle await i18next.changeLanguage(langID) - localStorage.setItem('language', langID) + safeLocalStorage.setItem('language', langID) const shouldReload = await Confirm(i18next.t('general.languageChange'))