From a044dc377e77aade4696984fb42f7aa5db8c2561 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Thu, 12 Sep 2024 15:47:48 +0300 Subject: Massively upgraded shadow control, added sorting by specificity in themes3, added/fixed disabled inputs --- src/i18n/en.json | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/i18n') diff --git a/src/i18n/en.json b/src/i18n/en.json index 3f7ea282..b27c36d7 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -870,6 +870,9 @@ "component": "Component", "override": "Override", "shadow_id": "Shadow #{value}", + "offset": "Shadow offset", + "light_grid": "Use light checkerboard", + "name": "Name", "blur": "Blur", "spread": "Spread", "inset": "Inset", -- cgit v1.2.3-70-g09d2 From aa7a3361833f4c88ec685c4a92ff7727ed7249a7 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Thu, 12 Sep 2024 19:31:19 +0300 Subject: Updated shadow control to be able to handle "absolute null" situation --- .../settings_modal/tabs/theme_tab/theme_tab.js | 14 ++- .../settings_modal/tabs/theme_tab/theme_tab.vue | 46 +------- src/components/shadow_control/shadow_control.js | 122 +++++++++++---------- src/components/shadow_control/shadow_control.scss | 17 ++- src/components/shadow_control/shadow_control.vue | 103 +++++++++++++---- src/i18n/en.json | 1 + src/services/theme_data/theme_data.service.js | 2 +- 7 files changed, 179 insertions(+), 126 deletions(-) (limited to 'src/i18n') diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.js b/src/components/settings_modal/tabs/theme_tab/theme_tab.js index 25836559..a295e880 100644 --- a/src/components/settings_modal/tabs/theme_tab/theme_tab.js +++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.js @@ -314,7 +314,18 @@ export default { }, set (val) { if (val) { - this.shadowsLocal[this.shadowSelected] = this.currentShadowFallback.map(_ => Object.assign({}, _)) + this.shadowsLocal[this.shadowSelected] = (this.currentShadowFallback || []) + .map(s => ({ + name: null, + x: 0, + y: 0, + blur: 0, + spread: 0, + inset: false, + color: '#000000', + alpha: 1, + ...s + })) } else { delete this.shadowsLocal[this.shadowSelected] } @@ -328,6 +339,7 @@ export default { return this.shadowsLocal[this.shadowSelected] }, set (v) { + console.log('TT', v) this.shadowsLocal[this.shadowSelected] = v } }, diff --git a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue index d975c61d..00a55832 100644 --- a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue +++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue @@ -937,24 +937,14 @@
- - {{ ' ' }} - -
@@ -141,11 +145,12 @@
diff --git a/src/i18n/en.json b/src/i18n/en.json index b27c36d7..1b67d4f7 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -880,6 +880,7 @@ "filter_hint": { "always_drop_shadow": "Warning, this shadow always uses {0} when browser supports it.", "drop_shadow_syntax": "{0} does not support {1} parameter and {2} keyword.", + "avatar_inset_short": "Separate inset shadow", "avatar_inset": "Please note that combining both inset and non-inset shadows on avatars might give unexpected results with transparent avatars.", "spread_zero": "Shadows with spread > 0 will appear as if it was set to zero", "inset_classic": "Inset shadows will be using {0}" diff --git a/src/services/theme_data/theme_data.service.js b/src/services/theme_data/theme_data.service.js index 2dddfa04..ef7ec645 100644 --- a/src/services/theme_data/theme_data.service.js +++ b/src/services/theme_data/theme_data.service.js @@ -452,7 +452,7 @@ export const getCssShadow = (input, usesDropShadow) => { ]).join(' ')).join(', ') } -const getCssShadowFilter = (input) => { +export const getCssShadowFilter = (input) => { if (input.length === 0) { return 'none' } -- cgit v1.2.3-70-g09d2 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 (limited to 'src/i18n') 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 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(-) (limited to 'src/i18n') 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 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 (limited to 'src/i18n') 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 6335a205c80336c70f4ac4d68e6f3ec305994070 Mon Sep 17 00:00:00 2001 From: Kian-ting Tan Date: Wed, 11 Sep 2024 12:34:58 +0000 Subject: Translated using Weblate (Chinese (Min Nan) (nan_TW)) Currently translated at 91.6% (1093 of 1193 strings) Translation: Pleroma/Pleroma-FE Translate-URL: https://translate.pleroma.social/projects/pleroma/pleroma-fe/nan_TW/ --- src/i18n/nan-TW.json | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) (limited to 'src/i18n') diff --git a/src/i18n/nan-TW.json b/src/i18n/nan-TW.json index 782a75f5..44a693dd 100644 --- a/src/i18n/nan-TW.json +++ b/src/i18n/nan-TW.json @@ -190,7 +190,8 @@ "mobile_notifications_close": "關掉通知", "announcements": "公告", "search": "Tshuē", - "mobile_notifications_mark_as_seen": "Lóng 標做有讀" + "mobile_notifications_mark_as_seen": "Lóng 標做有讀", + "quotes": "引用" }, "notifications": { "broken_favorite": "狀態毋知影,leh tshiau-tshuē……", @@ -212,7 +213,8 @@ "unread_follow_requests": "{num}ê新ê跟tuè請求", "configuration_tip": "用{theSettings},lí通自訂siánn物佇tsia顯示。{dismiss}", "configuration_tip_settings": "設定", - "configuration_tip_dismiss": "Mài koh顯示" + "configuration_tip_dismiss": "Mài koh顯示", + "subscribed_status": "有發送ê" }, "polls": { "add_poll": "開投票", @@ -252,7 +254,8 @@ }, "load_all_hint": "載入頭前 {saneAmount} ê 繪文字,規个攏載入效能可能 ē khah 食力。", "load_all": "Kā {emojiAmount} ê 繪文字攏載入", - "regional_indicator": "地區指引 {letter}" + "regional_indicator": "地區指引 {letter}", + "hide_custom_emoji": "Khàm掉自訂ê繪文字" }, "errors": { "storage_unavailable": "Pleroma buē-tàng the̍h 著瀏覽器儲存 ê。Lí ê 登入狀態抑是局部設定 buē 儲存,mā 凡勢 tú 著意料外 ê 問題。拍開 cookie 看māi。" @@ -263,7 +266,8 @@ "emoji_reactions": "繪文字 ê 反應", "reports": "檢舉", "moves": "用者 ê 移民", - "load_older": "載入 koh khah 早 ê 互動" + "load_older": "載入 koh khah 早 ê 互動", + "statuses": "訂ê" }, "post_status": { "edit_status": "編輯狀態", @@ -935,7 +939,34 @@ "notification_extra_chats": "顯示bô讀ê開講", "notification_extra_announcements": "顯示bô讀ê公告", "notification_extra_follow_requests": "顯示新ê跟tuè請求", - "notification_extra_tip": "顯示自訂其他通知ê撇步" + "notification_extra_tip": "顯示自訂其他通知ê撇步", + "confirm_new_setting": "Lí敢確認新ê設定?", + "text_size_tip": "用 {0} 做絕對值,{1} ē根據瀏覽器ê標準文字sài-suh放大縮小。", + "theme_debug": "佇處理透明ê時,顯示背景主題ia̋n-jín 所假使ê(DEBUG)", + "units": { + "time": { + "s": "秒鐘", + "m": "分鐘", + "h": "點鐘", + "d": "工" + } + }, + "actor_type": "Tsit ê口座是:", + "actor_type_Person": "一般ê用者", + "actor_type_description": "標記lí ê口座做群組,ē hōo自動轉送提起伊ê狀態。", + "actor_type_Group": "群組", + "actor_type_Service": "機器lâng", + "appearance": "外觀", + "confirm_new_question": "Tse看起來kám好?設定ē佇10秒鐘後改轉去。", + "revert": "改轉去", + "confirm": "確認", + "text_size": "文字kap界面ê sài-suh", + "text_size_tip2": "毋是 {0} ê值可能ē破壞一寡物件kap主題", + "emoji_size": "繪文字ê sài-suh", + "navbar_size": "頂 liâu-á êsài-suh", + "panel_header_size": "面pang標題ê sài-suh", + "visual_tweaks": "細細ê外觀調整", + "scale_and_layout": "界面ê sài-suh kap排列" }, "status": { "favorites": "收藏", @@ -1001,7 +1032,7 @@ "show_only_conversation_under_this": "Kan-ta顯示tsit ê狀態ê回應", "status_history": "狀態ê歷史", "reaction_count_label": "{num}ê lâng用表情反應", - "hide_quote": "Khàm條引用ê狀態", + "hide_quote": "Khàm掉引用ê狀態", "display_quote": "顯示引用ê狀態", "invisible_quote": "引用ê狀態bē當用:{link}", "more_actions": "佇tsit ê狀態ê其他動作" -- cgit v1.2.3-70-g09d2