diff options
Diffstat (limited to 'src/components/settings_modal')
18 files changed, 504 insertions, 266 deletions
diff --git a/src/components/settings_modal/helpers/boolean_setting.js b/src/components/settings_modal/helpers/boolean_setting.js new file mode 100644 index 00000000..5c52f697 --- /dev/null +++ b/src/components/settings_modal/helpers/boolean_setting.js @@ -0,0 +1,38 @@ +import { get, set } from 'lodash' +import Checkbox from 'src/components/checkbox/checkbox.vue' +import ModifiedIndicator from './modified_indicator.vue' +export default { + components: { + Checkbox, + ModifiedIndicator + }, + props: [ + 'path', + 'disabled' + ], + computed: { + pathDefault () { + const [firstSegment, ...rest] = this.path.split('.') + return [firstSegment + 'DefaultValue', ...rest].join('.') + }, + state () { + const value = get(this.$parent, this.path) + if (value === undefined) { + return this.defaultState + } else { + return value + } + }, + defaultState () { + return get(this.$parent, this.pathDefault) + }, + isChanged () { + return this.state !== this.defaultState + } + }, + methods: { + update (e) { + set(this.$parent, this.path, e) + } + } +} diff --git a/src/components/settings_modal/helpers/boolean_setting.vue b/src/components/settings_modal/helpers/boolean_setting.vue index 146ad6c1..c3ee6583 100644 --- a/src/components/settings_modal/helpers/boolean_setting.vue +++ b/src/components/settings_modal/helpers/boolean_setting.vue @@ -18,40 +18,4 @@ </label> </template> -<script> -import { get, set } from 'lodash' -import Checkbox from 'src/components/checkbox/checkbox.vue' -import ModifiedIndicator from './modified_indicator.vue' -export default { - components: { - Checkbox, - ModifiedIndicator - }, - props: [ - 'path', - 'disabled' - ], - computed: { - pathDefault () { - const [firstSegment, ...rest] = this.path.split('.') - return [firstSegment + 'DefaultValue', ...rest].join('.') - }, - state () { - return get(this.$parent, this.path) - }, - isChanged () { - return get(this.$parent, this.path) !== get(this.$parent, this.pathDefault) - } - }, - methods: { - update (e) { - set(this.$parent, this.path, e) - } - } -} -</script> - -<style lang="scss"> -.BooleanSetting { -} -</style> +<script src="./boolean_setting.js"></script> diff --git a/src/components/settings_modal/helpers/choice_setting.js b/src/components/settings_modal/helpers/choice_setting.js new file mode 100644 index 00000000..a15f6bac --- /dev/null +++ b/src/components/settings_modal/helpers/choice_setting.js @@ -0,0 +1,39 @@ +import { get, set } from 'lodash' +import Select from 'src/components/select/select.vue' +import ModifiedIndicator from './modified_indicator.vue' +export default { + components: { + Select, + ModifiedIndicator + }, + props: [ + 'path', + 'disabled', + 'options' + ], + computed: { + pathDefault () { + const [firstSegment, ...rest] = this.path.split('.') + return [firstSegment + 'DefaultValue', ...rest].join('.') + }, + state () { + const value = get(this.$parent, this.path) + if (value === undefined) { + return this.defaultState + } else { + return value + } + }, + defaultState () { + return get(this.$parent, this.pathDefault) + }, + isChanged () { + return this.state !== this.defaultState + } + }, + methods: { + update (e) { + set(this.$parent, this.path, e) + } + } +} diff --git a/src/components/settings_modal/helpers/choice_setting.vue b/src/components/settings_modal/helpers/choice_setting.vue new file mode 100644 index 00000000..fa17661b --- /dev/null +++ b/src/components/settings_modal/helpers/choice_setting.vue @@ -0,0 +1,29 @@ +<template> + <label + class="ChoiceSetting" + > + <slot /> + <Select + :value="state" + :disabled="disabled" + @change="update" + > + <option + v-for="option in options" + :key="option.key" + :value="option.value" + > + {{ option.label }} + {{ option.value === defaultState ? $t('settings.instance_default_simple') : '' }} + </option> + </Select> + <ModifiedIndicator :changed="isChanged" /> + </label> +</template> + +<script src="./choice_setting.js"></script> + +<style lang="scss"> +.ChoiceSetting { +} +</style> diff --git a/src/components/settings_modal/helpers/modified_indicator.vue b/src/components/settings_modal/helpers/modified_indicator.vue index 9f4e81fe..ad212db9 100644 --- a/src/components/settings_modal/helpers/modified_indicator.vue +++ b/src/components/settings_modal/helpers/modified_indicator.vue @@ -6,18 +6,18 @@ <Popover trigger="hover" > - <span slot="trigger"> + <template v-slot:trigger> <FAIcon icon="wrench" + :aria-label="$t('settings.setting_changed')" /> - </span> - <div - slot="content" - class="modified-tooltip" - > - {{ $t('settings.setting_changed') }} - </div> + </template> + <template v-slot:content> + <div class="modified-tooltip"> + {{ $t('settings.setting_changed') }} + </div> + </template> </Popover> </span> </template> diff --git a/src/components/settings_modal/settings_modal.js b/src/components/settings_modal/settings_modal.js index f0d49c91..04043483 100644 --- a/src/components/settings_modal/settings_modal.js +++ b/src/components/settings_modal/settings_modal.js @@ -2,10 +2,55 @@ import Modal from 'src/components/modal/modal.vue' import PanelLoading from 'src/components/panel_loading/panel_loading.vue' import AsyncComponentError from 'src/components/async_component_error/async_component_error.vue' import getResettableAsyncComponent from 'src/services/resettable_async_component.js' +import Popover from '../popover/popover.vue' +import { library } from '@fortawesome/fontawesome-svg-core' +import { cloneDeep } from 'lodash' +import { + newImporter, + newExporter +} from 'src/services/export_import/export_import.js' +import { + faTimes, + faFileUpload, + faFileDownload, + faChevronDown +} from '@fortawesome/free-solid-svg-icons' +import { + faWindowMinimize +} from '@fortawesome/free-regular-svg-icons' + +const PLEROMAFE_SETTINGS_MAJOR_VERSION = 1 +const PLEROMAFE_SETTINGS_MINOR_VERSION = 0 + +library.add( + faTimes, + faWindowMinimize, + faFileUpload, + faFileDownload, + faChevronDown +) const SettingsModal = { + data () { + return { + dataImporter: newImporter({ + validator: this.importValidator, + onImport: this.onImport, + onImportFailure: this.onImportFailure + }), + dataThemeExporter: newExporter({ + filename: 'pleromafe_settings.full', + getExportedObject: () => this.generateExport(true) + }), + dataExporter: newExporter({ + filename: 'pleromafe_settings', + getExportedObject: () => this.generateExport() + }) + } + }, components: { Modal, + Popover, SettingsModalContent: getResettableAsyncComponent( () => import('./settings_modal_content.vue'), { @@ -21,6 +66,85 @@ const SettingsModal = { }, peekModal () { this.$store.dispatch('togglePeekSettingsModal') + }, + importValidator (data) { + if (!Array.isArray(data._pleroma_settings_version)) { + return { + messageKey: 'settings.file_import_export.invalid_file' + } + } + + const [major, minor] = data._pleroma_settings_version + + if (major > PLEROMAFE_SETTINGS_MAJOR_VERSION) { + return { + messageKey: 'settings.file_export_import.errors.file_too_new', + messageArgs: { + fileMajor: major, + feMajor: PLEROMAFE_SETTINGS_MAJOR_VERSION + } + } + } + + if (major < PLEROMAFE_SETTINGS_MAJOR_VERSION) { + return { + messageKey: 'settings.file_export_import.errors.file_too_old', + messageArgs: { + fileMajor: major, + feMajor: PLEROMAFE_SETTINGS_MAJOR_VERSION + } + } + } + + if (minor > PLEROMAFE_SETTINGS_MINOR_VERSION) { + this.$store.dispatch('pushGlobalNotice', { + level: 'warning', + messageKey: 'settings.file_export_import.errors.file_slightly_new' + }) + } + + return true + }, + onImportFailure (result) { + if (result.error) { + this.$store.dispatch('pushGlobalNotice', { messageKey: 'settings.invalid_settings_imported', level: 'error' }) + } else { + this.$store.dispatch('pushGlobalNotice', { ...result.validationResult, level: 'error' }) + } + }, + onImport (data) { + if (data) { this.$store.dispatch('loadSettings', data) } + }, + restore () { + this.dataImporter.importData() + }, + backup () { + this.dataExporter.exportData() + }, + backupWithTheme () { + this.dataThemeExporter.exportData() + }, + generateExport (theme = false) { + const { config } = this.$store.state + let sample = config + if (!theme) { + const ignoreList = new Set([ + 'customTheme', + 'customThemeSource', + 'colors' + ]) + sample = Object.fromEntries( + Object + .entries(sample) + .filter(([key]) => !ignoreList.has(key)) + ) + } + const clone = cloneDeep(sample) + clone._pleroma_settings_version = [ + PLEROMAFE_SETTINGS_MAJOR_VERSION, + PLEROMAFE_SETTINGS_MINOR_VERSION + ] + return clone } }, computed: { diff --git a/src/components/settings_modal/settings_modal.vue b/src/components/settings_modal/settings_modal.vue index 552ca41f..583c2ecc 100644 --- a/src/components/settings_modal/settings_modal.vue +++ b/src/components/settings_modal/settings_modal.vue @@ -31,20 +31,84 @@ </transition> <button class="btn button-default" + :title="$t('general.peek')" @click="peekModal" > - {{ $t('general.peek') }} + <FAIcon + :icon="['far', 'window-minimize']" + fixed-width + /> </button> <button class="btn button-default" + :title="$t('general.close')" @click="closeModal" > - {{ $t('general.close') }} + <FAIcon + icon="times" + fixed-width + /> </button> </div> <div class="panel-body"> <SettingsModalContent v-if="modalOpenedOnce" /> </div> + <div class="panel-footer"> + <Popover + class="export" + trigger="click" + placement="top" + :offset="{ y: 5, x: 5 }" + :bound-to="{ x: 'container' }" + remove-padding + > + <template v-slot:trigger> + <button + class="btn button-default" + :title="$t('general.close')" + > + <span>{{ $t("settings.file_export_import.backup_restore") }}</span> + <FAIcon + icon="chevron-down" + /> + </button> + </template> + <template v-slot:content="{close}"> + <div class="dropdown-menu"> + <button + class="button-default dropdown-item dropdown-item-icon" + @click.prevent="backup" + @click="close" + > + <FAIcon + icon="file-download" + fixed-width + /><span>{{ $t("settings.file_export_import.backup_settings") }}</span> + </button> + <button + class="button-default dropdown-item dropdown-item-icon" + @click.prevent="backupWithTheme" + @click="close" + > + <FAIcon + icon="file-download" + fixed-width + /><span>{{ $t("settings.file_export_import.backup_settings_theme") }}</span> + </button> + <button + class="button-default dropdown-item dropdown-item-icon" + @click.prevent="restore" + @click="close" + > + <FAIcon + icon="file-upload" + fixed-width + /><span>{{ $t("settings.file_export_import.restore_settings") }}</span> + </button> + </div> + </template> + </Popover> + </div> </div> </Modal> </template> diff --git a/src/components/settings_modal/settings_modal_content.scss b/src/components/settings_modal/settings_modal_content.scss index f066234c..81ab434b 100644 --- a/src/components/settings_modal/settings_modal_content.scss +++ b/src/components/settings_modal/settings_modal_content.scss @@ -7,13 +7,24 @@ margin: 1em 1em 1.4em; padding-bottom: 1.4em; - > div { + > div, + > label { + display: block; margin-bottom: .5em; &:last-child { margin-bottom: 0; } } + .select-multiple { + display: flex; + + .option-list { + margin: 0; + padding-left: .5em; + } + } + &:last-child { border-bottom: none; padding-bottom: 0; diff --git a/src/components/settings_modal/tabs/filtering_tab.js b/src/components/settings_modal/tabs/filtering_tab.js index 6e95f7af..4eaf4217 100644 --- a/src/components/settings_modal/tabs/filtering_tab.js +++ b/src/components/settings_modal/tabs/filtering_tab.js @@ -1,24 +1,23 @@ import { filter, trim } from 'lodash' import BooleanSetting from '../helpers/boolean_setting.vue' +import ChoiceSetting from '../helpers/choice_setting.vue' import SharedComputedObject from '../helpers/shared_computed_object.js' -import { library } from '@fortawesome/fontawesome-svg-core' -import { - faChevronDown -} from '@fortawesome/free-solid-svg-icons' - -library.add( - faChevronDown -) const FilteringTab = { data () { return { - muteWordsStringLocal: this.$store.getters.mergedConfig.muteWords.join('\n') + muteWordsStringLocal: this.$store.getters.mergedConfig.muteWords.join('\n'), + replyVisibilityOptions: ['all', 'following', 'self'].map(mode => ({ + key: mode, + value: mode, + label: this.$t(`settings.reply_visibility_${mode}`) + })) } }, components: { - BooleanSetting + BooleanSetting, + ChoiceSetting }, computed: { ...SharedComputedObject(), diff --git a/src/components/settings_modal/tabs/filtering_tab.vue b/src/components/settings_modal/tabs/filtering_tab.vue index 402c2a4a..6fc9ceaa 100644 --- a/src/components/settings_modal/tabs/filtering_tab.vue +++ b/src/components/settings_modal/tabs/filtering_tab.vue @@ -36,29 +36,13 @@ </li> </ul> </div> - <div> + <ChoiceSetting + id="replyVisibility" + path="replyVisibility" + :options="replyVisibilityOptions" + > {{ $t('settings.replies_in_timeline') }} - <label - for="replyVisibility" - class="select" - > - <select - id="replyVisibility" - v-model="replyVisibility" - > - <option - value="all" - selected - >{{ $t('settings.reply_visibility_all') }}</option> - <option value="following">{{ $t('settings.reply_visibility_following') }}</option> - <option value="self">{{ $t('settings.reply_visibility_self') }}</option> - </select> - <FAIcon - class="select-down-icon" - icon="chevron-down" - /> - </label> - </div> + </ChoiceSetting> <div> <BooleanSetting path="hidePostStats"> {{ $t('settings.hide_post_stats') }} diff --git a/src/components/settings_modal/tabs/general_tab.js b/src/components/settings_modal/tabs/general_tab.js index 2db523be..eeda61bf 100644 --- a/src/components/settings_modal/tabs/general_tab.js +++ b/src/components/settings_modal/tabs/general_tab.js @@ -1,21 +1,25 @@ import BooleanSetting from '../helpers/boolean_setting.vue' +import ChoiceSetting from '../helpers/choice_setting.vue' import InterfaceLanguageSwitcher from 'src/components/interface_language_switcher/interface_language_switcher.vue' import SharedComputedObject from '../helpers/shared_computed_object.js' import { library } from '@fortawesome/fontawesome-svg-core' import { - faChevronDown, faGlobe } from '@fortawesome/free-solid-svg-icons' library.add( - faChevronDown, faGlobe ) const GeneralTab = { data () { return { + subjectLineOptions: ['email', 'noop', 'masto'].map(mode => ({ + key: mode, + value: mode, + label: this.$t(`settings.subject_line_${mode === 'masto' ? 'mastodon' : mode}`) + })), loopSilentAvailable: // Firefox Object.getOwnPropertyDescriptor(HTMLVideoElement.prototype, 'mozHasAudio') || @@ -27,17 +31,26 @@ const GeneralTab = { }, components: { BooleanSetting, + ChoiceSetting, InterfaceLanguageSwitcher }, computed: { postFormats () { return this.$store.state.instance.postFormats || [] }, + postContentOptions () { + return this.postFormats.map(format => ({ + key: format, + value: format, + label: this.$t(`post_status.content_type["${format}"]`) + })) + }, instanceSpecificPanelPresent () { return this.$store.state.instance.showInstanceSpecificPanel }, instanceWallpaperUsed () { return this.$store.state.instance.background && !this.$store.state.users.currentUser.background_image }, + instanceShoutboxPresent () { return this.$store.state.instance.shoutAvailable }, ...SharedComputedObject() } } diff --git a/src/components/settings_modal/tabs/general_tab.vue b/src/components/settings_modal/tabs/general_tab.vue index f93f4ea0..d3e71b31 100644 --- a/src/components/settings_modal/tabs/general_tab.vue +++ b/src/components/settings_modal/tabs/general_tab.vue @@ -11,11 +11,21 @@ {{ $t('settings.hide_isp') }} </BooleanSetting> </li> + <li> + <BooleanSetting path="sidebarRight"> + {{ $t('settings.right_sidebar') }} + </BooleanSetting> + </li> <li v-if="instanceWallpaperUsed"> <BooleanSetting path="hideInstanceWallpaper"> {{ $t('settings.hide_wallpaper') }} </BooleanSetting> </li> + <li v-if="instanceShoutboxPresent"> + <BooleanSetting path="hideShoutbox"> + {{ $t('settings.hide_shoutbox') }} + </BooleanSetting> + </li> </ul> </div> <div class="setting-item"> @@ -85,66 +95,31 @@ </BooleanSetting> </li> <li> - <div> + <ChoiceSetting + id="subjectLineBehavior" + path="subjectLineBehavior" + :options="subjectLineOptions" + > {{ $t('settings.subject_line_behavior') }} - <label - for="subjectLineBehavior" - class="select" - > - <select - id="subjectLineBehavior" - v-model="subjectLineBehavior" - > - <option value="email"> - {{ $t('settings.subject_line_email') }} - {{ subjectLineBehaviorDefaultValue == 'email' ? $t('settings.instance_default_simple') : '' }} - </option> - <option value="masto"> - {{ $t('settings.subject_line_mastodon') }} - {{ subjectLineBehaviorDefaultValue == 'mastodon' ? $t('settings.instance_default_simple') : '' }} - </option> - <option value="noop"> - {{ $t('settings.subject_line_noop') }} - {{ subjectLineBehaviorDefaultValue == 'noop' ? $t('settings.instance_default_simple') : '' }} - </option> - </select> - <FAIcon - class="select-down-icon" - icon="chevron-down" - /> - </label> - </div> + </ChoiceSetting> </li> <li v-if="postFormats.length > 0"> - <div> + <ChoiceSetting + id="postContentType" + path="postContentType" + :options="postContentOptions" + > {{ $t('settings.post_status_content_type') }} - <label - for="postContentType" - class="select" - > - <select - id="postContentType" - v-model="postContentType" - > - <option - v-for="postFormat in postFormats" - :key="postFormat" - :value="postFormat" - > - {{ $t(`post_status.content_type["${postFormat}"]`) }} - {{ postContentTypeDefaultValue === postFormat ? $t('settings.instance_default_simple') : '' }} - </option> - </select> - <FAIcon - class="select-down-icon" - icon="chevron-down" - /> - </label> - </div> + </ChoiceSetting> </li> <li> <BooleanSetting path="minimalScopesMode"> - {{ $t('settings.minimal_scopes_mode') }} {{ minimalScopesModeDefaultValue }} + {{ $t('settings.minimal_scopes_mode') }} + </BooleanSetting> + </li> + <li> + <BooleanSetting path="sensitiveByDefault"> + {{ $t('settings.sensitive_by_default') }} </BooleanSetting> </li> <li> diff --git a/src/components/settings_modal/tabs/mutes_and_blocks_tab.vue b/src/components/settings_modal/tabs/mutes_and_blocks_tab.vue index 63d36bf9..32a21415 100644 --- a/src/components/settings_modal/tabs/mutes_and_blocks_tab.vue +++ b/src/components/settings_modal/tabs/mutes_and_blocks_tab.vue @@ -10,20 +10,18 @@ :query="queryUserIds" :placeholder="$t('settings.search_user_to_block')" > - <BlockCard - slot-scope="row" - :user-id="row.item" - /> + <template v-slot="row"> + <BlockCard + :user-id="row.item" + /> + </template> </Autosuggest> </div> <BlockList :refresh="true" :get-key="i => i" > - <template - slot="header" - slot-scope="{selected}" - > + <template v-slot:header="{selected}"> <div class="bulk-actions"> <ProgressButton v-if="selected.length > 0" @@ -31,7 +29,7 @@ :click="() => blockUsers(selected)" > {{ $t('user_card.block') }} - <template slot="progress"> + <template v-slot:progress> {{ $t('user_card.block_progress') }} </template> </ProgressButton> @@ -41,19 +39,16 @@ :click="() => unblockUsers(selected)" > {{ $t('user_card.unblock') }} - <template slot="progress"> + <template v-slot:progress> {{ $t('user_card.unblock_progress') }} </template> </ProgressButton> </div> </template> - <template - slot="item" - slot-scope="{item}" - > + <template v-slot:item="{item}"> <BlockCard :user-id="item" /> </template> - <template slot="empty"> + <template v-slot:empty> {{ $t('settings.no_blocks') }} </template> </BlockList> @@ -68,20 +63,18 @@ :query="queryUserIds" :placeholder="$t('settings.search_user_to_mute')" > - <MuteCard - slot-scope="row" - :user-id="row.item" - /> + <template v-slot="row"> + <MuteCard + :user-id="row.item" + /> + </template> </Autosuggest> </div> <MuteList :refresh="true" :get-key="i => i" > - <template - slot="header" - slot-scope="{selected}" - > + <template v-slot:header="{selected}"> <div class="bulk-actions"> <ProgressButton v-if="selected.length > 0" @@ -89,7 +82,7 @@ :click="() => muteUsers(selected)" > {{ $t('user_card.mute') }} - <template slot="progress"> + <template v-slot:progress> {{ $t('user_card.mute_progress') }} </template> </ProgressButton> @@ -99,19 +92,16 @@ :click="() => unmuteUsers(selected)" > {{ $t('user_card.unmute') }} - <template slot="progress"> + <template v-slot:progress> {{ $t('user_card.unmute_progress') }} </template> </ProgressButton> </div> </template> - <template - slot="item" - slot-scope="{item}" - > + <template v-slot:item="{item}"> <MuteCard :user-id="item" /> </template> - <template slot="empty"> + <template v-slot:empty> {{ $t('settings.no_mutes') }} </template> </MuteList> @@ -124,20 +114,18 @@ :query="queryKnownDomains" :placeholder="$t('settings.type_domains_to_mute')" > - <DomainMuteCard - slot-scope="row" - :domain="row.item" - /> + <template v-slot="row"> + <DomainMuteCard + :domain="row.item" + /> + </template> </Autosuggest> </div> <DomainMuteList :refresh="true" :get-key="i => i" > - <template - slot="header" - slot-scope="{selected}" - > + <template v-slot:header="{selected}"> <div class="bulk-actions"> <ProgressButton v-if="selected.length > 0" @@ -145,19 +133,16 @@ :click="() => unmuteDomains(selected)" > {{ $t('domain_mute_card.unmute') }} - <template slot="progress"> + <template v-slot:progress> {{ $t('domain_mute_card.unmute_progress') }} </template> </ProgressButton> </div> </template> - <template - slot="item" - slot-scope="{item}" - > + <template v-slot:item="{item}"> <DomainMuteCard :domain="item" /> </template> - <template slot="empty"> + <template v-slot:empty> {{ $t('settings.no_mutes') }} </template> </DomainMuteList> diff --git a/src/components/settings_modal/tabs/notifications_tab.vue b/src/components/settings_modal/tabs/notifications_tab.vue index 8f8fe48e..7e0568ea 100644 --- a/src/components/settings_modal/tabs/notifications_tab.vue +++ b/src/components/settings_modal/tabs/notifications_tab.vue @@ -24,7 +24,7 @@ class="btn button-default" @click="updateNotificationSettings" > - {{ $t('general.submit') }} + {{ $t('settings.save') }} </button> </div> </div> diff --git a/src/components/settings_modal/tabs/profile_tab.vue b/src/components/settings_modal/tabs/profile_tab.vue index 175a0219..bb3c301d 100644 --- a/src/components/settings_modal/tabs/profile_tab.vue +++ b/src/components/settings_modal/tabs/profile_tab.vue @@ -153,7 +153,7 @@ class="btn button-default" @click="updateProfile" > - {{ $t('general.submit') }} + {{ $t('settings.save') }} </button> </div> <div class="setting-item"> @@ -227,7 +227,7 @@ class="btn button-default" @click="submitBanner(banner)" > - {{ $t('general.submit') }} + {{ $t('settings.save') }} </button> </div> <div class="setting-item"> @@ -266,7 +266,7 @@ class="btn button-default" @click="submitBackground(background)" > - {{ $t('general.submit') }} + {{ $t('settings.save') }} </button> </div> </div> diff --git a/src/components/settings_modal/tabs/security_tab/security_tab.vue b/src/components/settings_modal/tabs/security_tab/security_tab.vue index 56bea1f4..275d4616 100644 --- a/src/components/settings_modal/tabs/security_tab/security_tab.vue +++ b/src/components/settings_modal/tabs/security_tab/security_tab.vue @@ -22,7 +22,7 @@ class="btn button-default" @click="changeEmail" > - {{ $t('general.submit') }} + {{ $t('settings.save') }} </button> <p v-if="changedEmail"> {{ $t('settings.changed_email') }} @@ -60,7 +60,7 @@ class="btn button-default" @click="changePassword" > - {{ $t('general.submit') }} + {{ $t('settings.save') }} </button> <p v-if="changedPassword"> {{ $t('settings.changed_password') }} @@ -133,7 +133,7 @@ class="btn button-default" @click="confirmDelete" > - {{ $t('general.submit') }} + {{ $t('settings.save') }} </button> </div> </div> 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 6cf75fe7..8b81db5d 100644 --- a/src/components/settings_modal/tabs/theme_tab/theme_tab.js +++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.js @@ -16,6 +16,10 @@ import { colors2to3 } from 'src/services/style_setter/style_setter.js' import { + newImporter, + newExporter +} from 'src/services/export_import/export_import.js' +import { SLOT_INHERITANCE } from 'src/services/theme_data/pleromafe.js' import { @@ -31,18 +35,10 @@ import ShadowControl from 'src/components/shadow_control/shadow_control.vue' import FontControl from 'src/components/font_control/font_control.vue' import ContrastRatio from 'src/components/contrast_ratio/contrast_ratio.vue' import TabSwitcher from 'src/components/tab_switcher/tab_switcher.js' -import ExportImport from 'src/components/export_import/export_import.vue' import Checkbox from 'src/components/checkbox/checkbox.vue' +import Select from 'src/components/select/select.vue' import Preview from './preview.vue' -import { library } from '@fortawesome/fontawesome-svg-core' -import { - faChevronDown -} from '@fortawesome/free-solid-svg-icons' - -library.add( - faChevronDown -) // List of color values used in v1 const v1OnlyNames = [ @@ -67,8 +63,18 @@ const colorConvert = (color) => { export default { data () { return { + themeImporter: newImporter({ + validator: this.importValidator, + onImport: this.onImport, + onImportFailure: this.onImportFailure + }), + themeExporter: newExporter({ + filename: 'pleroma_theme', + getExportedObject: () => this.exportedTheme + }), availableStyles: [], - selected: this.$store.getters.mergedConfig.theme, + selected: '', + selectedTheme: this.$store.getters.mergedConfig.theme, themeWarning: undefined, tempImportFile: undefined, engineVersion: 0, @@ -202,7 +208,7 @@ export default { } }, selectedVersion () { - return Array.isArray(this.selected) ? 1 : 2 + return Array.isArray(this.selectedTheme) ? 1 : 2 }, currentColors () { return Object.keys(SLOT_INHERITANCE) @@ -383,8 +389,8 @@ export default { FontControl, TabSwitcher, Preview, - ExportImport, - Checkbox + Checkbox, + Select }, methods: { loadTheme ( @@ -528,10 +534,15 @@ export default { this.previewColors.mod ) }, + importTheme () { this.themeImporter.importData() }, + exportTheme () { this.themeExporter.exportData() }, onImport (parsed, forceSource = false) { this.tempImportFile = parsed this.loadTheme(parsed, 'file', forceSource) }, + onImportFailure (result) { + this.$store.dispatch('pushGlobalNotice', { messageKey: 'settings.invalid_theme_imported', level: 'error' }) + }, importValidator (parsed) { const version = parsed._pleroma_theme_version return version >= 1 || version <= 2 @@ -735,6 +746,16 @@ export default { } }, selected () { + this.selectedTheme = Object.entries(this.availableStyles).find(([k, s]) => { + if (Array.isArray(s)) { + console.log(s[0] === this.selected, this.selected) + return s[0] === this.selected + } else { + return s.name === this.selected + } + })[1] + }, + selectedTheme () { this.dismissWarning() if (this.selectedVersion === 1) { if (!this.keepRoundness) { @@ -752,17 +773,17 @@ export default { if (!this.keepColor) { this.clearV1() - this.bgColorLocal = this.selected[1] - this.fgColorLocal = this.selected[2] - this.textColorLocal = this.selected[3] - this.linkColorLocal = this.selected[4] - this.cRedColorLocal = this.selected[5] - this.cGreenColorLocal = this.selected[6] - this.cBlueColorLocal = this.selected[7] - this.cOrangeColorLocal = this.selected[8] + this.bgColorLocal = this.selectedTheme[1] + this.fgColorLocal = this.selectedTheme[2] + this.textColorLocal = this.selectedTheme[3] + this.linkColorLocal = this.selectedTheme[4] + this.cRedColorLocal = this.selectedTheme[5] + this.cGreenColorLocal = this.selectedTheme[6] + this.cBlueColorLocal = this.selectedTheme[7] + this.cOrangeColorLocal = this.selectedTheme[8] } } else if (this.selectedVersion >= 2) { - this.normalizeLocalState(this.selected.theme, 2, this.selected.source) + this.normalizeLocalState(this.selectedTheme.theme, 2, this.selectedTheme.source) } } } 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 b8add42f..c02986ed 100644 --- a/src/components/settings_modal/tabs/theme_tab/theme_tab.vue +++ b/src/components/settings_modal/tabs/theme_tab/theme_tab.vue @@ -48,46 +48,47 @@ </template> </div> </div> - <ExportImport - :export-object="exportedTheme" - :export-label="$t("settings.export_theme")" - :import-label="$t("settings.import_theme")" - :import-failed-text="$t("settings.invalid_theme_imported")" - :on-import="onImport" - :validator="importValidator" - > - <template slot="before"> - <div class="presets"> - {{ $t('settings.presets') }} - <label - for="preset-switcher" - class="select" + <div class="top"> + <div class="presets"> + {{ $t('settings.presets') }} + <label + for="preset-switcher" + class="select" + > + <Select + id="preset-switcher" + v-model="selected" + class="preset-switcher" > - <select - id="preset-switcher" - v-model="selected" - class="preset-switcher" + <option + v-for="style in availableStyles" + :key="style.name" + :value="style.name || style[0]" + :style="{ + backgroundColor: style[1] || (style.theme || style.source).colors.bg, + color: style[3] || (style.theme || style.source).colors.text + }" > - <option - v-for="style in availableStyles" - :key="style.name" - :value="style" - :style="{ - backgroundColor: style[1] || (style.theme || style.source).colors.bg, - color: style[3] || (style.theme || style.source).colors.text - }" - > - {{ style[0] || style.name }} - </option> - </select> - <FAIcon - class="select-down-icon" - icon="chevron-down" - /> - </label> - </div> - </template> - </ExportImport> + {{ style[0] || style.name }} + </option> + </Select> + </label> + </div> + <div class="export-import"> + <button + class="btn button-default" + @click="importTheme" + > + {{ $t("settings.import_theme") }} + </button> + <button + class="btn button-default" + @click="exportTheme" + > + {{ $t("settings.export_theme") }} + </button> + </div> + </div> </div> <div class="save-load-options"> <span class="keep-option"> @@ -902,28 +903,19 @@ <div class="tab-header shadow-selector"> <div class="select-container"> {{ $t('settings.style.shadows.component') }} - <label - for="shadow-switcher" - class="select" + <Select + id="shadow-switcher" + v-model="shadowSelected" + class="shadow-switcher" > - <select - id="shadow-switcher" - v-model="shadowSelected" - class="shadow-switcher" + <option + v-for="shadow in shadowsAvailable" + :key="shadow" + :value="shadow" > - <option - v-for="shadow in shadowsAvailable" - :key="shadow" - :value="shadow" - > - {{ $t('settings.style.shadows.components.' + shadow) }} - </option> - </select> - <FAIcon - class="select-down-icon" - icon="chevron-down" - /> - </label> + {{ $t('settings.style.shadows.components.' + shadow) }} + </option> + </Select> </div> <div class="override"> <label |
