commit: 00df9c9c32832feea80d6cd6d66c69fabacfab42
parent 8ee51229090ba323ceacf2cb8c6b50f2b1309560
Author: Henry Jameson <me@hjkos.com>
Date: Mon, 16 Sep 2024 02:34:02 +0300
initial splashscreen implementation
Diffstat:
9 files changed, 238 insertions(+), 16 deletions(-)
diff --git a/index.html b/index.html
@@ -8,9 +8,99 @@
<style id="pleroma-lazy-styles" type="text/css"></style>
<!--server-generated-meta-->
</head>
- <body class="hidden">
+ <body style="margin: 0; padding: 0">
<noscript>To use Pleroma, please enable JavaScript.</noscript>
- <div id="app"></div>
+ <!-- putting styles here to avoid having to wait for styles to load up -->
+ <div id="splash" style="
+ width: 100vw;
+ height: 100vh;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-direction: column;
+ background: #0f161e;
+ font-family: sans-serif;
+ color: #b9b9ba;
+ position: absolute;
+ "
+ >
+ <img
+ style="
+ width: 30vh";
+ margin-top: 1vh;
+ margin-bottom: 0.5vh;
+ "
+ src="/static/pleromatan_apology_fox.png"
+ />
+ <div
+ id="throbber"
+ style='
+ --logoChunkSize: 2vh;
+ display: grid;
+ margin-top: 2.5vh;
+ margin-bottom: 0.5vh;
+ width: 30vw;
+ grid-template-rows: repeat(8, var(--logoChunkSize));
+ grid-template-columns: repeat(5, var(--logoChunkSize));
+ grid-template-areas: "P P . L L"
+ "P P . L L"
+ "P P . L L"
+ "P P . L L"
+ "P P . . ."
+ "P P . . ."
+ "P P . E E"
+ "P P . E E";
+ width: auto;
+ '
+ >
+ <div
+ style="
+ background-color: #e2b188;
+ grid-area: P;
+ border-top-left-radius: calc(var(--logoChunkSize) / 2);
+ box-shadow: 0.1vh 0.1vh 1vh 0 #e2b188;
+ "
+ >
+ </div>
+ <div
+ style="
+ width: 100%;
+ height: 100%;
+ background-color: #e2b188;
+ grid-area: L;
+ border-bottom-right-radius: calc(var(--logoChunkSize) / 2);
+ box-shadow: 0.1vh 0.1vh 1vh 0 #e2b188;
+ "
+ >
+ </div>
+ <div
+ style="
+ width: 100%;
+ height: 100%;
+ background-color: #e2b188;
+ grid-area: E;
+ border-bottom-right-radius: calc(var(--logoChunkSize) / 2);
+ box-shadow: 0.1vh 0.1vh 1vh 0 #e2b188;
+ "
+ >
+ </div>
+ </div>
+ <div
+ id="status"
+ class="css-ok"
+ style="
+ margin-top: 3.5vh;
+ height: 4vh;
+ line-height: 4vh;
+ font-size: 4vh;
+ width: 100%;
+ text-align: center;
+ "
+ >
+ <span class="initial-text">(。>﹏<)</span>
+ </div>
+ </div>
+ <div id="app" class="hidden"></div>
<div id="modal"></div>
<!-- built files will be auto injected -->
<div id="popovers" />
diff --git 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -0,0 +1 @@
+/home/bocchi/Repos/Mine/pleroma-fe/src/assets/pleromatan_apology_fox.png
+\ No newline at end of file