logo

pleroma-fe

My custom branche(s) on git.pleroma.social/pleroma/pleroma-fe git clone https://hacktivis.me/git/pleroma-fe.git
commit: bd5b62b1071d6424f82477dca2f0d374f709a596
parent 4baa397ed02f5deab4d5548dd89bbfb07c8a3d80
Author: Henry Jameson <me@hjkos.com>
Date:   Mon,  8 Mar 2021 19:42:24 +0200

changed importexport into a service instead of component for simplicity

Diffstat:

Dsrc/components/export_import/export_import.vue102-------------------------------------------------------------------------------
Msrc/components/settings_modal/tabs/theme_tab/theme_tab.js20++++++++++++++++++--
Msrc/components/settings_modal/tabs/theme_tab/theme_tab.vue75+++++++++++++++++++++++++++++++++++++--------------------------------------
Asrc/services/export_import/export_import.js57+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 112 insertions(+), 142 deletions(-)

diff --git a/src/components/export_import/export_import.vue b/src/components/export_import/export_import.vue @@ -1,102 +0,0 @@ -<template> - <div class="import-export-container"> - <slot name="before" /> - <button - class="btn button-default" - @click="exportData" - > - {{ exportLabel }} - </button> - <button - class="btn button-default" - @click="importData" - > - {{ importLabel }} - </button> - <slot name="afterButtons" /> - <p - v-if="importFailed" - class="alert error" - > - {{ importFailedText }} - </p> - <slot name="afterError" /> - </div> -</template> - -<script> -export default { - props: [ - 'exportObject', - 'importLabel', - 'exportLabel', - 'importFailedText', - 'validator', - 'onImport', - 'onImportFailure' - ], - data () { - return { - importFailed: false - } - }, - methods: { - exportData () { - const stringified = JSON.stringify(this.exportObject, null, 2) // Pretty-print and indent with 2 spaces - - // Create an invisible link with a data url and simulate a click - const e = document.createElement('a') - e.setAttribute('download', 'pleroma_theme.json') - e.setAttribute('href', 'data:application/json;base64,' + window.btoa(stringified)) - e.style.display = 'none' - - document.body.appendChild(e) - e.click() - document.body.removeChild(e) - }, - importData () { - this.importFailed = false - const filePicker = document.createElement('input') - filePicker.setAttribute('type', 'file') - filePicker.setAttribute('accept', '.json') - - filePicker.addEventListener('change', event => { - if (event.target.files[0]) { - // eslint-disable-next-line no-undef - const reader = new FileReader() - reader.onload = ({ target }) => { - try { - const parsed = JSON.parse(target.result) - const valid = this.validator(parsed) - if (valid) { - this.onImport(parsed) - } else { - this.importFailed = true - // this.onImportFailure(valid) - } - } catch (e) { - // This will happen both if there is a JSON syntax error or the theme is missing components - this.importFailed = true - // this.onImportFailure(e) - } - } - reader.readAsText(event.target.files[0]) - } - }) - - document.body.appendChild(filePicker) - filePicker.click() - document.body.removeChild(filePicker) - } - } -} -</script> - -<style lang="scss"> -.import-export-container { - display: flex; - flex-wrap: wrap; - align-items: baseline; - justify-content: center; -} -</style> diff --git 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,7 +35,6 @@ 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 Preview from './preview.vue' @@ -67,6 +70,15 @@ 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, themeWarning: undefined, @@ -383,7 +395,6 @@ export default { FontControl, TabSwitcher, Preview, - ExportImport, Checkbox }, methods: { @@ -528,10 +539,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 diff --git 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,45 @@ </template> </div> </div> - <ExportImport - :export-object="exportedTheme" - :export-label="$t(&quot;settings.export_theme&quot;)" - :import-label="$t(&quot;settings.import_theme&quot;)" - :import-failed-text="$t(&quot;settings.invalid_theme_imported&quot;)" - :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" + :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> + <FAIcon + class="select-down-icon" + icon="chevron-down" + /> + </label> + </div> + <div class="export-import"> + <button class="btn button-default" @click="importTheme"> + {{ $t(&quot;settings.import_theme&quot;) }} + </button> + <button class="btn button-default" @click="exportTheme"> + {{ $t(&quot;settings.export_theme&quot;) }} + </button> + </div> + </div> </div> <div class="save-load-options"> <span class="keep-option"> diff --git a/src/services/export_import/export_import.js b/src/services/export_import/export_import.js @@ -0,0 +1,57 @@ +export const newExporter = ({ + filename = 'data', + getExportedObject +}) => ({ + exportData () { + const stringified = JSON.stringify(getExportedObject(), null, 2) // Pretty-print and indent with 2 spaces + + // Create an invisible link with a data url and simulate a click + const e = document.createElement('a') + e.setAttribute('download', `${filename}.json`) + e.setAttribute('href', 'data:application/json;base64,' + window.btoa(stringified)) + e.style.display = 'none' + + document.body.appendChild(e) + e.click() + document.body.removeChild(e) + } +}) + +export const newImporter = ({ + onImport, + onImportFailure, + validator = () => true +}) => ({ + importData () { + const filePicker = document.createElement('input') + filePicker.setAttribute('type', 'file') + filePicker.setAttribute('accept', '.json') + console.log(1) + + filePicker.addEventListener('change', event => { + if (event.target.files[0]) { + // eslint-disable-next-line no-undef + const reader = new FileReader() + reader.onload = ({ target }) => { + try { + const parsed = JSON.parse(target.result) + const validationResult = validator(parsed) + if (validationResult === true) { + onImport(parsed) + } else { + onImportFailure({ validationResult }) + } + } catch (error) { + onImportFailure({ error }) + } + } + console.log(2) + reader.readAsText(event.target.files[0]) + } + }) + + document.body.appendChild(filePicker) + filePicker.click() + document.body.removeChild(filePicker) + } +})