diff --git a/src/components/settings_modal/tabs/general_tab.js b/src/components/settings_modal/tabs/general_tab.js index 025d7f1e..935591dc 100644 --- a/src/components/settings_modal/tabs/general_tab.js +++ b/src/components/settings_modal/tabs/general_tab.js @@ -8,11 +8,12 @@ import SharedComputedObject from '../helpers/shared_computed_object.js' import ServerSideIndicator from '../helpers/server_side_indicator.vue' import { library } from '@fortawesome/fontawesome-svg-core' import { - faGlobe + faGlobe, faSync } from '@fortawesome/free-solid-svg-icons' library.add( - faGlobe + faGlobe, + faSync ) const GeneralTab = { @@ -104,7 +105,8 @@ const GeneralTab = { return this.$store.getters.mergedConfig.profileVersion }, translationLanguages () { - return (this.$store.state.instance.supportedTranslationLanguages.target || []).map(lang => ({ key: lang.code, value: lang.code, label: lang.name })) + const langs = this.$store.state.instance.translationLanguages || [] + return (langs || []).map(lang => ({ key: lang.code, value: lang.code, label: lang.name })) }, translationLanguage: { get: function () { return this.$store.getters.mergedConfig.translationLanguage }, @@ -133,6 +135,17 @@ const GeneralTab = { this.$store.dispatch('setOption', { name: 'profileVersion', value: 1 }) this.$store.dispatch('syncSettings') this.newProfileName = '' + }, + forceSync () { + this.$store.dispatch('getSettingsProfile') + }, + refreshProfiles () { + this.$store.dispatch('listSettingsProfiles') + }, + deleteSettingsProfile (name) { + if (confirm(this.$t('settings.settings_profile_delete_confirm'))) { + this.$store.dispatch('deleteSettingsProfile', name) + } } } } diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue index 479cb1d3..2c7c6c01 100644 --- a/src/components/settings_modal/tabs/general_tab.vue +++ b/src/components/settings_modal/tabs/general_tab.vue @@ -13,7 +13,16 @@ v-if="user && (settingsProfiles.length > 0)" > <h2>{{ $t('settings.settings_profile') }}</h2> - <p>{{ $t('settings.settings_profile_currently', { name: settingsProfile, version: settingsVersion }) }}</p> + <p> + {{ $t('settings.settings_profile_currently', { name: settingsProfile, version: settingsVersion }) }} + <button + class="btn button-default" + @click="forceSync()" + > + {{ $t('settings.settings_profile_force_sync') }} + </button> + + </p> <div @click="toggleExpandedSettings" > @@ -36,6 +45,7 @@ <template v-if="profilesExpanded" > + <div v-for="profile in settingsProfiles" :key="profile.id" @@ -45,21 +55,31 @@ <template v-if="settingsProfile === profile.name" > - {{ $t('settings.settings_profile_in_use') }} + {{ $t('settings.settings_profile_in_use') }} </template> <template v-else - > + > <button class="btn button-default" @click="loadSettingsProfile(profile.name)" > {{ $t('settings.settings_profile_use') }} </button> + <button + class="btn button-default" + @click="deleteSettingsProfile(profile.name)" + > + {{ $t('settings.settings_profile_delete') }} + </button> </template> </div> + <button class="btn button-default" @click="refreshProfiles()"> + {{ $t('settings.settings_profiles_refresh') }} + <FAIcon icon="sync" @click="refreshProfiles()" /> + </button> <h3>{{ $t('settings.settings_profile_creation') }}</h3> - <input v-model="newProfileName" /> + <input v-model="newProfileName"> <button class="btn button-default" @click="createSettingsProfile" diff --git a/src/i18n/en.json b/src/i18n/en.json index 750b41c2..5b68a5b0 100644 --- a/src/i18n/en.json +++ b/src/i18n/en.json @@ -701,6 +701,10 @@ "settings_profile_creation": "Create new profile", "settings_profile_creation_submit": "Create", "settings_profile_use": "Use", + "settings_profile_delete": "Delete", + "settings_profile_delete_confirm": "Do you really want to delete this profile?", + "settings_profile_force_sync": "Synchronize", + "settings_profiles_refresh": "Reload settings profiles", "show_admin_badge": "Show \"Admin\" badge in my profile", "show_moderator_badge": "Show \"Moderator\" badge in my profile", "show_nav_shortcuts": "Show extra navigation shortcuts in top panel", @@ -903,7 +907,8 @@ "settings_profile": { "synchronizing": "Synchronizing setting profile \"{profile}\"...", "synchronized": "Synchronized settings!", - "synchronization_error": "Could not synchronize settings: {err}" + "synchronization_error": "Could not synchronize settings: {err}", + "creating": "Creating new setting profile \"{profile}\"..." }, "status": { "ancestor_follow": "See {numReplies} other reply under this post | See {numReplies} other replies under this post", diff --git a/src/modules/config.js b/src/modules/config.js index 81ebb031..e30bd1ff 100644 --- a/src/modules/config.js +++ b/src/modules/config.js @@ -181,6 +181,7 @@ const config = { messageArgs: { profile: store.state.profile }, timeout: 2000 }) + store.dispatch('listSettingsProfiles') }).catch((err) => { store.dispatch('removeGlobalNotice', notice) store.dispatch('pushGlobalNotice', { @@ -192,6 +193,11 @@ const config = { console.error(err) }) }, + deleteSettingsProfile (store, name) { + store.rootState.api.backendInteractor.deleteSettingsProfile({ profileName: name }).then(() => { + store.dispatch('listSettingsProfiles') + }) + }, loadSettings ({ dispatch }, data) { const knownKeys = new Set(Object.keys(defaultState)) const presentKeys = new Set(Object.keys(data)) @@ -233,7 +239,6 @@ const config = { } }, getSettingsProfile (store, forceUpdate = false) { - console.log('getSettingsProfile') const profile = store.state.profile store.rootState.api.backendInteractor.getSettingsProfile({ store, profileName: profile }) .then(({ settings, version }) => { @@ -256,6 +261,7 @@ const config = { store.dispatch('pushGlobalNotice', { level: 'warning', messageKey: 'settings_profile.creating', + args: { profile }, timeout: 5000 }) store.dispatch('syncSettings') diff --git a/src/modules/users.js b/src/modules/users.js index 94321839..fb72a6a8 100644 --- a/src/modules/users.js +++ b/src/modules/users.js @@ -562,6 +562,8 @@ const users = { // Start fetching notifications store.dispatch('startFetchingNotifications') + + store.dispatch('startFetchingConfig') } if (store.getters.mergedConfig.useStreamingApi) { diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js index e7a8c812..2ed0f1ac 100644 --- a/src/services/api/api.service.js +++ b/src/services/api/api.service.js @@ -1472,6 +1472,14 @@ const saveSettingsProfile = ({ profileName, credentials, settings, version }) => }) } +const deleteSettingsProfile = ({ profileName, credentials }) => { + return promisedRequest({ + url: AKKOMA_SETTING_PROFILE_URL(profileName), + method: 'DELETE', + credentials + }) +} + const listSettingsProfiles = ({ credentials }) => { return promisedRequest({ url: AKKOMA_SETTING_PROFILE_LIST, @@ -1708,7 +1716,8 @@ const apiService = { getSupportedTranslationlanguages, getSettingsProfile, saveSettingsProfile, - listSettingsProfiles + listSettingsProfiles, + deleteSettingsProfile } export default apiService diff --git a/src/services/backend_interactor_service/backend_interactor_service.js b/src/services/backend_interactor_service/backend_interactor_service.js index bedc51b2..596151d8 100644 --- a/src/services/backend_interactor_service/backend_interactor_service.js +++ b/src/services/backend_interactor_service/backend_interactor_service.js @@ -4,6 +4,7 @@ import notificationsFetcher from '../notifications_fetcher/notifications_fetcher import followRequestFetcher from '../../services/follow_request_fetcher/follow_request_fetcher.service' import listsFetcher from '../../services/lists_fetcher/lists_fetcher.service.js' import announcementsFetcher from '../../services/announcements_fetcher/announcements_fetcher.service.js' +import configFetcher from '../config_fetcher/config_fetcher.service.js' const backendInteractorService = credentials => ({ startFetchingTimeline ({ timeline, store, userId = false, listId = false, tag }) { @@ -18,6 +19,10 @@ const backendInteractorService = credentials => ({ return notificationsFetcher.startFetching({ store, credentials }) }, + startFetchingConfig ({ store }) { + return configFetcher.startFetching({ store, credentials }) + }, + fetchNotifications (args) { return notificationsFetcher.fetchAndUpdate({ ...args, credentials }) }, diff --git a/src/services/config_fetcher/config_fetcher.service.js b/src/services/config_fetcher/config_fetcher.service.js new file mode 100644 index 00000000..2c6d07ee --- /dev/null +++ b/src/services/config_fetcher/config_fetcher.service.js @@ -0,0 +1,13 @@ +import { promiseInterval } from '../promise_interval/promise_interval.js' + +const startFetching = ({ credentials, store }) => { + const boundFetchAndUpdate = () => store.dispatch('getSettingsProfile') + boundFetchAndUpdate() + return promiseInterval(boundFetchAndUpdate, 5 * 60000) +} + +const configFetcher = { + startFetching +} + +export default configFetcher