From 00df9c9c32832feea80d6cd6d66c69fabacfab42 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 16 Sep 2024 02:34:02 +0300 Subject: [PATCH] initial splashscreen implementation --- index.html | 94 +++++++++++++++++++- src/App.js | 10 +++ src/App.scss | 100 ++++++++++++++++++++++ src/boot/after_store.js | 6 +- src/i18n/en.json | 11 +++ src/main.js | 2 + src/modules/interface.js | 12 +-- src/services/style_setter/style_setter.js | 17 ++-- static/pleromatan_apology_fox.png | 1 + 9 files changed, 237 insertions(+), 16 deletions(-) create mode 120000 static/pleromatan_apology_fox.png diff --git a/index.html b/index.html index 6d9c4ce5..85371c8b 100644 --- a/index.html +++ b/index.html @@ -8,9 +8,99 @@ - + -
+ +
+ +
+
+
+
+
+
+
+
+
+ (。>﹏<) +
+
+
diff --git a/src/App.js b/src/App.js index b7eb2f72..6f140612 100644 --- a/src/App.js +++ b/src/App.js @@ -44,6 +44,13 @@ export default { data: () => ({ mobileActivePanel: 'timeline' }), + watch: { + themeApplied (value) { + document.querySelector('#app').classList.remove('hidden') + document.querySelector('#splash').className = 'hidden' + document.querySelector('#status').textContent = this.$t('splash.fun_' + Math.ceil(Math.random() * 4)) + } + }, created () { // Load the locale from the storage const val = this.$store.getters.mergedConfig.interfaceLanguage @@ -54,6 +61,9 @@ export default { window.removeEventListener('resize', this.updateMobileState) }, computed: { + themeApplied () { + return this.$store.state.interface.themeApplied + }, classes () { return [ { diff --git a/src/App.scss b/src/App.scss index 9d1ce77a..408ba402 100644 --- a/src/App.scss +++ b/src/App.scss @@ -914,3 +914,103 @@ option { color: var(--selectionText); background-color: var(--selectionBackground); } + +#splash { + pointer-events: none; + transition: opacity 2s; + opacity: 1; + z-index: 9999999999999999999999999999; + + &.hidden { + opacity: 0; + } + + #status { + &.css-ok { + &::before { + display: inline-block; + content: "CSS OK"; + } + } + + .initial-text { + display: none; + } + } + + #throbber { + animation-duration: 2s; + animation-name: bounce; + animation-iteration-count: infinite; + animation-direction: normal; + transform-origin: bottom center; + + @keyframes bounce { + 0% { + scale: 1 1; + translate: 0 0; + animation-timing-function: ease-out; + } + + 10% { + scale: 1.2 0.8; + translate: 0 0; + animation-timing-function: ease-out; + } + + 30% { + scale: 0.9 1.1; + translate: 0 -40%; + animation-timing-function: ease-in; + } + + 40% { + scale: 1.1 0.9; + translate: 0 -50%; + animation-timing-function: ease-in; + } + + 45% { + scale: 0.9 1.1; + translate: 0 -45%; + animation-timing-function: ease-in; + } + + 50% { + scale: 1.05 0.95; + translate: 0 -40%; + animation-timing-function: ease-in; + } + + 55% { + scale: 0.985 1.025; + translate: 0 -35%; + animation-timing-function: ease-in; + } + + 60% { + scale: 1.0125 0.9985; + translate: 0 -30%; + animation-timing-function: ease-in; + } + + 80% { + scale: 1.0063 0.9938; + translate: 0 -10%; + animation-timing-function: ease-in-ou; + } + + 90% { + scale: 1.2 0.8; + translate: 0 0; + animation-timing-function: ease-out; + } + + 100% { + scale: 1 1; + translate: 0 0; + animation-timing-function: ease-out; + } + } + } +} diff --git a/src/boot/after_store.js b/src/boot/after_store.js index 6cad05f6..6691ff3e 100644 --- a/src/boot/after_store.js +++ b/src/boot/after_store.js @@ -352,10 +352,12 @@ const afterStoreSetup = async ({ store, i18n }) => { await setConfig({ store }) await store.dispatch('setTheme') - applyConfig(store.state.config) + document.querySelector('#status').textContent = i18n.global.t('splash.theme') + applyConfig(store.state.config, i18n.global) // Now we can try getting the server settings and logging in // Most of these are preloaded into the index.html so blocking is minimized + document.querySelector('#status').textContent = i18n.global.t('splash.instance') await Promise.all([ checkOAuthToken({ store }), getInstancePanel({ store }), @@ -395,9 +397,9 @@ const afterStoreSetup = async ({ store, i18n }) => { // remove after vue 3.3 app.config.unwrapInjectedRef = true + document.querySelector('#status').textContent = i18n.global.t('splash.almost') app.mount('#app') - return app } diff --git a/src/i18n/en.json b/src/i18n/en.json index 3f7ea282..d30b07ef 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -1401,5 +1401,16 @@ }, "unicode_domain_indicator": { "tooltip": "This domain contains non-ascii characters." + }, + "splash": { + "loading": "Loading...", + "theme": "Applying theme, please wait warmly...", + "instance": "Getting instance info...", + "splines": "Reticulating splines...", + "almost": "Almost there!", + "fun_1": "Drink more water!", + "fun_2": "Take it easy!", + "fun_3": "Suya..", + "fun_4": "#cofe", } } diff --git a/src/main.js b/src/main.js index 85eb1f4c..580c5005 100644 --- a/src/main.js +++ b/src/main.js @@ -67,6 +67,8 @@ const persistedStateOptions = { console.error(e) storageError = true } + document.querySelector('#status').removeAttribute('class') + document.querySelector('#status').textContent = i18n.global.t('splash.loading') const store = createStore({ modules: { i18n: { diff --git a/src/modules/interface.js b/src/modules/interface.js index 57bfe0c6..3f180cf5 100644 --- a/src/modules/interface.js +++ b/src/modules/interface.js @@ -56,9 +56,6 @@ const interfaceMod = { state.temporaryChangesConfirm = () => {} state.temporaryChangesRevert = () => {} }, - setThemeApplied (state) { - state.themeApplied = true - }, setNotificationPermission (state, permission) { state.notificationPermission = permission }, @@ -120,6 +117,9 @@ const interfaceMod = { setPageTitle ({ rootState }, option = '') { document.title = `${option} ${rootState.instance.name}` }, + setThemeApplied ({ state, rootGetters }) { + state.themeApplied = true + }, settingsSaved ({ commit, dispatch }, { success, error }) { commit('settingsSaved', { success, error }) }, @@ -212,7 +212,7 @@ const interfaceMod = { setLastTimeline ({ commit }, value) { commit('setLastTimeline', value) }, - setTheme ({ commit, rootState }, { themeName, themeData, recompile, saveData } = {}) { + setTheme ({ dispatch, commit, rootState }, { themeName, themeData, recompile, saveData } = {}) { const { theme: instanceThemeName } = rootState.instance @@ -258,7 +258,7 @@ const interfaceMod = { // If we're not not forced to recompile try using // cache (tryLoadCache return true if load successful) if (!forceRecompile && !themeDebug && tryLoadCache()) { - commit('setThemeApplied') + dispatch('setThemeApplied') return } @@ -342,7 +342,7 @@ const interfaceMod = { applyTheme( ruleset, - () => commit('setThemeApplied'), + () => dispatch('setThemeApplied'), themeDebug ) }) diff --git a/src/services/style_setter/style_setter.js b/src/services/style_setter/style_setter.js index e54a95bf..2b3f88a8 100644 --- a/src/services/style_setter/style_setter.js +++ b/src/services/style_setter/style_setter.js @@ -169,7 +169,16 @@ export const applyTheme = async (input, onFinish = (data) => {}, debug) => { adoptStyleSheets([eagerStyles, lazyStyles]) const cache = { engineChecksum: getEngineChecksum(), data: [eagerStyles.rules, lazyStyles.rules] } onFinish(cache) - localStorage.setItem('pleroma-fe-theme-cache', JSON.stringify(cache)) + try { + localStorage.setItem('pleroma-fe-theme-cache', JSON.stringify(cache)) + } catch (e) { + localStorage.removeItem('pleroma-fe-theme-cache') + try { + localStorage.setItem('pleroma-fe-theme-cache', JSON.stringify(cache)) + } catch (e) { + console.warn('cannot save cache!', e) + } + } } }, debug @@ -222,7 +231,7 @@ const extractStyleConfig = ({ const defaultStyleConfig = extractStyleConfig(defaultState) -export const applyConfig = (input) => { +export const applyConfig = (input, i18n) => { const config = extractStyleConfig(input) if (config === defaultStyleConfig) { @@ -230,8 +239,6 @@ export const applyConfig = (input) => { } const head = document.head - const body = document.body - body.classList.add('hidden') const rules = Object .entries(config) @@ -252,8 +259,6 @@ export const applyConfig = (input) => { --roundness: var(--forcedRoundness) !important; }`, 'index-max') } - - body.classList.remove('hidden') } export const getThemes = () => { diff --git a/static/pleromatan_apology_fox.png b/static/pleromatan_apology_fox.png new file mode 120000 index 00000000..99f0ab91 --- /dev/null +++ b/static/pleromatan_apology_fox.png @@ -0,0 +1 @@ +/home/bocchi/Repos/Mine/pleroma-fe/src/assets/pleromatan_apology_fox.png \ No newline at end of file