Merge branch 'feature/theme-export-import' into 'develop'

Theme import & export

Closes #119

See merge request pleroma/pleroma-fe!290
This commit is contained in:
kaniini 2018-08-20 00:03:35 +00:00
commit 9982376f9a
7 changed files with 92 additions and 28 deletions

View file

@ -63,6 +63,8 @@ button{
box-shadow: 0px 0px 2px black; box-shadow: 0px 0px 2px black;
font-size: 14px; font-size: 14px;
font-family: sans-serif; font-family: sans-serif;
min-width: 10em;
min-height: 2em;
&:hover { &:hover {
box-shadow: 0px 0px 4px rgba(255, 255, 255, 0.3); box-shadow: 0px 0px 4px rgba(255, 255, 255, 0.3);

View file

@ -34,11 +34,6 @@
@import '../../_variables.scss'; @import '../../_variables.scss';
.login-form { .login-form {
.btn {
min-height: 28px;
width: 10em;
}
.error { .error {
text-align: center; text-align: center;
} }

View file

@ -107,10 +107,6 @@
padding: 0.5em; padding: 0.5em;
height: 32px; height: 32px;
button {
width: 10em;
}
p { p {
margin: 0.35em; margin: 0.35em;
padding: 0.35em; padding: 0.35em;

View file

@ -113,8 +113,6 @@
.btn { .btn {
margin-top: 1em; margin-top: 1em;
min-height: 28px;
width: 10em;
} }
} }
.setting-list { .setting-list {

View file

@ -5,6 +5,7 @@ export default {
return { return {
availableStyles: [], availableStyles: [],
selected: this.$store.state.config.theme, selected: this.$store.state.config.theme,
invalidThemeImported: false,
bgColorLocal: '', bgColorLocal: '',
btnColorLocal: '', btnColorLocal: '',
textColorLocal: '', textColorLocal: '',
@ -32,25 +33,61 @@ export default {
}) })
}, },
mounted () { mounted () {
this.bgColorLocal = rgbstr2hex(this.$store.state.config.colors.bg) this.normalizeLocalState(this.$store.state.config.colors, this.$store.state.config.radii)
this.btnColorLocal = rgbstr2hex(this.$store.state.config.colors.btn)
this.textColorLocal = rgbstr2hex(this.$store.state.config.colors.fg)
this.linkColorLocal = rgbstr2hex(this.$store.state.config.colors.link)
this.redColorLocal = rgbstr2hex(this.$store.state.config.colors.cRed)
this.blueColorLocal = rgbstr2hex(this.$store.state.config.colors.cBlue)
this.greenColorLocal = rgbstr2hex(this.$store.state.config.colors.cGreen)
this.orangeColorLocal = rgbstr2hex(this.$store.state.config.colors.cOrange)
this.btnRadiusLocal = this.$store.state.config.radii.btnRadius || 4
this.inputRadiusLocal = this.$store.state.config.radii.inputRadius || 4
this.panelRadiusLocal = this.$store.state.config.radii.panelRadius || 10
this.avatarRadiusLocal = this.$store.state.config.radii.avatarRadius || 5
this.avatarAltRadiusLocal = this.$store.state.config.radii.avatarAltRadius || 50
this.tooltipRadiusLocal = this.$store.state.config.radii.tooltipRadius || 2
this.attachmentRadiusLocal = this.$store.state.config.radii.attachmentRadius || 5
}, },
methods: { methods: {
exportCurrentTheme () {
const stringified = JSON.stringify({
// To separate from other random JSON files and possible future theme formats
_pleroma_theme_version: 1,
colors: this.$store.state.config.colors,
radii: this.$store.state.config.radii
}, 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)
},
importTheme () {
this.invalidThemeImported = 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)
if (parsed._pleroma_theme_version === 1) {
this.normalizeLocalState(parsed.colors, parsed.radii)
} else {
// A theme from the future, spooky
this.invalidThemeImported = true
}
} catch (e) {
// This will happen both if there is a JSON syntax error or the theme is missing components
this.invalidThemeImported = true
}
}
reader.readAsText(event.target.files[0])
}
})
document.body.appendChild(filePicker)
filePicker.click()
document.body.removeChild(filePicker)
},
setCustomTheme () { setCustomTheme () {
if (!this.bgColorLocal && !this.btnColorLocal && !this.linkColorLocal) { if (!this.bgColorLocal && !this.btnColorLocal && !this.linkColorLocal) {
// reset to picked themes // reset to picked themes
@ -95,6 +132,26 @@ export default {
attachmentRadius: this.attachmentRadiusLocal attachmentRadius: this.attachmentRadiusLocal
}}) }})
} }
},
normalizeLocalState (colors, radii) {
this.bgColorLocal = rgbstr2hex(colors.bg)
this.btnColorLocal = rgbstr2hex(colors.btn)
this.textColorLocal = rgbstr2hex(colors.fg)
this.linkColorLocal = rgbstr2hex(colors.link)
this.redColorLocal = rgbstr2hex(colors.cRed)
this.blueColorLocal = rgbstr2hex(colors.cBlue)
this.greenColorLocal = rgbstr2hex(colors.cGreen)
this.orangeColorLocal = rgbstr2hex(colors.cOrange)
this.btnRadiusLocal = radii.btnRadius || 4
this.inputRadiusLocal = radii.inputRadius || 4
this.panelRadiusLocal = radii.panelRadius || 10
this.avatarRadiusLocal = radii.avatarRadius || 5
this.avatarAltRadiusLocal = radii.avatarAltRadius || 50
this.tooltipRadiusLocal = radii.tooltipRadius || 2
this.attachmentRadiusLocal = radii.attachmentRadius || 5
} }
}, },
watch: { watch: {

View file

@ -11,6 +11,11 @@
<i class="icon-down-open"/> <i class="icon-down-open"/>
</label> </label>
</div> </div>
<div>
<button class="btn" @click="exportCurrentTheme">{{ $t('settings.export_theme') }}</button>
<button class="btn" @click="importTheme">{{ $t('settings.import_theme') }}</button>
<p v-if="invalidThemeImported" class="import-warning">{{ $t('settings.invalid_theme_imported') }}</p>
</div>
<div class="color-container"> <div class="color-container">
<p>{{$t('settings.theme_help')}}</p> <p>{{$t('settings.theme_help')}}</p>
<div class="color-item"> <div class="color-item">
@ -134,6 +139,11 @@
margin-right: 1em; margin-right: 1em;
} }
.import-warning {
color: $fallback--cRed;
color: var(--cRed, $fallback--cRed);
}
.radius-container, .radius-container,
.color-container { .color-container {
display: flex; display: flex;

View file

@ -48,6 +48,9 @@ const de = {
settings: 'Einstellungen', settings: 'Einstellungen',
theme: 'Farbschema', theme: 'Farbschema',
presets: 'Voreinstellungen', presets: 'Voreinstellungen',
export_theme: 'Aktuelles Theme exportieren',
import_theme: 'Gespeichertes Theme laden',
invalid_theme_imported: 'Die ausgewählte Datei ist kein unterstütztes Pleroma-Theme. Keine Änderungen wurden vorgenommen.',
theme_help: 'Benutze HTML Farbcodes (#rrggbb) um dein Farbschema anzupassen', theme_help: 'Benutze HTML Farbcodes (#rrggbb) um dein Farbschema anzupassen',
radii_help: 'Kantenrundung (in Pixel) der Oberfläche anpassen', radii_help: 'Kantenrundung (in Pixel) der Oberfläche anpassen',
background: 'Hintergrund', background: 'Hintergrund',
@ -288,7 +291,10 @@ const en = {
settings: 'Settings', settings: 'Settings',
theme: 'Theme', theme: 'Theme',
presets: 'Presets', presets: 'Presets',
export_theme: 'Export current theme',
import_theme: 'Load saved theme',
theme_help: 'Use hex color codes (#rrggbb) to customize your color theme.', theme_help: 'Use hex color codes (#rrggbb) to customize your color theme.',
invalid_theme_imported: 'The selected file is not a supported Pleroma theme. No changes to your theme were made.',
radii_help: 'Set up interface edge rounding (in pixels)', radii_help: 'Set up interface edge rounding (in pixels)',
background: 'Background', background: 'Background',
foreground: 'Foreground', foreground: 'Foreground',