diff --git a/src/components/settings_modal/admin_tabs/emoji_tab.js b/src/components/settings_modal/admin_tabs/emoji_tab.js index 585254a9b..7f575bcb4 100644 --- a/src/components/settings_modal/admin_tabs/emoji_tab.js +++ b/src/components/settings_modal/admin_tabs/emoji_tab.js @@ -8,6 +8,7 @@ import Popover from 'components/popover/popover.vue' import ConfirmModal from 'components/confirm_modal/confirm_modal.vue' import ModifiedIndicator from '../helpers/modified_indicator.vue' import EmojiEditingPopover from '../helpers/emoji_editing_popover.vue' +import { useInterfaceStore } from 'src/stores/interface' const EmojiTab = { components: { @@ -232,7 +233,7 @@ const EmojiTab = { }) }, displayError (msg) { - this.$store.useInterfaceStore().pushGlobalNotice({ + useInterfaceStore().pushGlobalNotice({ messageKey: 'admin_dash.emoji.error', messageArgs: [msg], level: 'error' diff --git a/src/components/settings_modal/admin_tabs/frontends_tab.js b/src/components/settings_modal/admin_tabs/frontends_tab.js index 6d983104b..a9a4777da 100644 --- a/src/components/settings_modal/admin_tabs/frontends_tab.js +++ b/src/components/settings_modal/admin_tabs/frontends_tab.js @@ -5,6 +5,7 @@ import StringSetting from '../helpers/string_setting.vue' import GroupSetting from '../helpers/group_setting.vue' import Popover from 'src/components/popover/popover.vue' import PanelLoading from 'src/components/panel_loading/panel_loading.vue' +import { useInterfaceStore } from 'src/stores/interface' import SharedComputedObject from '../helpers/shared_computed_object.js' import { library } from '@fortawesome/fontawesome-svg-core' @@ -80,7 +81,7 @@ const FrontendsTab = { this.$store.dispatch('loadFrontendsStuff') if (response.error) { const reason = await response.error.json() - this.$store.useInterfaceStore().pushGlobalNotice({ + useInterfaceStore().pushGlobalNotice({ level: 'error', messageKey: 'admin_dash.frontend.failure_installing_frontend', messageArgs: { @@ -90,7 +91,7 @@ const FrontendsTab = { timeout: 5000 }) } else { - this.$store.useInterfaceStore().pushGlobalNotice({ + useInterfaceStore().pushGlobalNotice({ level: 'success', messageKey: 'admin_dash.frontend.success_installing_frontend', messageArgs: { diff --git a/src/components/settings_modal/tabs/appearance_tab.js b/src/components/settings_modal/tabs/appearance_tab.js index da72c8f55..fd18b91e5 100644 --- a/src/components/settings_modal/tabs/appearance_tab.js +++ b/src/components/settings_modal/tabs/appearance_tab.js @@ -315,7 +315,7 @@ const AppearanceTab = { }, onImportFailure (result) { console.error('Failure importing theme:', result) - this.$store.useInterfaceStore().pushGlobalNotice({ messageKey: 'settings.invalid_theme_imported', level: 'error' }) + useInterfaceStore().pushGlobalNotice({ messageKey: 'settings.invalid_theme_imported', level: 'error' }) }, importValidator (parsed, filename) { if (filename.endsWith('.json')) { diff --git a/src/components/settings_modal/tabs/filtering_tab.js b/src/components/settings_modal/tabs/filtering_tab.js index 34ade4dfc..3345cb0c9 100644 --- a/src/components/settings_modal/tabs/filtering_tab.js +++ b/src/components/settings_modal/tabs/filtering_tab.js @@ -1,8 +1,15 @@ import { cloneDeep } from 'lodash' import { mapState, mapActions } from 'pinia' -import { useServerSideStorageStore } from 'src/stores/serverSideStorage' import { v4 as uuidv4 } from 'uuid'; +import { useServerSideStorageStore } from 'src/stores/serverSideStorage' +import { useInterfaceStore } from 'src/stores/interface' + +import { + newImporter, + newExporter +} from 'src/services/export_import/export_import.js' + import BooleanSetting from '../helpers/boolean_setting.vue' import ChoiceSetting from '../helpers/choice_setting.vue' import UnitSetting from '../helpers/unit_setting.vue' @@ -13,9 +20,10 @@ import Select from 'src/components/select/select.vue' import SharedComputedObject from '../helpers/shared_computed_object.js' +const SUPPORTED_TYPES = new Set(['word', 'regexp', 'user', 'user_regexp']) + const FilteringTab = { data () { - console.log(cloneDeep(useServerSideStorageStore().prefsStorage.simple.muteFilters)) return { replyVisibilityOptions: ['all', 'following', 'self'].map(mode => ({ key: mode, @@ -27,7 +35,44 @@ const FilteringTab = { Object.entries( useServerSideStorageStore().prefsStorage.simple.muteFilters ).map(([k]) => [k, false]) - ) + ), + exportedFilter: null, + filterImporter: newImporter({ + validator (parsed) { + if (Array.isArray(parsed)) return false + if (!SUPPORTED_TYPES.has(parsed.type)) return false + return true + }, + onImport: (data) => { + const { + enabled = true, + expires = null, + hide = false, + name = '', + value = '' + } = data + + this.createFilter({ + enabled, + expires, + hide, + name, + value + }) + }, + onImportFailure (result) { + console.error('Failure importing filter:', result) + useInterfaceStore() + .pushGlobalNotice({ + messageKey: 'settings.filter.import_failure', + level: 'error' + }) + } + }), + filterExporter: newExporter({ + filename: 'pleromafe_mute-filter', + getExportedObject: () => this.exportedFilter + }) } }, components: { @@ -83,22 +128,29 @@ const FilteringTab = { } return valid }, - createFilter () { - const filter = { - type: 'word', - value: '', - name: 'New Filter', - enabled: true, - expires: null, - hide: false, - order: this.muteFilters.length + 2 - } + createFilter (filter = { + type: 'word', + value: '', + name: 'New Filter', + enabled: true, + expires: null, + hide: false, + }) { const newId = uuidv4() + filter.order = this.muteFilters.length + 2 this.muteFiltersDraftObject[newId] = filter this.setPreference({ path: 'simple.muteFilters.' + newId , value: filter }) this.pushServerSideStorage() }, + exportFilter(id) { + this.exportedFilter = { ...this.muteFiltersDraftObject[id] } + delete this.exportedFilter.order + this.filterExporter.exportData() + }, + importFilter() { + this.filterImporter.importData() + }, copyFilter (id) { const filter = { ...this.muteFiltersDraftObject[id] } const newId = uuidv4() @@ -131,14 +183,12 @@ const FilteringTab = { } this.muteFiltersDraftObject[id] = filter this.muteFiltersDraftDirty[id] = true - console.log(this.muteFiltersDraftDirty) }, saveFilter(id) { this.setPreference({ path: 'simple.muteFilters.' + id , value: this.muteFiltersDraftObject[id] }) this.pushServerSideStorage() this.muteFiltersDraftDirty[id] = false - console.log(this.muteFiltersDraftDirty) - } + }, }, // Updating nested properties watch: { diff --git a/src/components/settings_modal/tabs/filtering_tab.scss b/src/components/settings_modal/tabs/filtering_tab.scss index 6346654b9..3f3fa3b58 100644 --- a/src/components/settings_modal/tabs/filtering_tab.scss +++ b/src/components/settings_modal/tabs/filtering_tab.scss @@ -12,7 +12,7 @@ margin: 0.5em; padding: 0.5em; display: grid; - grid-template-columns: fit-content() 1fr fit-content(); + grid-template-columns: fit-content 1fr fit-content; align-items: baseline; grid-gap: 0.5em; } @@ -33,6 +33,7 @@ grid-column: 3; grid-row: 1; text-align: right; + line-height: 2; } .filter-field { @@ -55,5 +56,21 @@ .filter-buttons { grid-column: 1 / span 3; justify-self: end; + display: inline-grid; + grid-gap: 0.5em; + grid-template-columns: repeat(4, 1fr); + max-width: 100%; + justify-content: end; + } + + .total { + text-align: center; + } +} + + +.settings-modal.-mobile .filtering-tab { + .filter-buttons { + grid-template-columns: repeat(1, 1fr); } } diff --git a/src/components/settings_modal/tabs/filtering_tab.vue b/src/components/settings_modal/tabs/filtering_tab.vue index f7754090b..968a7a0e7 100644 --- a/src/components/settings_modal/tabs/filtering_tab.vue +++ b/src/components/settings_modal/tabs/filtering_tab.vue @@ -73,232 +73,245 @@