diff --git a/changelog.d/migrate-auth-flow-pinia.skip b/changelog.d/migrate-auth-flow-pinia.skip deleted file mode 100644 index e69de29bb..000000000 diff --git a/changelog.d/small-fixes.skip b/changelog.d/small-fixes.skip deleted file mode 100644 index e69de29bb..000000000 diff --git a/changelog.d/unify-show-hide-buttons.add b/changelog.d/unify-show-hide-buttons.add deleted file mode 100644 index 663bc38a5..000000000 --- a/changelog.d/unify-show-hide-buttons.add +++ /dev/null @@ -1 +0,0 @@ -Unify show/hide content buttons diff --git a/index.html b/index.html index 86d15971b..f279ed01a 100644 --- a/index.html +++ b/index.html @@ -135,7 +135,6 @@ - diff --git a/src/boot/after_store.js b/src/boot/after_store.js index 05ddda982..39fc6f6f0 100644 --- a/src/boot/after_store.js +++ b/src/boot/after_store.js @@ -21,7 +21,6 @@ import { useOAuthStore } from 'src/stores/oauth' import { useI18nStore } from 'src/stores/i18n' import { useInterfaceStore } from 'src/stores/interface' import { useAnnouncementsStore } from 'src/stores/announcements' -import { useAuthFlowStore } from 'src/stores/auth_flow' let staticInitialResults = null @@ -157,7 +156,7 @@ const setSettings = async ({ apiConfig, staticConfig, store }) => { : config.logoMargin }) copyInstanceOption('logoLeft') - useAuthFlowStore().setInitialStrategy(config.loginMethod) + store.commit('authFlow/setInitialStrategy', config.loginMethod) copyInstanceOption('redirectRootNoLogin') copyInstanceOption('redirectRootLogin') diff --git a/src/components/auth_form/auth_form.js b/src/components/auth_form/auth_form.js index 243cbf574..a86a3dca2 100644 --- a/src/components/auth_form/auth_form.js +++ b/src/components/auth_form/auth_form.js @@ -2,8 +2,7 @@ import { h, resolveComponent } from 'vue' import LoginForm from '../login_form/login_form.vue' import MFARecoveryForm from '../mfa_form/recovery_form.vue' import MFATOTPForm from '../mfa_form/totp_form.vue' -import { mapState } from 'pinia' -import { useAuthFlowStore } from 'src/stores/auth_flow' +import { mapGetters } from 'vuex' const AuthForm = { name: 'AuthForm', @@ -16,7 +15,7 @@ const AuthForm = { if (this.requiredRecovery) { return 'MFARecoveryForm' } return 'LoginForm' }, - ...mapState(useAuthFlowStore, ['requiredTOTP', 'requiredRecovery']) + ...mapGetters('authFlow', ['requiredTOTP', 'requiredRecovery']) }, components: { MFARecoveryForm, diff --git a/src/components/color_input/color_input.vue b/src/components/color_input/color_input.vue index bcdf435fc..26b67cfe8 100644 --- a/src/components/color_input/color_input.vue +++ b/src/components/color_input/color_input.vue @@ -26,7 +26,7 @@ class="textColor unstyled" :class="{ disabled: !present || disabled }" type="text" - :value="modelValue ?? fallback" + :value="modelValue || fallback" :disabled="!present || disabled" @input="updateValue($event.target.value)" > diff --git a/src/components/login_form/login_form.js b/src/components/login_form/login_form.js index 9566aa903..ed3f5dfc6 100644 --- a/src/components/login_form/login_form.js +++ b/src/components/login_form/login_form.js @@ -1,8 +1,7 @@ -import { mapState } from 'vuex' -import { mapStores, mapActions, mapState as mapPiniaState } from 'pinia' +import { mapState, mapGetters, mapActions, mapMutations } from 'vuex' +import { mapStores } from 'pinia' import oauthApi from '../../services/new_api/oauth.js' import { useOAuthStore } from 'src/stores/oauth.js' -import { useAuthFlowStore } from 'src/stores/auth_flow.js' import { library } from '@fortawesome/fontawesome-svg-core' import { faTimes @@ -26,10 +25,13 @@ const LoginForm = { instance: state => state.instance, loggingIn: state => state.users.loggingIn, }), - ...mapPiniaState(useAuthFlowStore, ['requiredPassword', 'requiredToken', 'requiredMFA']) + ...mapGetters( + 'authFlow', ['requiredPassword', 'requiredToken', 'requiredMFA'] + ) }, methods: { - ...mapActions(useAuthFlowStore, ['requireMFA', 'login']), + ...mapMutations('authFlow', ['requireMFA']), + ...mapActions({ login: 'authFlow/login' }), submit () { this.isTokenAuth ? this.submitToken() : this.submitPassword() }, diff --git a/src/components/mfa_form/recovery_form.js b/src/components/mfa_form/recovery_form.js index 84479b1ec..2d0f4fdff 100644 --- a/src/components/mfa_form/recovery_form.js +++ b/src/components/mfa_form/recovery_form.js @@ -1,8 +1,7 @@ import mfaApi from '../../services/new_api/mfa.js' -import { mapState } from 'vuex' -import { mapStores, mapActions, mapState as mapPiniaState } from 'pinia' +import { mapState, mapGetters, mapActions, mapMutations } from 'vuex' +import { mapStores } from 'pinia' import { useOAuthStore } from 'src/stores/oauth.js' -import { useAuthFlowStore } from 'src/stores/auth_flow.js' import { library } from '@fortawesome/fontawesome-svg-core' import { faTimes @@ -18,8 +17,8 @@ export default { error: false }), computed: { - ...mapPiniaState(useAuthFlowStore, { - authSettings: store => store.settings + ...mapGetters({ + authSettings: 'authFlow/settings' }), ...mapStores(useOAuthStore), ...mapState({ @@ -27,7 +26,8 @@ export default { }) }, methods: { - ...mapActions(useAuthFlowStore, ['requireTOTP', 'abortMFA', 'login']), + ...mapMutations('authFlow', ['requireTOTP', 'abortMFA']), + ...mapActions({ login: 'authFlow/login' }), clearError () { this.error = false }, focusOnCodeInput () { diff --git a/src/components/mfa_form/totp_form.js b/src/components/mfa_form/totp_form.js index e369d8a5d..857d055ff 100644 --- a/src/components/mfa_form/totp_form.js +++ b/src/components/mfa_form/totp_form.js @@ -1,8 +1,7 @@ import mfaApi from '../../services/new_api/mfa.js' -import { mapState } from 'vuex' -import { mapStores, mapActions, mapState as mapPiniaState } from 'pinia' +import { mapState, mapGetters, mapActions, mapMutations } from 'vuex' +import { mapStores } from 'pinia' import { useOAuthStore } from 'src/stores/oauth.js' -import { useAuthFlowStore } from 'src/stores/auth_flow.js' import { library } from '@fortawesome/fontawesome-svg-core' import { faTimes @@ -18,8 +17,8 @@ export default { error: false }), computed: { - ...mapPiniaState(useAuthFlowStore, { - authSettings: store => store.settings + ...mapGetters({ + authSettings: 'authFlow/settings' }), ...mapStores(useOAuthStore), ...mapState({ @@ -27,7 +26,8 @@ export default { }) }, methods: { - ...mapActions(useAuthFlowStore, ['requireRecovery', 'abortMFA', 'login']), + ...mapMutations('authFlow', ['requireRecovery', 'abortMFA']), + ...mapActions({ login: 'authFlow/login' }), clearError () { this.error = false }, focusOnCodeInput () { diff --git a/src/components/settings_modal/tabs/style_tab/style_tab.js b/src/components/settings_modal/tabs/style_tab/style_tab.js index 82c63f503..8324263cd 100644 --- a/src/components/settings_modal/tabs/style_tab/style_tab.js +++ b/src/components/settings_modal/tabs/style_tab/style_tab.js @@ -372,9 +372,6 @@ export default { const path = getPath(component, directive) usedRule = get(real, path) // get real - if (usedRule === '') { - return usedRule - } if (!usedRule) { usedRule = get(fallback, path) } @@ -382,7 +379,7 @@ export default { return postProcess(usedRule) }, set (value) { - if (value != null) { + if (value) { set(allEditedRules.value, getPath(component, directive), value) } else { unset(allEditedRules.value, getPath(component, directive)) diff --git a/src/components/status_body/status_body.js b/src/components/status_body/status_body.js index aa334499e..b8f6f9a0b 100644 --- a/src/components/status_body/status_body.js +++ b/src/components/status_body/status_body.js @@ -72,23 +72,6 @@ const StatusContent = { hideTallStatus () { return this.mightHideBecauseTall && !this.showingTall }, - shouldShowToggle () { - return this.mightHideBecauseSubject || this.mightHideBecauseTall - }, - toggleButtonClasses () { - return { - 'cw-status-hider': !this.showingMore && this.mightHideBecauseSubject, - 'tall-status-hider': !this.showingMore && this.mightHideBecauseTall, - 'status-unhider': this.showingMore, - } - }, - toggleText () { - if (this.showingMore) { - return this.mightHideBecauseSubject ? this.$t('status.hide_content') : this.$t('general.show_less') - } else { - return this.mightHideBecauseSubject ? this.$t('status.show_content') : this.$t('general.show_more') - } - }, showingMore () { return (this.mightHideBecauseTall && this.showingTall) || (this.mightHideBecauseSubject && this.expandingSubject) }, diff --git a/src/components/status_body/status_body.scss b/src/components/status_body/status_body.scss index f89ea8d89..07fc8ef45 100644 --- a/src/components/status_body/status_body.scss +++ b/src/components/status_body/status_body.scss @@ -62,6 +62,7 @@ &.-tall-status { position: relative; height: 16em; + overflow: hidden; z-index: 1; .media-body { @@ -81,10 +82,6 @@ mask-composite: exclude; } } - - &.-expanded { - overflow: visible; - } } & .tall-status-hider, @@ -98,13 +95,6 @@ text-align: center; } - .status-unhider { - margin-top: auto; - position: sticky; - bottom: 0; - padding-bottom: 1em; - } - .tall-status-hider { position: absolute; height: 5em; @@ -128,10 +118,6 @@ } } - .toggle-button { - padding: 0.5em; - } - &.-compact { align-items: start; flex-direction: row; @@ -180,11 +166,11 @@ line-height: inherit; margin: 0; border: none; + display: inline-block; } .text-wrapper { display: inline-block; - width: 100%; } } } diff --git a/src/components/status_body/status_body.vue b/src/components/status_body/status_body.vue index 0fc024b04..16894021b 100644 --- a/src/components/status_body/status_body.vue +++ b/src/components/status_body/status_body.vue @@ -31,9 +31,17 @@
+ - + {{ $t("status.show_content") }} + + + + + + + +
diff --git a/src/modules/auth_flow.js b/src/modules/auth_flow.js new file mode 100644 index 000000000..dfa673db9 --- /dev/null +++ b/src/modules/auth_flow.js @@ -0,0 +1,86 @@ +import { useOAuthStore } from 'src/stores/oauth.js' + +const PASSWORD_STRATEGY = 'password' +const TOKEN_STRATEGY = 'token' + +// MFA strategies +const TOTP_STRATEGY = 'totp' +const RECOVERY_STRATEGY = 'recovery' + +// initial state +const state = { + settings: {}, + strategy: PASSWORD_STRATEGY, + initStrategy: PASSWORD_STRATEGY // default strategy from config +} + +const resetState = (state) => { + state.strategy = state.initStrategy + state.settings = {} +} + +// getters +const getters = { + settings: (state) => { + return state.settings + }, + requiredPassword: (state) => { + return state.strategy === PASSWORD_STRATEGY + }, + requiredToken: (state) => { + return state.strategy === TOKEN_STRATEGY + }, + requiredTOTP: (state) => { + return state.strategy === TOTP_STRATEGY + }, + requiredRecovery: (state) => { + return state.strategy === RECOVERY_STRATEGY + } +} + +// mutations +const mutations = { + setInitialStrategy (state, strategy) { + if (strategy) { + state.initStrategy = strategy + state.strategy = strategy + } + }, + requirePassword (state) { + state.strategy = PASSWORD_STRATEGY + }, + requireToken (state) { + state.strategy = TOKEN_STRATEGY + }, + requireMFA (state, { settings }) { + state.settings = settings + state.strategy = TOTP_STRATEGY // default strategy of MFA + }, + requireRecovery (state) { + state.strategy = RECOVERY_STRATEGY + }, + requireTOTP (state) { + state.strategy = TOTP_STRATEGY + }, + abortMFA (state) { + resetState(state) + } +} + +// actions +const actions = { + + async login ({ state, dispatch }, { access_token: accessToken }) { + useOAuthStore().setToken(accessToken) + await dispatch('loginUser', accessToken, { root: true }) + resetState(state) + } +} + +export default { + namespaced: true, + state, + getters, + mutations, + actions +} diff --git a/src/modules/index.js b/src/modules/index.js index fd233585d..7f0aa3706 100644 --- a/src/modules/index.js +++ b/src/modules/index.js @@ -6,6 +6,7 @@ import api from './api.js' import config from './config.js' import profileConfig from './profileConfig.js' import adminSettings from './adminSettings.js' +import authFlow from './auth_flow.js' import drafts from './drafts.js' import chats from './chats.js' @@ -18,6 +19,7 @@ export default { config, profileConfig, adminSettings, + authFlow, drafts, chats } diff --git a/src/services/style_setter/style_setter.js b/src/services/style_setter/style_setter.js index ef4a6f5c4..13606cdd9 100644 --- a/src/services/style_setter/style_setter.js +++ b/src/services/style_setter/style_setter.js @@ -242,7 +242,7 @@ export const applyConfig = (input) => { .map(([k, v]) => `--${k}: ${v}`).join(';') document.getElementById('style-config')?.remove() - const styleEl = document.getElementById('theme-holder') + const styleEl = document.createElement('style') styleEl.id = 'style-config' head.appendChild(styleEl) const styleSheet = styleEl.sheet diff --git a/src/stores/auth_flow.js b/src/stores/auth_flow.js deleted file mode 100644 index e41a9bc5e..000000000 --- a/src/stores/auth_flow.js +++ /dev/null @@ -1,69 +0,0 @@ -import { useOAuthStore } from 'src/stores/oauth.js' -import { defineStore } from 'pinia' - -const PASSWORD_STRATEGY = 'password' -const TOKEN_STRATEGY = 'token' - -// MFA strategies -const TOTP_STRATEGY = 'totp' -const RECOVERY_STRATEGY = 'recovery' - -export const useAuthFlowStore = defineStore('authFlow', { - // initial state - state: () => ({ - settings: {}, - strategy: PASSWORD_STRATEGY, - initStrategy: PASSWORD_STRATEGY // default strategy from config - }), - // getters - getters: { - requiredPassword: (state) => { - return state.strategy === PASSWORD_STRATEGY - }, - requiredToken: (state) => { - return state.strategy === TOKEN_STRATEGY - }, - requiredTOTP: (state) => { - return state.strategy === TOTP_STRATEGY - }, - requiredRecovery: (state) => { - return state.strategy === RECOVERY_STRATEGY - }, - }, - actions: { - setInitialStrategy (strategy) { - if (strategy) { - this.initStrategy = strategy - this.strategy = strategy - } - }, - requirePassword () { - this.strategy = PASSWORD_STRATEGY - }, - requireToken () { - this.strategy = TOKEN_STRATEGY - }, - requireMFA ({ settings }) { - this.settings = settings - this.strategy = TOTP_STRATEGY // default strategy of MFA - }, - requireRecovery () { - this.strategy = RECOVERY_STRATEGY - }, - requireTOTP () { - this.strategy = TOTP_STRATEGY - }, - abortMFA () { - this.resetState() - }, - resetState () { - this.strategy = this.initStrategy - this.settings = {} - }, - async login ({ access_token: accessToken }) { - useOAuthStore().setToken(accessToken) - await window.vuex.dispatch('loginUser', accessToken, { root: true }) - this.resetState() - } - } -}) \ No newline at end of file diff --git a/src/sw.js b/src/sw.js index 834c68e7f..7ba910589 100644 --- a/src/sw.js +++ b/src/sw.js @@ -223,8 +223,7 @@ self.addEventListener('fetch', (event) => { // Do not mess up with remote things const isSameOrigin = (new URL(event.request.url)).origin === self.location.origin if (shouldCache && event.request.method === 'GET' && isSameOrigin && isNotMedia(event.request)) { - // this is a bit spammy - // console.debug('[Service worker] fetch:', event.request.url) + console.debug('[Service worker] fetch:', event.request.url) event.respondWith((async () => { const r = await caches.match(event.request) const isEmojiReq = isEmoji(event.request)