From 00df9c9c32832feea80d6cd6d66c69fabacfab42 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 16 Sep 2024 02:34:02 +0300 Subject: 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 -- cgit v1.2.3-70-g09d2 From 023c1d5ff0f60826d62fcd9efbc78b8f7b68cc5b Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 16 Sep 2024 02:39:37 +0300 Subject: oops --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 85371c8b..b8d24c1a 100644 --- a/index.html +++ b/index.html @@ -26,7 +26,7 @@ > Date: Mon, 16 Sep 2024 02:41:17 +0300 Subject: escape --- index.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index b8d24c1a..36562105 100644 --- a/index.html +++ b/index.html @@ -97,7 +97,8 @@ text-align: center; " > - (。>﹏<) + + %28%uFF61%3E%uFE4F%3C%29
-- cgit v1.2.3-70-g09d2 From 6b37e5baec48fd9cad4a59cb4684ed9dc85e30e8 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 16 Sep 2024 02:42:35 +0300 Subject: actual escape for real this time --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 36562105..c6a12fc1 100644 --- a/index.html +++ b/index.html @@ -98,7 +98,7 @@ " > - %28%uFF61%3E%uFE4F%3C%29 + (。>﹏<) -- cgit v1.2.3-70-g09d2 From bfc1091f7f071e199d8d1111a38a9484e20c4088 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 16 Sep 2024 02:49:16 +0300 Subject: ugh, json --- src/i18n/en.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/i18n/en.json b/src/i18n/en.json index d30b07ef..0d4609b5 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -1411,6 +1411,6 @@ "fun_1": "Drink more water!", "fun_2": "Take it easy!", "fun_3": "Suya..", - "fun_4": "#cofe", + "fun_4": "#cofe" } } -- cgit v1.2.3-70-g09d2 From dc4cbbe8308cc9a9521dca630b12ba9092e1c208 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 16 Sep 2024 02:52:27 +0300 Subject: fix symlink --- static/pleromatan_apology_fox.png | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/pleromatan_apology_fox.png b/static/pleromatan_apology_fox.png index 99f0ab91..5892f0cb 120000 --- a/static/pleromatan_apology_fox.png +++ b/static/pleromatan_apology_fox.png @@ -1 +1 @@ -/home/bocchi/Repos/Mine/pleroma-fe/src/assets/pleromatan_apology_fox.png \ No newline at end of file +../src/assets/pleromatan_apology_fox.png \ No newline at end of file -- cgit v1.2.3-70-g09d2 From 2abde63afc9ecdd4f1faa070650236597fbbf116 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 16 Sep 2024 03:00:31 +0300 Subject: swap pleromatan_apology_fox location --- index.html | 1 + src/App.js | 2 +- src/assets/pleromatan_apology_fox.png | Bin 533320 -> 39 bytes static/pleromatan_apology_fox.png | Bin 40 -> 533320 bytes 4 files changed, 2 insertions(+), 1 deletion(-) mode change 100644 => 120000 src/assets/pleromatan_apology_fox.png mode change 120000 => 100644 static/pleromatan_apology_fox.png diff --git a/index.html b/index.html index c6a12fc1..809318cf 100644 --- a/index.html +++ b/index.html @@ -22,6 +22,7 @@ font-family: sans-serif; color: #b9b9ba; position: absolute; + z-index: 99; " > Date: Mon, 16 Sep 2024 03:06:19 +0300 Subject: attemt to fix production --- index.html | 2 +- src/App.js | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/index.html b/index.html index 809318cf..474c0244 100644 --- a/index.html +++ b/index.html @@ -22,7 +22,7 @@ font-family: sans-serif; color: #b9b9ba; position: absolute; - z-index: 99; + z-index: 999999; " > { + document.querySelector('#app').classList.remove('hidden') + document.querySelector('#splash').classList.add('hidden') + document.querySelector('#status').textContent = this.$t('splash.fun_' + Math.ceil(Math.random() * 4)) + }) } }, created () { -- cgit v1.2.3-70-g09d2 From 6c5fc53789538e393703ac1251d6cecdc9bb64bb Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Mon, 16 Sep 2024 03:36:17 +0300 Subject: fix production --- src/App.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/App.js b/src/App.js index e1ce8808..d2dd35c7 100644 --- a/src/App.js +++ b/src/App.js @@ -46,11 +46,7 @@ export default { }), watch: { themeApplied (value) { - this.$nextTick(() => { - document.querySelector('#app').classList.remove('hidden') - document.querySelector('#splash').classList.add('hidden') - document.querySelector('#status').textContent = this.$t('splash.fun_' + Math.ceil(Math.random() * 4)) - }) + this.removeSplash() } }, created () { @@ -59,6 +55,11 @@ export default { this.$store.dispatch('setOption', { name: 'interfaceLanguage', value: val }) window.addEventListener('resize', this.updateMobileState) }, + mounted () { + if (this.$store.state.interface.themeApplied) { + this.removeSplash() + } + }, unmounted () { window.removeEventListener('resize', this.updateMobileState) }, @@ -142,6 +143,11 @@ export default { updateMobileState () { this.$store.dispatch('setLayoutWidth', windowWidth()) this.$store.dispatch('setLayoutHeight', windowHeight()) + }, + removeSplash () { + document.querySelector('#status').textContent = this.$t('splash.fun_' + Math.ceil(Math.random() * 4)) + document.querySelector('#splash').classList.add('hidden') + document.querySelector('#app').classList.remove('hidden') } } } -- cgit v1.2.3-70-g09d2 From 7550b8cbd2152c86fb32258c846c1ad2fe139c89 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Tue, 17 Sep 2024 05:04:52 +0300 Subject: splashscreen is now smaller, big cleanup on aisle themes - removed a lot unnecessary sync/awaits and promises that were sequential anyway --- index.html | 197 +++++++++++++----------- src/App.scss | 79 +++++++++- src/boot/after_store.js | 17 +- src/i18n/en.json | 11 +- src/main.js | 110 +++++++------ src/modules/interface.js | 182 +++++++++++----------- src/services/style_setter/style_setter.js | 10 +- src/services/theme_data/theme_data_3.service.js | 5 + static/pleromatan_orz.png | Bin 0 -> 1113445 bytes static/pleromatan_orz_fox.png | Bin 0 -> 1301128 bytes 10 files changed, 362 insertions(+), 249 deletions(-) create mode 100644 static/pleromatan_orz.png create mode 100644 static/pleromatan_orz_fox.png diff --git a/index.html b/index.html index 474c0244..6588a287 100644 --- a/index.html +++ b/index.html @@ -4,6 +4,101 @@ + @@ -11,95 +106,23 @@ -
- -
-
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+ + (。>﹏<)
-
-
-
-
- - (。>﹏<)
diff --git a/src/App.scss b/src/App.scss index 408ba402..5e7d3656 100644 --- a/src/App.scss +++ b/src/App.scss @@ -919,7 +919,6 @@ option { pointer-events: none; transition: opacity 2s; opacity: 1; - z-index: 9999999999999999999999999999; &.hidden { opacity: 0; @@ -938,13 +937,80 @@ option { } } + #mascot-container { + perspective: 60em; + perspective-origin: 0 -15em; + transform-style: preserve-3d; + } + #throbber { - animation-duration: 2s; + animation-duration: 3s; animation-name: bounce; animation-iteration-count: infinite; animation-direction: normal; transform-origin: bottom center; + --defaultY: 0; + + &.dead { + animation-name: dead; + animation-duration: 3s; + // animation-iteration-count: 1; + animation-iteration-count: 1; + transform: rotateX(90deg) rotateY(0) rotateZ(-45deg); + } + + @keyframes dead { + 0% { + transform: rotateX(0) rotateY(0) rotateZ(0); + } + + 5% { + transform: rotateX(0) rotateY(0) rotateZ(1deg); + } + + 10% { + transform: rotateX(0) rotateY(0) rotateZ(-2deg); + } + + 15% { + transform: rotateX(0) rotateY(0) rotateZ(3deg); + } + + 20% { + transform: rotateX(0) rotateY(0) rotateZ(0); + } + + 25% { + transform: rotateX(0) rotateY(0) rotateZ(0); + } + + 30% { + transform: rotateX(10deg) rotateY(0) rotateZ(0); + } + + 35% { + transform: rotateX(-10deg) rotateY(0) rotateZ(0); + } + + 40% { + transform: rotateX(10deg) rotateY(0) rotateZ(0); + } + + 45% { + transform: rotateX(-10deg) rotateY(0) rotateZ(0); + } + + 50% { + transform: rotateX(10deg) rotateY(0) rotateZ(0); + } + + 100% { + transform: rotateX(90deg) rotateY(0) rotateZ(-45deg); + transition-timing-function: cubic-bezier(0.755, 0.05, 0.855, 0.06); /* easeInQuint */ + } + } + @keyframes bounce { 0% { scale: 1 1; @@ -955,24 +1021,28 @@ option { 10% { scale: 1.2 0.8; translate: 0 0; + transform: rotateZ(var(--defaultZ)); animation-timing-function: ease-out; } 30% { scale: 0.9 1.1; translate: 0 -40%; + transform: rotateZ(var(--defaultZ)); animation-timing-function: ease-in; } 40% { scale: 1.1 0.9; translate: 0 -50%; + transform: rotateZ(var(--defaultZ)); animation-timing-function: ease-in; } 45% { scale: 0.9 1.1; translate: 0 -45%; + transform: rotateZ(var(--defaultZ)); animation-timing-function: ease-in; } @@ -985,30 +1055,35 @@ option { 55% { scale: 0.985 1.025; translate: 0 -35%; + transform: rotateZ(var(--defaultZ)); animation-timing-function: ease-in; } 60% { scale: 1.0125 0.9985; translate: 0 -30%; + transform: rotateZ(var(--defaultZ)); animation-timing-function: ease-in; } 80% { scale: 1.0063 0.9938; translate: 0 -10%; + transform: rotateZ(var(--defaultZ)); animation-timing-function: ease-in-ou; } 90% { scale: 1.2 0.8; translate: 0 0; + transform: rotateZ(var(--defaultZ)); animation-timing-function: ease-out; } 100% { scale: 1 1; translate: 0 0; + transform: rotateZ(var(--defaultZ)); animation-timing-function: ease-out; } } diff --git a/src/boot/after_store.js b/src/boot/after_store.js index 6691ff3e..356b09fa 100644 --- a/src/boot/after_store.js +++ b/src/boot/after_store.js @@ -327,11 +327,7 @@ const setConfig = async ({ store }) => { const checkOAuthToken = async ({ store }) => { if (store.getters.getUserToken()) { - try { - await store.dispatch('loginUser', store.getters.getUserToken()) - } catch (e) { - console.error(e) - } + return store.dispatch('loginUser', store.getters.getUserToken()) } return Promise.resolve() } @@ -349,10 +345,15 @@ const afterStoreSetup = async ({ store, i18n }) => { const server = (typeof overrides.target !== 'undefined') ? overrides.target : window.location.origin store.dispatch('setInstanceOption', { name: 'server', value: server }) + document.querySelector('#status').textContent = i18n.global.t('splash.settings') await setConfig({ store }) - await store.dispatch('setTheme') - document.querySelector('#status').textContent = i18n.global.t('splash.theme') + try { + await store.dispatch('setTheme').catch((e) => { console.log(e) }) + } catch (e) { + return Promise.reject(e) + } + applyConfig(store.state.config, i18n.global) // Now we can try getting the server settings and logging in @@ -363,7 +364,7 @@ const afterStoreSetup = async ({ store, i18n }) => { getInstancePanel({ store }), getNodeInfo({ store }), getInstanceConfig({ store }) - ]) + ]).catch(e => Promise.reject(e)) // Start fetching things that don't need to block the UI store.dispatch('fetchMutes') diff --git a/src/i18n/en.json b/src/i18n/en.json index 0d4609b5..8d6a9bfe 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -1406,11 +1406,12 @@ "loading": "Loading...", "theme": "Applying theme, please wait warmly...", "instance": "Getting instance info...", - "splines": "Reticulating splines...", - "almost": "Almost there!", - "fun_1": "Drink more water!", + "settings": "Applying settings...", + "almost": "Reticulating splines...", + "fun_1": "Drink more water", "fun_2": "Take it easy!", - "fun_3": "Suya..", - "fun_4": "#cofe" + "fun_3": "Suya...", + "fun_4": "My Pleroma machine is full power!", + "error": "Something went wrong" } } diff --git a/src/main.js b/src/main.js index 580c5005..40347e6d 100644 --- a/src/main.js +++ b/src/main.js @@ -48,6 +48,16 @@ const i18n = createI18n({ messages.setLanguage(i18n.global, currentLocale) +const splashError = (i18n, e) => { + document.querySelector('#mascot').src = (Math.floor(Math.random() * 2) > 0) + ? '/static/pleromatan_orz_fox.png' + : '/static/pleromatan_orz.png' + document.querySelector('#mascot').classList.add('orz') + document.querySelector('#throbber').classList.add('dead') + document.querySelector('#status').textContent = i18n.global.t('splash.error') + console.error('PleromaFE failed to initialize: ', e) +} + const persistedStateOptions = { paths: [ 'serverSideStorage.cache', @@ -58,57 +68,61 @@ const persistedStateOptions = { }; (async () => { - let storageError = false - const plugins = [pushNotifications] try { - const persistedState = await createPersistedState(persistedStateOptions) - plugins.push(persistedState) - } catch (e) { - console.error(e) - storageError = true - } - document.querySelector('#status').removeAttribute('class') - document.querySelector('#status').textContent = i18n.global.t('splash.loading') - const store = createStore({ - modules: { - i18n: { - getters: { - i18n: () => i18n.global - } + let storageError + const plugins = [pushNotifications] + try { + const persistedState = await createPersistedState(persistedStateOptions) + plugins.push(persistedState) + } catch (e) { + console.error('Storage error', e) + storageError = e + } + document.querySelector('#status').removeAttribute('class') + document.querySelector('#status').textContent = i18n.global.t('splash.loading') + const store = createStore({ + modules: { + i18n: { + getters: { + i18n: () => i18n.global + } + }, + interface: interfaceModule, + instance: instanceModule, + // TODO refactor users/statuses modules, they depend on each other + users: usersModule, + statuses: statusesModule, + notifications: notificationsModule, + lists: listsModule, + api: apiModule, + config: configModule, + profileConfig: profileConfigModule, + serverSideStorage: serverSideStorageModule, + adminSettings: adminSettingsModule, + shout: shoutModule, + oauth: oauthModule, + authFlow: authFlowModule, + mediaViewer: mediaViewerModule, + oauthTokens: oauthTokensModule, + reports: reportsModule, + polls: pollsModule, + postStatus: postStatusModule, + editStatus: editStatusModule, + statusHistory: statusHistoryModule, + chats: chatsModule, + announcements: announcementsModule }, - interface: interfaceModule, - instance: instanceModule, - // TODO refactor users/statuses modules, they depend on each other - users: usersModule, - statuses: statusesModule, - notifications: notificationsModule, - lists: listsModule, - api: apiModule, - config: configModule, - profileConfig: profileConfigModule, - serverSideStorage: serverSideStorageModule, - adminSettings: adminSettingsModule, - shout: shoutModule, - oauth: oauthModule, - authFlow: authFlowModule, - mediaViewer: mediaViewerModule, - oauthTokens: oauthTokensModule, - reports: reportsModule, - polls: pollsModule, - postStatus: postStatusModule, - editStatus: editStatusModule, - statusHistory: statusHistoryModule, - chats: chatsModule, - announcements: announcementsModule - }, - plugins, - strict: false // Socket modifies itself, let's ignore this for now. - // strict: process.env.NODE_ENV !== 'production' - }) - if (storageError) { - store.dispatch('pushGlobalNotice', { messageKey: 'errors.storage_unavailable', level: 'error' }) + plugins, + strict: false // Socket modifies itself, let's ignore this for now. + // strict: process.env.NODE_ENV !== 'production' + }) + if (storageError) { + store.dispatch('pushGlobalNotice', { messageKey: 'errors.storage_unavailable', level: 'error' }) + } + return await afterStoreSetup({ store, i18n }) + } catch (e) { + splashError(i18n, e) } - afterStoreSetup({ store, i18n }) })() // These are inlined by webpack's DefinePlugin diff --git a/src/modules/interface.js b/src/modules/interface.js index 3f180cf5..68b51015 100644 --- a/src/modules/interface.js +++ b/src/modules/interface.js @@ -230,27 +230,27 @@ const interfaceMod = { const forceRecompile = forceThemeRecompilation || recompile - let promise = null + let result = null if (themeData) { - promise = Promise.resolve(normalizeThemeData(themeData)) + result = normalizeThemeData(themeData) } else if (themeName) { - promise = getPreset(themeName).then(themeData => normalizeThemeData(themeData)) + result = normalizeThemeData(getPreset(themeName)) + .then(themeData => normalizeThemeData(themeData)) } else if (userThemeSource || userThemeSnapshot) { - promise = Promise.resolve(normalizeThemeData({ + result = normalizeThemeData({ _pleroma_theme_version: 2, theme: userThemeSnapshot, source: userThemeSource - })) - } else if (actualThemeName && actualThemeName !== 'custom') { - promise = getPreset(actualThemeName).then(themeData => { - const realThemeData = normalizeThemeData(themeData) - if (actualThemeName === instanceThemeName) { - // This sole line is the reason why this whole block is above the recompilation check - commit('setInstanceOption', { name: 'themeData', value: { theme: realThemeData } }) - } - return realThemeData }) + } else if (actualThemeName && actualThemeName !== 'custom') { + const themeData = actualThemeName + const realThemeData = normalizeThemeData(themeData) + if (actualThemeName === instanceThemeName) { + // This sole line is the reason why this whole block is above the recompilation check + commit('setInstanceOption', { name: 'themeData', value: { theme: realThemeData } }) + } + result = realThemeData } else { throw new Error('Cannot load any theme!') } @@ -259,95 +259,91 @@ const interfaceMod = { // cache (tryLoadCache return true if load successful) if (!forceRecompile && !themeDebug && tryLoadCache()) { dispatch('setThemeApplied') - return + return Promise.resolve() } - promise - .then(realThemeData => { - const theme2ruleset = convertTheme2To3(realThemeData) + const realThemeData = result + const theme2ruleset = convertTheme2To3(realThemeData) - if (saveData) { - commit('setOption', { name: 'theme', value: themeName || actualThemeName }) - commit('setOption', { name: 'customTheme', value: realThemeData }) - commit('setOption', { name: 'customThemeSource', value: realThemeData }) - } - const hacks = [] + if (saveData) { + commit('setOption', { name: 'theme', value: themeName || actualThemeName }) + commit('setOption', { name: 'customTheme', value: realThemeData }) + commit('setOption', { name: 'customThemeSource', value: realThemeData }) + } + const hacks = [] - Object.entries(theme3hacks).forEach(([key, value]) => { - switch (key) { - case 'fonts': { - Object.entries(theme3hacks.fonts).forEach(([fontKey, font]) => { - if (!font?.family) return - switch (fontKey) { - case 'interface': - hacks.push({ - component: 'Root', - directives: { - '--font': 'generic | ' + font.family - } - }) - break - case 'input': - hacks.push({ - component: 'Input', - directives: { - '--font': 'generic | ' + font.family - } - }) - break - case 'post': - hacks.push({ - component: 'RichContent', - directives: { - '--font': 'generic | ' + font.family - } - }) - break - case 'monospace': - hacks.push({ - component: 'Root', - directives: { - '--monoFont': 'generic | ' + font.family - } - }) - break - } - }) - break + Object.entries(theme3hacks).forEach(([key, value]) => { + switch (key) { + case 'fonts': { + Object.entries(theme3hacks.fonts).forEach(([fontKey, font]) => { + if (!font?.family) return + switch (fontKey) { + case 'interface': + hacks.push({ + component: 'Root', + directives: { + '--font': 'generic | ' + font.family + } + }) + break + case 'input': + hacks.push({ + component: 'Input', + directives: { + '--font': 'generic | ' + font.family + } + }) + break + case 'post': + hacks.push({ + component: 'RichContent', + directives: { + '--font': 'generic | ' + font.family + } + }) + break + case 'monospace': + hacks.push({ + component: 'Root', + directives: { + '--monoFont': 'generic | ' + font.family + } + }) + break } - case 'underlay': { - if (value !== 'none') { - const newRule = { - component: 'Underlay', - directives: {} - } - if (value === 'opaque') { - newRule.directives.opacity = 1 - newRule.directives.background = '--wallpaper' - } - if (value === 'transparent') { - newRule.directives.opacity = 0 - } - hacks.push(newRule) - } - break + }) + break + } + case 'underlay': { + if (value !== 'none') { + const newRule = { + component: 'Underlay', + directives: {} } + if (value === 'opaque') { + newRule.directives.opacity = 1 + newRule.directives.background = '--wallpaper' + } + if (value === 'transparent') { + newRule.directives.opacity = 0 + } + hacks.push(newRule) } - }) - - const ruleset = [ - ...theme2ruleset, - ...hacks - ] + break + } + } + }) - applyTheme( - ruleset, - () => dispatch('setThemeApplied'), - themeDebug - ) - }) + const ruleset = [ + ...theme2ruleset, + ...hacks + ] - return promise + applyTheme( + ruleset, + () => dispatch('setThemeApplied'), + themeDebug + ) } } } diff --git a/src/services/style_setter/style_setter.js b/src/services/style_setter/style_setter.js index 2b3f88a8..c1603f39 100644 --- a/src/services/style_setter/style_setter.js +++ b/src/services/style_setter/style_setter.js @@ -43,16 +43,16 @@ const adoptStyleSheets = (styles) => { // is nothing to do here. } -export const generateTheme = async (inputRuleset, callbacks, debug) => { +export const generateTheme = (inputRuleset, callbacks, debug) => { const { onNewRule = (rule, isLazy) => {}, onLazyFinished = () => {}, onEagerFinished = () => {} } = callbacks - // Assuming that "worst case scenario background" is panel background since it's the most likely one const themes3 = init({ inputRuleset, + // Assuming that "worst case scenario background" is panel background since it's the most likely one ultimateBackgroundColor: inputRuleset[0].directives['--bg'].split('|')[1].trim(), debug }) @@ -146,11 +146,11 @@ export const tryLoadCache = () => { } } -export const applyTheme = async (input, onFinish = (data) => {}, debug) => { +export const applyTheme = (input, onFinish = (data) => {}, debug) => { const eagerStyles = createStyleSheet(EAGER_STYLE_ID) const lazyStyles = createStyleSheet(LAZY_STYLE_ID) - const { lazyProcessFunc } = await generateTheme( + const { lazyProcessFunc } = generateTheme( input, { onNewRule (rule, isLazy) { @@ -185,8 +185,6 @@ export const applyTheme = async (input, onFinish = (data) => {}, debug) => { ) setTimeout(lazyProcessFunc, 0) - - return Promise.resolve() } const extractStyleConfig = ({ diff --git a/src/services/theme_data/theme_data_3.service.js b/src/services/theme_data/theme_data_3.service.js index cf58da11..056b78f7 100644 --- a/src/services/theme_data/theme_data_3.service.js +++ b/src/services/theme_data/theme_data_3.service.js @@ -196,6 +196,11 @@ export const init = ({ return rule }) + const i = 4 + if (2 + 2 === i) { + throw new Error('test') + } + const ruleset = rulesetUnsorted .map((data, index) => ({ data, index })) .sort(({ data: a, index: ai }, { data: b, index: bi }) => { diff --git a/static/pleromatan_orz.png b/static/pleromatan_orz.png new file mode 100644 index 00000000..aa54411f Binary files /dev/null and b/static/pleromatan_orz.png differ diff --git a/static/pleromatan_orz_fox.png b/static/pleromatan_orz_fox.png new file mode 100644 index 00000000..936e42f1 Binary files /dev/null and b/static/pleromatan_orz_fox.png differ -- cgit v1.2.3-70-g09d2 From 05577aea546296e675c2722d248bf7f515961c0d Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Tue, 17 Sep 2024 22:56:06 +0300 Subject: replace toSorted with sort, add artist credit --- index.html | 16 ++++++++++++++++ src/main.js | 1 + src/services/theme_data/theme_data_3.service.js | 5 ----- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/index.html b/index.html index 6588a287..702acfe8 100644 --- a/index.html +++ b/index.html @@ -29,6 +29,13 @@ font-size: calc(1vw + 1vh + 1vmin); } + #splash-credit { + position: absolute; + font-size: 14px; + bottom: 0; + right: 0; + } + #splash-container { align-items: center; } @@ -98,6 +105,12 @@ width: 100%; text-align: center; } + + @media (prefers-reduced-motion) { + #throbber { + animation: none; + } + } @@ -107,6 +120,9 @@
+
+ Art by pipivovott +
diff --git a/src/main.js b/src/main.js index 40347e6d..4ccdabb9 100644 --- a/src/main.js +++ b/src/main.js @@ -80,6 +80,7 @@ const persistedStateOptions = { } document.querySelector('#status').removeAttribute('class') document.querySelector('#status').textContent = i18n.global.t('splash.loading') + document.querySelector('#splash-credit').textContent = i18n.global.t('update.art_by', { linkToArtist: 'pipivovott' }) const store = createStore({ modules: { i18n: { diff --git a/src/services/theme_data/theme_data_3.service.js b/src/services/theme_data/theme_data_3.service.js index 056b78f7..cf58da11 100644 --- a/src/services/theme_data/theme_data_3.service.js +++ b/src/services/theme_data/theme_data_3.service.js @@ -196,11 +196,6 @@ export const init = ({ return rule }) - const i = 4 - if (2 + 2 === i) { - throw new Error('test') - } - const ruleset = rulesetUnsorted .map((data, index) => ({ data, index })) .sort(({ data: a, index: ai }, { data: b, index: bi }) => { -- cgit v1.2.3-70-g09d2 From 7c8308a41036604cd384910fd50a87e01ded9bd1 Mon Sep 17 00:00:00 2001 From: HJ <30-hj@users.noreply.git.pleroma.social> Date: Tue, 17 Sep 2024 23:19:35 +0000 Subject: Apply 1 suggestion(s) to 1 file(s) --- index.html | 4 ---- 1 file changed, 4 deletions(-) diff --git a/index.html b/index.html index 702acfe8..19e68806 100644 --- a/index.html +++ b/index.html @@ -5,10 +5,6 @@ @@ -132,7 +126,7 @@
- +
diff --git a/src/App.scss b/src/App.scss index 5e7d3656..d5bb6469 100644 --- a/src/App.scss +++ b/src/App.scss @@ -954,8 +954,7 @@ option { &.dead { animation-name: dead; - animation-duration: 3s; - // animation-iteration-count: 1; + animation-duration: 2s; animation-iteration-count: 1; transform: rotateX(90deg) rotateY(0) rotateZ(-45deg); } diff --git a/src/assets/pleromatan_apology.png b/src/assets/pleromatan_apology.png deleted file mode 100644 index 36ad7aeb..00000000 Binary files a/src/assets/pleromatan_apology.png and /dev/null differ diff --git a/src/assets/pleromatan_apology.png b/src/assets/pleromatan_apology.png new file mode 120000 index 00000000..a7f6191f --- /dev/null +++ b/src/assets/pleromatan_apology.png @@ -0,0 +1 @@ +../../static/pleromatan_apology.png \ No newline at end of file diff --git a/src/main.js b/src/main.js index 4ccdabb9..81fa09db 100644 --- a/src/main.js +++ b/src/main.js @@ -48,16 +48,6 @@ const i18n = createI18n({ messages.setLanguage(i18n.global, currentLocale) -const splashError = (i18n, e) => { - document.querySelector('#mascot').src = (Math.floor(Math.random() * 2) > 0) - ? '/static/pleromatan_orz_fox.png' - : '/static/pleromatan_orz.png' - document.querySelector('#mascot').classList.add('orz') - document.querySelector('#throbber').classList.add('dead') - document.querySelector('#status').textContent = i18n.global.t('splash.error') - console.error('PleromaFE failed to initialize: ', e) -} - const persistedStateOptions = { paths: [ 'serverSideStorage.cache', @@ -68,6 +58,18 @@ const persistedStateOptions = { }; (async () => { + const isFox = Math.floor(Math.random() * 2) > 0 ? '_fox' : '' + + const splashError = (i18n, e) => { + const throbber = document.querySelector('#throbber') + throbber.addEventListener('animationend', () => { + document.querySelector('#mascot').src = `/static/pleromatan_orz${isFox}.png` + }) + throbber.classList.add('dead') + document.querySelector('#status').textContent = i18n.global.t('splash.error') + console.error('PleromaFE failed to initialize: ', e) + } + try { let storageError const plugins = [pushNotifications] @@ -78,6 +80,7 @@ const persistedStateOptions = { console.error('Storage error', e) storageError = e } + document.querySelector('#mascot').src = `/static/pleromatan_apology${isFox}.png` document.querySelector('#status').removeAttribute('class') document.querySelector('#status').textContent = i18n.global.t('splash.loading') document.querySelector('#splash-credit').textContent = i18n.global.t('update.art_by', { linkToArtist: 'pipivovott' }) diff --git a/static/pleromatan_apology.png b/static/pleromatan_apology.png new file mode 100644 index 00000000..36ad7aeb Binary files /dev/null and b/static/pleromatan_apology.png differ -- cgit v1.2.3-70-g09d2 From 711eb24504d231e2276640b614849a3ae6703c14 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Wed, 18 Sep 2024 17:36:50 +0300 Subject: cleanup --- src/App.scss | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/App.scss b/src/App.scss index d5bb6469..f52ba06b 100644 --- a/src/App.scss +++ b/src/App.scss @@ -937,12 +937,6 @@ option { } } - #mascot-container { - perspective: 60em; - perspective-origin: 0 -15em; - transform-style: preserve-3d; - } - #throbber { animation-duration: 3s; animation-name: bounce; @@ -950,8 +944,6 @@ option { animation-direction: normal; transform-origin: bottom center; - --defaultY: 0; - &.dead { animation-name: dead; animation-duration: 2s; -- cgit v1.2.3-70-g09d2 From e004c4e087d4cf977a3fb713f5441c92028b83b6 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Wed, 18 Sep 2024 21:33:20 +0300 Subject: remove splash when it's done --- src/App.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/App.js b/src/App.js index d2dd35c7..e87108dd 100644 --- a/src/App.js +++ b/src/App.js @@ -146,7 +146,11 @@ export default { }, removeSplash () { document.querySelector('#status').textContent = this.$t('splash.fun_' + Math.ceil(Math.random() * 4)) - document.querySelector('#splash').classList.add('hidden') + const splashscreenRoot = document.querySelector('#splash') + splashscreenRoot.addEventListener('transitionend', () => { + splashscreenRoot.remove() + }) + splashscreenRoot.classList.add('hidden') document.querySelector('#app').classList.remove('hidden') } } -- cgit v1.2.3-70-g09d2 From 80e8ea6feac6917f12b3f297b3d2595f894f698e Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Wed, 18 Sep 2024 21:35:10 +0300 Subject: re-align the mascot container --- index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.html b/index.html index b5116b25..461f5acc 100644 --- a/index.html +++ b/index.html @@ -58,7 +58,7 @@ display: grid; width: calc(5em * 0.5 * var(--scale)); height: calc(8em * 0.5 * var(--scale)); - margin-left: 5.1em; + margin-left: 4.1em; z-index: 2; grid-template-rows: repeat(8, 1fr); grid-template-columns: repeat(5, 1fr); @@ -93,7 +93,7 @@ } #status { - margin-top: 0.5em; + margin-top: 1em; line-height: 2; width: 100%; text-align: center; -- cgit v1.2.3-70-g09d2 From 51a8b20a920d1d32d9812664557db92ab9b40d4c Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Thu, 26 Sep 2024 01:46:17 +0300 Subject: changelog --- changelog.d/splashscreen.add | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/splashscreen.add diff --git a/changelog.d/splashscreen.add b/changelog.d/splashscreen.add new file mode 100644 index 00000000..f1f56551 --- /dev/null +++ b/changelog.d/splashscreen.add @@ -0,0 +1 @@ +Splash screen + loading indicator to make process of identifying initialization issues and load performance -- cgit v1.2.3-70-g09d2