* upstream/develop: (142 commits) fix timeago font added hide_network option, fixed properties naming Fix fetching new users, add storing local users in usersObjects with their screen_name as well as id, so that they could be fetched zero-state with screen-name link. improve notification subscription Fix typo that prevented scope copy from working. added check for activatePanel is function or not addressed PR comments activate panel on user screen click added not preload check so hidden toggles asap removed counters from left panel added router-links to all relavent links added activatePanel onclick for timeago button added PR comments add checkbox to disable web push removed brackets from condition resolved lint issue renamed config to preload images and add ident to config added config for preload and made attachment responsive to it preload nsfw image fix ...mobile-back
commit
610724ffcd
@ -0,0 +1,4 @@
|
||||
{
|
||||
"target": "https://pleroma.soykaf.com/",
|
||||
"staticConfigPreference": false
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<div class="color-control style-control" :class="{ disabled: !present || disabled }">
|
||||
<label :for="name" class="label">
|
||||
{{label}}
|
||||
</label>
|
||||
<input
|
||||
v-if="typeof fallback !== 'undefined'"
|
||||
class="opt exlcude-disabled"
|
||||
:id="name + '-o'"
|
||||
type="checkbox"
|
||||
:checked="present"
|
||||
@input="$emit('input', typeof value === 'undefined' ? fallback : undefined)">
|
||||
<label v-if="typeof fallback !== 'undefined'" class="opt-l" :for="name + '-o'"></label>
|
||||
<input
|
||||
:id="name"
|
||||
class="color-input"
|
||||
type="color"
|
||||
:value="value || fallback"
|
||||
:disabled="!present || disabled"
|
||||
@input="$emit('input', $event.target.value)"
|
||||
>
|
||||
<input
|
||||
:id="name + '-t'"
|
||||
class="text-input"
|
||||
type="text"
|
||||
:value="value || fallback"
|
||||
:disabled="!present || disabled"
|
||||
@input="$emit('input', $event.target.value)"
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: [
|
||||
'name', 'label', 'value', 'fallback', 'disabled'
|
||||
],
|
||||
computed: {
|
||||
present () {
|
||||
return typeof this.value !== 'undefined'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.color-control {
|
||||
input.text-input {
|
||||
max-width: 7em;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<span v-if="contrast" class="contrast-ratio">
|
||||
<span :title="hint" class="rating">
|
||||
<span v-if="contrast.aaa">
|
||||
<i class="icon-thumbs-up-alt"/>
|
||||
</span>
|
||||
<span v-if="!contrast.aaa && contrast.aa">
|
||||
<i class="icon-adjust"/>
|
||||
</span>
|
||||
<span v-if="!contrast.aaa && !contrast.aa">
|
||||
<i class="icon-attention"/>
|
||||
</span>
|
||||
</span>
|
||||
<span class="rating" v-if="contrast && large" :title="hint_18pt">
|
||||
<span v-if="contrast.laaa">
|
||||
<i class="icon-thumbs-up-alt"/>
|
||||
</span>
|
||||
<span v-if="!contrast.laaa && contrast.laa">
|
||||
<i class="icon-adjust"/>
|
||||
</span>
|
||||
<span v-if="!contrast.laaa && !contrast.laa">
|
||||
<i class="icon-attention"/>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: [
|
||||
'large', 'contrast'
|
||||
],
|
||||
computed: {
|
||||
hint () {
|
||||
const levelVal = this.contrast.aaa ? 'aaa' : (this.contrast.aa ? 'aa' : 'bad')
|
||||
const level = this.$t(`settings.style.common.contrast.level.${levelVal}`)
|
||||
const context = this.$t('settings.style.common.contrast.context.text')
|
||||
const ratio = this.contrast.text
|
||||
return this.$t('settings.style.common.contrast.hint', { level, context, ratio })
|
||||
},
|
||||
hint_18pt () {
|
||||
const levelVal = this.contrast.laaa ? 'aaa' : (this.contrast.laa ? 'aa' : 'bad')
|
||||
const level = this.$t(`settings.style.common.contrast.level.${levelVal}`)
|
||||
const context = this.$t('settings.style.common.contrast.context.18pt')
|
||||
const ratio = this.contrast.text
|
||||
return this.$t('settings.style.common.contrast.hint', { level, context, ratio })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.contrast-ratio {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
|
||||
margin-top: -4px;
|
||||
margin-bottom: 5px;
|
||||
|
||||
.label {
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.rating {
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,87 @@
|
||||
<template>
|
||||
<div class="import-export-container">
|
||||
<slot name="before"/>
|
||||
<button class="btn" @click="exportData">{{ exportLabel }}</button>
|
||||
<button class="btn" @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) // 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>
|
@ -0,0 +1,58 @@
|
||||
import { set } from 'vue'
|
||||
|
||||
export default {
|
||||
props: [
|
||||
'name', 'label', 'value', 'fallback', 'options', 'no-inherit'
|
||||
],
|
||||
data () {
|
||||
return {
|
||||
lValue: this.value,
|
||||
availableOptions: [
|
||||
this.noInherit ? '' : 'inherit',
|
||||
'custom',
|
||||
...(this.options || []),
|
||||
'serif',
|
||||
'monospace',
|
||||
'sans-serif'
|
||||
].filter(_ => _)
|
||||
}
|
||||
},
|
||||
beforeUpdate () {
|
||||
this.lValue = this.value
|
||||
},
|
||||
computed: {
|
||||
present () {
|
||||
return typeof this.lValue !== 'undefined'
|
||||
},
|
||||
dValue () {
|
||||
return this.lValue || this.fallback || {}
|
||||
},
|
||||
family: {
|
||||
get () {
|
||||
return this.dValue.family
|
||||
},
|
||||
set (v) {
|
||||
set(this.lValue, 'family', v)
|
||||
this.$emit('input', this.lValue)
|
||||
}
|
||||
},
|
||||
isCustom () {
|
||||
return this.preset === 'custom'
|
||||
},
|
||||
preset: {
|
||||
get () {
|
||||
if (this.family === 'serif' ||
|
||||
this.family === 'sans-serif' ||
|
||||
this.family === 'monospace' ||
|
||||
this.family === 'inherit') {
|
||||
return this.family
|
||||
} else {
|
||||
return 'custom'
|
||||
}
|
||||
},
|
||||
set (v) {
|
||||
this.family = v === 'custom' ? '' : v
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<div class="font-control style-control" :class="{ custom: isCustom }">
|
||||
<label :for="preset === 'custom' ? name : name + '-font-switcher'" class="label">
|
||||
{{label}}
|
||||
</label>
|
||||
<input
|
||||
v-if="typeof fallback !== 'undefined'"
|
||||
class="opt exlcude-disabled"
|
||||
type="checkbox"
|
||||
:id="name + '-o'"
|
||||
:checked="present"
|
||||
@input="$emit('input', typeof value === 'undefined' ? fallback : undefined)">
|
||||
<label v-if="typeof fallback !== 'undefined'" class="opt-l" :for="name + '-o'"></label>
|
||||
<label :for="name + '-font-switcher'" class="select" :disabled="!present">
|
||||
<select
|
||||
:disabled="!present"
|
||||
v-model="preset"
|
||||
class="font-switcher"
|
||||
:id="name + '-font-switcher'">
|
||||
<option v-for="option in availableOptions" :value="option">
|
||||
{{ option === 'custom' ? $t('settings.style.fonts.custom') : option }}
|
||||
</option>
|
||||
</select>
|
||||
<i class="icon-down-open"/>
|
||||
</label>
|
||||
<input
|
||||
v-if="isCustom"
|
||||
class="custom-font"
|
||||
type="text"
|
||||
:id="name"
|
||||
v-model="family">
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script src="./font_control.js" ></script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../../_variables.scss';
|
||||
.font-control {
|
||||
input.custom-font {
|
||||
min-width: 10em;
|
||||
}
|
||||
&.custom {
|
||||
.select {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
.custom-font {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<div class="opacity-control style-control" :class="{ disabled: !present || disabled }">
|
||||
<label :for="name" class="label">
|
||||
{{$t('settings.style.common.opacity')}}
|
||||
</label>
|
||||
<input
|
||||
v-if="typeof fallback !== 'undefined'"
|
||||
class="opt exclude-disabled"
|
||||
:id="name + '-o'"
|
||||
type="checkbox"
|
||||
:checked="present"
|
||||
@input="$emit('input', !present ? fallback : undefined)">
|
||||
<label v-if="typeof fallback !== 'undefined'" class="opt-l" :for="name + '-o'"></label>
|
||||
<input
|
||||
:id="name"
|
||||
class="input-number"
|
||||
type="number"
|
||||
:value="value || fallback"
|
||||
:disabled="!present || disabled"
|
||||
@input="$emit('input', $event.target.value)"
|
||||
max="1"
|
||||
min="0"
|
||||
step=".05">
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: [
|
||||
'name', 'value', 'fallback', 'disabled'
|
||||
],
|
||||
computed: {
|
||||
present () {
|
||||
return typeof this.value !== 'undefined'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<div class="range-control style-control" :class="{ disabled: !present || disabled }">
|
||||
<label :for="name" class="label">
|
||||
{{label}}
|
||||
</label>
|
||||
<input
|
||||
v-if="typeof fallback !== 'undefined'"
|
||||
class="opt exclude-disabled"
|
||||
:id="name + '-o'"
|
||||
type="checkbox"
|
||||
:checked="present"
|
||||
@input="$emit('input', !present ? fallback : undefined)">
|
||||
<label v-if="typeof fallback !== 'undefined'" class="opt-l" :for="name + '-o'"></label>
|
||||
<input
|
||||
:id="name"
|
||||
class="input-number"
|
||||
type="range"
|
||||
:value="value || fallback"
|
||||
:disabled="!present || disabled"
|
||||
@input="$emit('input', $event.target.value)"
|
||||
:max="max || hardMax || 100"
|
||||
:min="min || hardMin || 0"
|
||||
:step="step || 1">
|
||||
<input
|
||||
:id="name"
|
||||
class="input-number"
|
||||
type="number"
|
||||
:value="value || fallback"
|
||||
:disabled="!present || disabled"
|
||||
@input="$emit('input', $event.target.value)"
|
||||
:max="hardMax"
|
||||
:min="hardMin"
|
||||
:step="step || 1">
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: [
|
||||
'name', 'value', 'fallback', 'disabled', 'label', 'max', 'min', 'step', 'hardMin', 'hardMax'
|
||||
],
|
||||
computed: {
|
||||
present () {
|
||||
return typeof this.value !== 'undefined'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
@ -0,0 +1,87 @@
|
||||
import ColorInput from '../color_input/color_input.vue'
|
||||
import OpacityInput from '../opacity_input/opacity_input.vue'
|
||||
import { getCssShadow } from '../../services/style_setter/style_setter.js'
|
||||
import { hex2rgb } from '../../services/color_convert/color_convert.js'
|
||||
|
||||
export default {
|
||||
// 'Value' and 'Fallback' can be undefined, but if they are
|
||||
// initially vue won't detect it when they become something else
|
||||
// therefore i'm using "ready" which should be passed as true when
|
||||
// data becomes available
|
||||
props: [
|
||||
'value', 'fallback', 'ready'
|
||||
],
|
||||
data () {
|
||||
return {
|
||||
selectedId: 0,
|
||||
// TODO there are some bugs regarding display of array (it's not getting updated when deleting for some reason)
|
||||
cValue: this.value || this.fallback || []
|
||||
}
|
||||
},
|
||||
components: {
|
||||
ColorInput,
|
||||
OpacityInput
|
||||
},
|
||||
methods: {
|
||||
add () {
|
||||
this.cValue.push(Object.assign({}, this.selected))
|
||||
this.selectedId = this.cValue.length - 1
|
||||
},
|
||||
del () {
|
||||
this.cValue.splice(this.selectedId, 1)
|
||||
this.selectedId = this.cValue.length === 0 ? undefined : this.selectedId - 1
|
||||
},
|
||||
moveUp () {
|
||||
const movable = this.cValue.splice(this.selectedId, 1)[0]
|
||||
this.cValue.splice(this.selectedId - 1, 0, movable)
|
||||
this.selectedId -= 1
|
||||
},
|
||||
moveDn () {
|
||||
const movable = this.cValue.splice(this.selectedId, 1)[0]
|
||||
this.cValue.splice(this.selectedId + 1, 0, movable)
|
||||
this.selectedId += 1
|
||||
}
|
||||
},
|
||||
beforeUpdate () {
|
||||
this.cValue = this.value || this.fallback
|
||||
},
|
||||
computed: {
|
||||
selected () {
|
||||
if (this.ready && this.cValue.length > 0) {
|
||||
return this.cValue[this.selectedId]
|
||||
} else {
|
||||
return {
|
||||
x: 0,
|
||||
y: 0,
|
||||
blur: 0,
|
||||
spread: 0,
|
||||
inset: false,
|
||||
color: '#000000',
|
||||
alpha: 1
|
||||
}
|
||||
}
|
||||
},
|
||||
moveUpValid () {
|
||||
return this.ready && this.selectedId > 0
|
||||
},
|
||||
moveDnValid () {
|
||||
return this.ready && this.selectedId < this.cValue.length - 1
|
||||
},
|
||||
present () {
|
||||
return this.ready &&
|
||||
typeof this.cValue[this.selectedId] !== 'undefined' &&
|
||||
!this.usingFallback
|
||||
},
|
||||
usingFallback () {
|
||||
return typeof this.value === 'undefined'
|
||||
},
|
||||
rgb () {
|
||||
return hex2rgb(this.selected.color)
|
||||
},
|
||||
style () {
|
||||
return this.ready ? {
|
||||
boxShadow: getCssShadow(this.cValue)
|
||||
} : {}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,243 @@
|
||||
<template>
|
||||
<div class="shadow-control" :class="{ disabled: !present }">
|
||||
<div class="shadow-preview-container">
|
||||
<div :disabled="!present" class="y-shift-control">
|
||||
<input
|
||||
v-model="selected.y"
|
||||
:disabled="!present"
|
||||
class="input-number"
|
||||
type="number">
|
||||
<div class="wrap">
|
||||
<input
|
||||
v-model="selected.y"
|
||||
:disabled="!present"
|
||||
class="input-range"
|
||||
type="range"
|
||||
max="20"
|
||||
min="-20">
|
||||
</div>
|
||||
</div>
|
||||
<div class="preview-window">
|
||||
<div class="preview-block" :style="style"></div>
|
||||
</div>
|
||||
<div :disabled="!present" class="x-shift-control">
|
||||
<input
|
||||
v-model="selected.x"
|
||||
:disabled="!present"
|
||||
class="input-number"
|
||||
type="number">
|
||||
<div class="wrap">
|
||||
<input
|
||||
v-model="selected.x"
|
||||
:disabled="!present"
|
||||
class="input-range"
|
||||
type="range"
|
||||
max="20"
|
||||
min="-20">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="shadow-tweak">
|
||||
<div :disabled="usingFallback" class="id-control style-control">
|
||||
<label for="shadow-switcher" class="select" :disabled="!ready || usingFallback">
|
||||
<select
|
||||
v-model="selectedId" class="shadow-switcher"
|
||||
:disabled="!ready || usingFallback"
|
||||
id="shadow-switcher">
|
||||
<option v-for="(shadow, index) in cValue" :value="index">
|
||||
{{$t('settings.style.shadows.shadow_id', { value: index })}}
|
||||
</option>
|
||||
</select>
|
||||
<i class="icon-down-open"/>
|
||||
</label>
|
||||
<button class="btn btn-default" :disabled="!ready || !present" @click="del">
|
||||
<i class="icon-cancel"/>
|
||||
</button>
|
||||
<button class="btn btn-default" :disabled="!moveUpValid" @click="moveUp">
|
||||
<i class="icon-up-open"/>
|
||||
</button>
|
||||
<button class="btn btn-default" :disabled="!moveDnValid" @click="moveDn">
|
||||
<i class="icon-down-open"/>
|
||||
</button>
|
||||
<button class="btn btn-default" :disabled="usingFallback" @click="add">
|
||||
<i class="icon-plus"/>
|
||||
</button>
|
||||
</div>
|
||||
<div :disabled="!present" class="inset-control style-control">
|
||||
<label for="inset" class="label">
|
||||
{{$t('settings.style.shadows.inset')}}
|
||||
</label>
|
||||
<input
|
||||
v-model="selected.inset"
|
||||
:disabled="!present"
|
||||
name="inset"
|
||||
id="inset"
|
||||
class="input-inset"
|
||||
type="checkbox">
|
||||
<label class="checkbox-label" for="inset"></label>
|
||||
</div>
|
||||
<div :disabled="!present" class="blur-control style-control">
|
||||
<label for="spread" class="label">
|
||||
{{$t('settings.style.shadows.blur')}}
|
||||
</label>
|
||||
<input
|
||||
v-model="selected.blur"
|
||||
:disabled="!present"
|
||||
name="blur"
|
||||
id="blur"
|
||||
class="input-range"
|
||||
type="range"
|
||||
max="20"
|
||||
min="0">
|
||||
<input
|
||||
v-model="selected.blur"
|
||||
:disabled="!present"
|
||||
class="input-number"
|
||||
type="number"
|
||||
min="0">
|
||||
</div>
|
||||
<div :disabled="!present" class="spread-control style-control">
|
||||
<label for="spread" class="label">
|
||||
{{$t('settings.style.shadows.spread')}}
|
||||
</label>
|
||||
<input
|
||||
v-model="selected.spread"
|
||||
:disabled="!present"
|
||||
name="spread"
|
||||
id="spread"
|
||||
class="input-range"
|
||||
type="range"
|
||||
max="20"
|
||||
min="-20">
|
||||
<input
|
||||
v-model="selected.spread"
|
||||
:disabled="!present"
|
||||
class="input-number"
|
||||
type="number">
|
||||
</div>
|
||||
<ColorInput
|
||||
v-model="selected.color"
|
||||
:disabled="!present"
|
||||
:label="$t('settings.style.common.color')"
|
||||
name="shadow"/>
|
||||
<OpacityInput
|
||||
v-model="selected.alpha"
|
||||
:disabled="!present"/>
|
||||
<p>
|
||||
{{$t('settings.style.shadows.hint')}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script src="./shadow_control.js" ></script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../../_variables.scss';
|
||||
.shadow-control {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
margin-bottom: 1em;
|
||||
|
||||
.shadow-preview-container,
|
||||
.shadow-tweak {
|
||||
margin: 5px 6px 0 0;
|
||||
}
|
||||
.shadow-preview-container {
|
||||
flex: 0;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
$side: 15em;
|
||||
|
||||
input[type=number] {
|
||||
width: 5em;
|
||||
min-width: 2em;
|
||||
}
|
||||
.x-shift-control,
|
||||
.y-shift-control {
|
||||
display: flex;
|
||||
flex: 0;
|
||||
|
||||
&[disabled=disabled] *{
|
||||
opacity: .5
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.x-shift-control {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.x-shift-control .wrap,
|
||||
input[type=range] {
|
||||
margin: 0;
|
||||
width: $side;
|
||||
height: 2em;
|
||||
}
|
||||
.y-shift-control {
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
.wrap {
|
||||
width: 2em;
|
||||
height: $side;
|
||||
}
|
||||
input[type=range] {
|
||||
transform-origin: 1em 1em;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
.preview-window {
|
||||
flex: 1;
|
||||
background-color: #999999;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-image:
|
||||
linear-gradient(45deg, #666666 25%, transparent 25%),
|
||||
linear-gradient(-45deg, #666666 25%, transparent 25%),
|
||||
linear-gradient(45deg, transparent 75%, #666666 75%),
|
||||
linear-gradient(-45deg, transparent 75%, #666666 75%);
|
||||
background-size: 20px 20px;
|
||||
background-position:0 0, 0 10px, 10px -10px, -10px 0;
|
||||
|
||||
border-radius: $fallback--inputRadius;
|
||||
border-radius: var(--inputRadius, $fallback--inputRadius);
|
||||
|
||||
.preview-block {
|
||||
width: 33%;
|
||||
height: 33%;
|
||||
background-color: $fallback--bg;
|
||||
background-color: var(--bg, $fallback--bg);
|
||||
border-radius: $fallback--panelRadius;
|
||||
border-radius: var(--panelRadius, $fallback--panelRadius);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.shadow-tweak {
|
||||
flex: 1;
|
||||
min-width: 280px;
|
||||
|
||||
.id-control {
|
||||
align-items: stretch;
|
||||
.select, .btn {
|
||||
min-width: 1px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.btn {
|
||||
padding: 0 .4em;
|
||||
margin: 0 .1em;
|
||||
}
|
||||
.select {
|
||||
flex: 1;
|
||||
select {
|
||||
align-self: initial;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -0,0 +1,78 @@
|
||||
<template>
|
||||
<div class="panel dummy">
|
||||
<div class="panel-heading">
|
||||
<div class="title">
|
||||
{{$t('settings.style.preview.header')}}
|
||||
<span class="badge badge-notification">
|
||||
99
|
||||
</span>
|
||||
</div>
|
||||
<span class="faint">
|
||||
{{$t('settings.style.preview.header_faint')}}
|
||||
</span>
|
||||
<span class="alert error">
|
||||
{{$t('settings.style.preview.error')}}
|
||||
</span>
|
||||
<button class="btn">
|
||||
{{$t('settings.style.preview.button')}}
|
||||
</button>
|
||||
</div>
|
||||
<div class="panel-body theme-preview-content">
|
||||
<div class="post">
|
||||
<div class="avatar">
|
||||
( ͡° ͜ʖ ͡°)
|
||||
</div>
|
||||
<div class="content">
|
||||
<h4>
|
||||
{{$t('settings.style.preview.content')}}
|
||||
</h4>
|
||||
|
||||
<i18n path="settings.style.preview.text">
|
||||
<code style="font-family: var(--postCodeFont)">
|
||||
{{$t('settings.style.preview.mono')}}
|
||||
</code>
|
||||
<a style="color: var(--link)">
|
||||
{{$t('settings.style.preview.link')}}
|
||||
</a>
|
||||
</i18n>
|
||||
|
||||
<div class="icons">
|
||||
<i style="color: var(--cBlue)" class="icon-reply"/>
|
||||
<i style="color: var(--cGreen)" class="icon-retweet"/>
|
||||
<i style="color: var(--cOrange)" class="icon-star"/>
|
||||
<i style="color: var(--cRed)" class="icon-cancel"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="after-post">
|
||||
<div class="avatar-alt">
|
||||
:^)
|
||||
</div>
|
||||
<div class="content">
|
||||
<i18n path="settings.style.preview.fine_print" tag="span" class="faint">
|
||||
<a style="color: var(--faintLink)">
|
||||
{{$t('settings.style.preview.faint_link')}}
|
||||
</a>
|
||||
</i18n>
|
||||
</div>
|
||||
</div>
|
||||
<div class="separator"></div>
|
||||
|
||||
<span class="alert error">
|
||||
{{$t('settings.style.preview.error')}}
|
||||
</span>
|
||||
<input :value="$t('settings.style.preview.input')" type="text">
|
||||
|
||||
<div class="actions">
|
||||
<span class="checkbox">
|
||||
<input checked="very yes" type="checkbox" id="preview_checkbox">
|
||||
<label for="preview_checkbox">{{$t('settings.style.preview.checkbox')}}</label>
|
||||
</span>
|
||||
<button class="btn">
|
||||
{{$t('settings.style.preview.button')}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
@ -0,0 +1,335 @@
|
||||
@import '../../_variables.scss';
|
||||
.style-switcher {
|
||||
.preset-switcher {
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.style-control {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
margin-bottom: 5px;
|
||||
|
||||
.label {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
input, select {
|
||||
&:not(.exclude-disabled) {
|
||||
opacity: .5
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input, select {
|
||||
min-width: 3em;
|
||||
margin: 0;
|
||||
flex: 0;
|
||||
|
||||
&[type=color] {
|
||||
padding: 1px;
|
||||
cursor: pointer;
|
||||
height: 29px;
|
||||
min-width: 2em;
|
||||
border: none;
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
&[type=number] {
|
||||
min-width: 5em;
|
||||
}
|
||||
|
||||
&[type=range] {
|
||||
flex: 1;
|
||||
min-width: 3em;
|
||||
}
|
||||
|
||||
&[type=checkbox] + label {
|
||||
margin: 6px 0;
|
||||
}
|
||||
|
||||
&:not([type=number]):not([type=text]) {
|
||||
align-self: flex-start;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tab-switcher {
|
||||
margin: 0 -1em;
|
||||
}
|
||||
|
||||
.reset-container {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.fonts-container,
|
||||
.reset-container,
|
||||
.apply-container,
|
||||
.radius-container,
|
||||
.color-container,
|
||||
{
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.fonts-container,
|
||||
.radius-container {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.color-container{
|
||||
> h4 {
|
||||
width: 99%;
|
||||
}
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.fonts-container,
|
||||
.color-container,
|
||||
.shadow-container,
|
||||
.radius-container,
|
||||
.presets-container {
|
||||
margin: 1em 1em 0;
|
||||
}
|
||||
|
||||
.tab-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: baseline;
|
||||
width: 100%;
|
||||
min-height: 30px;
|
||||
|
||||
.btn {
|
||||
min-width: 1px;
|
||||
flex: 0 auto;
|
||||
padding: 0 1em;
|
||||
}
|
||||
|
||||
p {
|
||||
flex: 1;
|
||||
margin: 0;
|
||||
margin-right: .5em;
|
||||
}
|
||||
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.shadow-selector {
|
||||
.override {
|
||||
flex: 1;
|
||||
margin-left: .5em;
|
||||
}
|
||||
.select-container {
|
||||
margin-top: -4px;
|
||||
margin-bottom: -3px;
|
||||
}
|
||||
}
|
||||
|
||||
.save-load,
|
||||
.save-load-options {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: baseline;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.presets,
|
||||
.import-export {
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
|
||||
.import-export {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.override {
|
||||
margin-left: .5em;
|
||||
}
|
||||
}
|
||||
|
||||
.save-load-options {
|
||||
flex-wrap: wrap;
|
||||
margin-top: .5em;
|
||||
justify-content: center;
|
||||
.keep-option {
|
||||
margin: 0 .5em .5em;
|
||||
min-width: 25%;
|
||||
}
|
||||
}
|
||||
|
||||
.preview-container {
|
||||
border-top: 1px dashed;
|
||||
border-bottom: 1px dashed;
|
||||
border-color: $fallback--border;
|
||||
border-color: var(--border, $fallback--border);
|
||||
margin: 1em -1em 0;
|
||||
padding: 1em;
|
||||
background: var(--body-background-image);
|
||||
background-size: cover;
|
||||
background-position: 50% 50%;
|
||||
|
||||
.dummy {
|
||||
.post {
|
||||
font-family: var(--postFont);
|
||||
display: flex;
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
|
||||
h4 {
|
||||
margin-bottom: .25em;
|
||||
}
|
||||
|
||||
.icons {
|
||||
margin-top: .5em;
|
||||
display: flex;
|
||||
|
||||
i {
|
||||
margin-right: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.after-post {
|
||||
margin-top: 1em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.avatar, .avatar-alt{
|
||||
background: linear-gradient(135deg, #b8e1fc 0%,#a9d2f3 10%,#90bae4 25%,#90bcea 37%,#90bff0 50%,#6ba8e5 51%,#a2daf5 83%,#bdf3fd 100%);
|
||||
color: black;
|
||||
font-family: sans-serif;
|
||||
text-align: center;
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.avatar-alt {
|
||||
flex: 0 auto;
|
||||
margin-left: 28px;
|
||||
font-size: 12px;
|
||||
min-width: 20px;
|
||||
min-height: 20px;
|
||||
line-height: 20px;
|
||||
border-radius: $fallback--avatarAltRadius;
|
||||
border-radius: var(--avatarAltRadius, $fallback--avatarAltRadius);
|
||||
}
|
||||
|
||||
.avatar {
|
||||
flex: 0 auto;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
font-size: 14px;
|
||||
line-height: 48px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
|
||||
.checkbox {
|
||||
display: inline-flex;
|
||||
align-items: baseline;
|
||||
margin-right: 1em;
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.separator {
|
||||
margin: 1em;
|
||||
border-bottom: 1px solid;
|
||||
border-color: $fallback--border;
|
||||
border-color: var(--border, $fallback--border);
|
||||
}
|
||||
|
||||
.panel-heading {
|
||||
.badge, .alert, .btn, .faint {
|
||||
margin-left: 1em;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.faint {
|
||||
text-overflow: ellipsis;
|
||||
min-width: 2em;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.flex-spacer {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
.btn {
|
||||
margin-left: 0;
|
||||
padding: 0 1em;
|
||||
min-width: 3em;
|
||||
min-height: 30px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.apply-container {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.radius-item,
|
||||
.color-item {
|
||||
min-width: 20em;
|
||||
margin: 5px 6px 0 0;
|
||||
display:flex;
|
||||
flex-direction: column;
|
||||
flex: 1 1 0;
|
||||
|
||||
&.wide {
|
||||
min-width: 60%
|
||||
}
|
||||
|
||||
&:not(.wide):nth-child(2n+1) {
|
||||
margin-right: 7px;
|
||||
|
||||
}
|
||||
|
||||
.color, .opacity {
|
||||
display:flex;
|
||||
align-items: baseline;
|
||||
}
|
||||
}
|
||||
|
||||
.radius-item {
|
||||
flex-basis: auto;
|
||||
}
|
||||
|
||||
.theme-radius-rn,
|
||||
.theme-color-cl {
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
background: transparent;
|
||||
color: var(--faint, $fallback--faint);
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
.theme-color-cl,
|
||||
.theme-radius-in,
|
||||
.theme-color-in {
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.theme-radius-in {
|
||||
min-width: 1em;
|
||||
}
|
||||
|
||||
.theme-radius-in {
|
||||
max-width: 7em;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.theme-radius-lb{
|
||||
max-width: 50em;
|
||||
}
|
||||
|
||||
.theme-preview-content {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
margin-left: .25em;
|
||||
margin-right: .25em;
|
||||
}
|
||||
}
|
@ -1,300 +1,276 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="style-switcher">
|
||||
<div class="presets-container">
|
||||
<div>
|
||||
{{$t('settings.presets')}}
|
||||
<label for="style-switcher" class='select'>
|
||||
<select id="style-switcher" v-model="selected" class="style-switcher">
|
||||
<option v-for="style in availableStyles"
|
||||
:value="style"
|
||||
:style="{
|
||||
backgroundColor: style[1],
|
||||
color: style[3]
|
||||
}">
|
||||
{{style[0]}}
|
||||
</option>
|
||||
</select>
|
||||
<i class="icon-down-open"/>
|
||||
</label>
|
||||
<div class="save-load">
|
||||
<export-import
|
||||
:exportObject='exportedTheme'
|
||||
:exportLabel='$t("settings.export_theme")'
|
||||
:importLabel='$t("settings.import_theme")'
|
||||
:importFailedText='$t("settings.invalid_theme_imported")'
|
||||
:onImport='onImport'
|
||||
:validator='importValidator'>
|
||||
<template slot="before">
|
||||
<div class="presets">
|
||||
{{$t('settings.presets')}}
|
||||
<label for="preset-switcher" class='select'>
|
||||
<select id="preset-switcher" v-model="selected" class="preset-switcher">
|
||||
<option v-for="style in availableStyles"
|
||||
:value="style"
|
||||
:style="{
|
||||
backgroundColor: style[1] || style.theme.colors.bg,
|
||||
color: style[3] || style.theme.colors.text
|
||||
}">
|
||||
{{style[0] || style.name}}
|
||||
</option>
|
||||
</select>
|
||||
<i class="icon-down-open"/>
|
||||
</label>
|
||||
</div>
|
||||
</template>
|
||||
</export-import>
|
||||
</div>
|
||||
<div class="import-export">
|
||||
<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 class="save-load-options">
|
||||
<span class="keep-option">
|
||||
<input
|
||||
id="keep-color"
|
||||
type="checkbox"
|
||||
v-model="keepColor">
|
||||
<label for="keep-color">{{$t('settings.style.switcher.keep_color')}}</label>
|
||||
</span>
|
||||
<span class="keep-option">
|
||||
<input
|
||||
id="keep-shadows"
|
||||
type="checkbox"
|
||||
v-model="keepShadows">
|
||||
<label for="keep-shadows">{{$t('settings.style.switcher.keep_shadows')}}</label>
|
||||
</span>
|
||||
<span class="keep-option">
|
||||
<input
|
||||
id="keep-opacity"
|
||||
type="checkbox"
|
||||
v-model="keepOpacity">
|
||||
<label for="keep-opacity">{{$t('settings.style.switcher.keep_opacity')}}</label>
|
||||
</span>
|
||||
<span class="keep-option">
|
||||
<input
|
||||
id="keep-roundness"
|
||||
type="checkbox"
|
||||
v-model="keepRoundness">
|
||||
<label for="keep-roundness">{{$t('settings.style.switcher.keep_roundness')}}</label>
|
||||
</span>
|
||||
<span class="keep-option">
|
||||
<input
|
||||
id="keep-fonts"
|
||||
type="checkbox"
|
||||
v-model="keepFonts">
|
||||
<label for="keep-fonts">{{$t('settings.style.switcher.keep_fonts')}}</label>
|
||||
</span>
|
||||
<p>{{$t('settings.style.switcher.save_load_hint')}}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="preview-container">
|
||||
<div :style="{
|
||||
'--btnRadius': btnRadiusLocal + 'px',
|
||||
'--inputRadius': inputRadiusLocal + 'px',
|
||||
'--panelRadius': panelRadiusLocal + 'px',
|
||||
'--avatarRadius': avatarRadiusLocal + 'px',
|
||||
'--avatarAltRadius': avatarAltRadiusLocal + 'px',
|
||||
'--tooltipRadius': tooltipRadiusLocal + 'px',
|
||||
'--attachmentRadius': attachmentRadiusLocal + 'px'
|
||||
}">
|
||||
<div class="panel dummy">
|
||||
<div class="panel-heading" :style="{ 'background-color': btnColorLocal, 'color': textColorLocal }">Preview</div>
|
||||
<div class="panel-body theme-preview-content" :style="{ 'background-color': bgColorLocal, 'color': textColorLocal }">
|
||||
<div class="avatar" :style="{
|
||||
'border-radius': avatarRadiusLocal + 'px'
|
||||
}">
|
||||
( ͡° ͜ʖ ͡°)
|
||||
</div>
|
||||
<h4>Content</h4>
|
||||
<br>
|
||||
A bunch of more content and
|
||||
<a :style="{ color: linkColorLocal }">a nice lil' link</a>
|
||||
<i :style="{ color: blueColorLocal }" class="icon-reply"/>
|
||||
<i :style="{ color: greenColorLocal }" class="icon-retweet"/>
|
||||
<i :style="{ color: redColorLocal }" class="icon-cancel"/>
|
||||
<i :style="{ color: orangeColorLocal }" class="icon-star"/>
|
||||
<br>
|
||||
<button class="btn" :style="{ 'background-color': btnColorLocal, 'color': textColorLocal }">Button</button>
|
||||
<preview :style="previewRules"/>
|
||||
</div>
|
||||
|
||||
<keep-alive>
|
||||
<tab-switcher key="style-tweak">
|
||||
<div :label="$t('settings.style.common_colors._tab_label')" class="color-container">
|
||||
<div class="tab-header">
|
||||
<p>{{$t('settings.theme_help')}}</p>
|
||||
<button class="btn" @click="clearOpacity">{{$t('settings.style.switcher.clear_opacity')}}</button>
|
||||
<button class="btn" @click="clearV1">{{$t('settings.style.switcher.clear_all')}}</button>
|
||||
</div>
|
||||
<p>{{$t('settings.theme_help_v2_1')}}</p>
|
||||
<h4>{{ $t('settings.style.common_colors.main') }}</h4>
|
||||
<div class="color-item">
|
||||
<ColorInput name="bgColor" v-model="bgColorLocal" :label="$t('settings.background')"/>
|
||||
<OpacityInput name="bgOpacity" v-model="bgOpacityLocal" :fallback="previewTheme.opacity.bg || 1"/>
|
||||
<ColorInput name="textColor" v-model="textColorLocal" :label="$t('settings.text')"/>
|
||||
<ContrastRatio :contrast="previewContrast.bgText"/>
|
||||
<ColorInput name="linkColor" v-model="linkColorLocal" :label="$t('settings.links')"/>
|
||||
<ContrastRatio :contrast="previewContrast.bgLink"/>
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<ColorInput name="fgColor" v-model="fgColorLocal" :label="$t('settings.foreground')"/>
|
||||
<ColorInput name="fgTextColor" v-model="fgTextColorLocal" :label="$t('settings.text')" :fallback="previewTheme.colors.fgText"/>
|
||||
<ColorInput name="fgLinkColor" v-model="fgLinkColorLocal" :label="$t('settings.links')" :fallback="previewTheme.colors.fgLink"/>
|
||||
<p>{{ $t('settings.style.common_colors.foreground_hint') }}</p>
|
||||
</div>
|
||||
<h4>{{ $t('settings.style.common_colors.rgbo') }}</h4>
|
||||
<div class="color-item">
|
||||
<ColorInput name="cRedColor" v-model="cRedColorLocal" :label="$t('settings.cRed')"/>
|
||||
<ContrastRatio :contrast="previewContrast.bgRed"/>
|
||||
<ColorInput name="cBlueColor" v-model="cBlueColorLocal" :label="$t('settings.cBlue')"/>
|
||||
<ContrastRatio :contrast="previewContrast.bgBlue"/>
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<ColorInput name="cGreenColor" v-model="cGreenColorLocal" :label="$t('settings.cGreen')"/>
|
||||
<ContrastRatio :contrast="previewContrast.bgGreen"/>
|
||||
<ColorInput name="cOrangeColor" v-model="cOrangeColorLocal" :label="$t('settings.cOrange')"/>
|
||||
<ContrastRatio :contrast="previewContrast.bgOrange"/>
|
||||
</div>
|
||||
<p>{{$t('settings.theme_help_v2_2')}}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="color-container">
|
||||
<p>{{$t('settings.theme_help')}}</p>
|
||||
<div class="color-item">
|
||||
<label for="bgcolor" class="theme-color-lb">{{$t('settings.background')}}</label>
|
||||
<input id="bgcolor" class="theme-color-cl" type="color" v-model="bgColorLocal">
|
||||
<input id="bgcolor-t" class="theme-color-in" type="text" v-model="bgColorLocal">
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<label for="fgcolor" class="theme-color-lb">{{$t('settings.foreground')}}</label>
|
||||
<input id="fgcolor" class="theme-color-cl" type="color" v-model="btnColorLocal">
|
||||
<input id="fgcolor-t" class="theme-color-in" type="text" v-model="btnColorLocal">
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<label for="textcolor" class="theme-color-lb">{{$t('settings.text')}}</label>
|
||||
<input id="textcolor" class="theme-color-cl" type="color" v-model="textColorLocal">
|
||||
<input id="textcolor-t" class="theme-color-in" type="text" v-model="textColorLocal">
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<label for="linkcolor" class="theme-color-lb">{{$t('settings.links')}}</label>
|
||||
<input id="linkcolor" class="theme-color-cl" type="color" v-model="linkColorLocal">
|
||||
<input id="linkcolor-t" class="theme-color-in" type="text" v-model="linkColorLocal">
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<label for="redcolor" class="theme-color-lb">{{$t('settings.cRed')}}</label>
|
||||
<input id="redcolor" class="theme-color-cl" type="color" v-model="redColorLocal">
|
||||
<input id="redcolor-t" class="theme-color-in" type="text" v-model="redColorLocal">
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<label for="bluecolor" class="theme-color-lb">{{$t('settings.cBlue')}}</label>
|
||||
<input id="bluecolor" class="theme-color-cl" type="color" v-model="blueColorLocal">
|
||||
<input id="bluecolor-t" class="theme-color-in" type="text" v-model="blueColorLocal">
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<label for="greencolor" class="theme-color-lb">{{$t('settings.cGreen')}}</label>
|
||||
<input id="greencolor" class="theme-color-cl" type="color" v-model="greenColorLocal">
|
||||
<input id="greencolor-t" class="theme-color-in" type="green" v-model="greenColorLocal">
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<label for="orangecolor" class="theme-color-lb">{{$t('settings.cOrange')}}</label>
|
||||
<input id="orangecolor" class="theme-color-cl" type="color" v-model="orangeColorLocal">
|
||||
<input id="orangecolor-t" class="theme-color-in" type="text" v-model="orangeColorLocal">
|
||||
</div>
|
||||
</div>
|
||||
<div :label="$t('settings.style.advanced_colors._tab_label')" class="color-container">
|
||||
<div class="tab-header">
|
||||
<p>{{$t('settings.theme_help')}}</p>
|
||||
<button class="btn" @click="clearOpacity">{{$t('settings.style.switcher.clear_opacity')}}</button>
|
||||
<button class="btn" @click="clearV1">{{$t('settings.style.switcher.clear_all')}}</button>
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<h4>{{ $t('settings.style.advanced_colors.alert') }}</h4>
|
||||
<ColorInput name="alertError" v-model="alertErrorColorLocal" :label="$t('settings.style.advanced_colors.alert_error')" :fallback="previewTheme.colors.alertError"/>
|
||||
<ContrastRatio :contrast="previewContrast.alertError"/>
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<h4>{{ $t('settings.style.advanced_colors.badge') }}</h4>
|
||||
<ColorInput name="badgeNotification" v-model="badgeNotificationColorLocal" :label="$t('settings.style.advanced_colors.badge_notification')" :fallback="previewTheme.colors.badgeNotification"/>
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<h4>{{ $t('settings.style.advanced_colors.panel_header') }}</h4>
|
||||
<ColorInput name="panelColor" v-model="panelColorLocal" :fallback="fgColorLocal" :label="$t('settings.background')"/>
|
||||
<OpacityInput name="panelOpacity" v-model="panelOpacityLocal" :fallback="previewTheme.opacity.panel || 1"/>
|
||||
<ColorInput name="panelTextColor" v-model="panelTextColorLocal" :fallback="previewTheme.colors.panelText" :label="$t('settings.text')"/>
|
||||
<ContrastRatio :contrast="previewContrast.panelText" large="1"/>
|
||||
<ColorInput name="panelLinkColor" v-model="panelLinkColorLocal" :fallback="previewTheme.colors.panelLink" :label="$t('settings.links')"/>
|
||||
<ContrastRatio :contrast="previewContrast.panelLink" large="1"/>
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<h4>{{ $t('settings.style.advanced_colors.top_bar') }}</h4>
|
||||
<ColorInput name="topBarColor" v-model="topBarColorLocal" :fallback="fgColorLocal" :label="$t('settings.background')"/>
|
||||
<ColorInput name="topBarTextColor" v-model="topBarTextColorLocal" :fallback="previewTheme.colors.topBarText" :label="$t('settings.text')"/>
|
||||
<ContrastRatio :contrast="previewContrast.topBarText"/>
|
||||
<ColorInput name="topBarLinkColor" v-model="topBarLinkColorLocal" :fallback="previewTheme.colors.topBarLink" :label="$t('settings.links')"/>
|
||||
<ContrastRatio :contrast="previewContrast.topBarLink"/>
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<h4>{{ $t('settings.style.advanced_colors.inputs') }}</h4>
|
||||
<ColorInput name="inputColor" v-model="inputColorLocal" :fallback="fgColorLocal" :label="$t('settings.background')"/>
|
||||
<OpacityInput name="inputOpacity" v-model="inputOpacityLocal" :fallback="previewTheme.opacity.input || 1"/>
|
||||
<ColorInput name="inputTextColor" v-model="inputTextColorLocal" :fallback="previewTheme.colors.inputText" :label="$t('settings.text')"/>
|
||||
<ContrastRatio :contrast="previewContrast.inputText"/>
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<h4>{{ $t('settings.style.advanced_colors.buttons') }}</h4>
|
||||
<ColorInput name="btnColor" v-model="btnColorLocal" :fallback="fgColorLocal" :label="$t('settings.background')"/>
|
||||
<OpacityInput name="btnOpacity" v-model="btnOpacityLocal" :fallback="previewTheme.opacity.btn || 1"/>
|
||||
<ColorInput name="btnTextColor" v-model="btnTextColorLocal" :fallback="previewTheme.colors.btnText" :label="$t('settings.text')"/>
|
||||
<ContrastRatio :contrast="previewContrast.btnText"/>
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<h4>{{ $t('settings.style.advanced_colors.borders') }}</h4>
|
||||
<ColorInput name="borderColor" v-model="borderColorLocal" :fallback="previewTheme.colors.border" :label="$t('settings.style.common.color')"/>
|
||||
<OpacityInput name="borderOpacity" v-model="borderOpacityLocal" :fallback="previewTheme.opacity.border || 1"/>
|
||||
</div>
|
||||
<div class="color-item">
|
||||
<h4>{{ $t('settings.style.advanced_colors.faint_text') }}</h4>
|
||||
<ColorInput name="faintColor" v-model="faintColorLocal" :fallback="previewTheme.colors.faint || 1" :label="$t('settings.text')"/>
|
||||
<ColorInput name="faintLinkColor" v-model="faintLinkColorLocal" :fallback="previewTheme.colors.faintLink" :label="$t('settings.links')"/>
|
||||
<ColorInput name="panelFaintColor" v-model="panelFaintColorLocal" :fallback="previewTheme.colors.panelFaint" :label="$t('settings.style.advanced_colors.panel_header')"/>
|
||||
<OpacityInput name="faintOpacity" v-model="faintOpacityLocal" :fallback="previewTheme.opacity.faint || 0.5"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="radius-container">
|
||||
<p>{{$t('settings.radii_help')}}</p>
|
||||
<div class="radius-item">
|
||||
<label for="btnradius" class="theme-radius-lb">{{$t('settings.btnRadius')}}</label>
|
||||
<input id="btnradius" class="theme-radius-rn" type="range" v-model="btnRadiusLocal" max="16">
|
||||
<input id="btnradius-t" class="theme-radius-in" type="text" v-model="btnRadiusLocal">
|
||||
</div>
|
||||
<div class="radius-item">
|
||||
<label for="inputradius" class="theme-radius-lb">{{$t('settings.inputRadius')}}</label>
|
||||
<input id="inputradius" class="theme-radius-rn" type="range" v-model="inputRadiusLocal" max="16">
|
||||
<input id="inputradius-t" class="theme-radius-in" type="text" v-model="inputRadiusLocal">
|
||||
</div>
|
||||
<div class="radius-item">
|
||||
<label for="panelradius" class="theme-radius-lb">{{$t('settings.panelRadius')}}</label>
|
||||
<input id="panelradius" class="theme-radius-rn" type="range" v-model="panelRadiusLocal" max="50">
|
||||
<input id="panelradius-t" class="theme-radius-in" type="text" v-model="panelRadiusLocal">
|
||||
</div>
|
||||
<div class="radius-item">
|
||||
<label for="avatarradius" class="theme-radius-lb">{{$t('settings.avatarRadius')}}</label>
|
||||
<input id="avatarradius" class="theme-radius-rn" type="range" v-model="avatarRadiusLocal" max="28">
|
||||
<input id="avatarradius-t" class="theme-radius-in" type="green" v-model="avatarRadiusLocal">
|
||||
</div>
|
||||
<div class="radius-item">
|
||||
<label for="avataraltradius" class="theme-radius-lb">{{$t('settings.avatarAltRadius')}}</label>
|
||||
<input id="avataraltradius" class="theme-radius-rn" type="range" v-model="avatarAltRadiusLocal" max="28">
|
||||
<input id="avataraltradius-t" class="theme-radius-in" type="text" v-model="avatarAltRadiusLocal">
|
||||
</div>
|
||||
<div class="radius-item">
|
||||
<label for="attachmentradius" class="theme-radius-lb">{{$t('settings.attachmentRadius')}}</label>
|
||||
<input id="attachmentrradius" class="theme-radius-rn" type="range" v-model="attachmentRadiusLocal" max="50">
|
||||
<input id="attachmentradius-t" class="theme-radius-in" type="text" v-model="attachmentRadiusLocal">
|
||||
</div>
|
||||
<div class="radius-item">
|
||||
<label for="tooltipradius" class="theme-radius-lb">{{$t('settings.tooltipRadius')}}</label>
|
||||
<input id="tooltipradius" class="theme-radius-rn" type="range" v-model="tooltipRadiusLocal" max="20">
|
||||
<input id="tooltipradius-t" class="theme-radius-in" type="text" v-model="tooltipRadiusLocal">
|
||||
</div>
|
||||
</div>
|
||||
<div :label="$t('settings.style.radii._tab_label')" class="radius-container">
|
||||
<div class="tab-header">
|
||||
<p>{{$t('settings.radii_help')}}</p>
|
||||
<button class="btn" @click="clearRoundness">{{$t('settings.style.switcher.clear_all')}}</button>
|
||||
</div>
|
||||
<RangeInput name="btnRadius" :label="$t('settings.btnRadius')" v-model="btnRadiusLocal" :fallback="previewTheme.radii.btn" max="16" hardMin="0"/>
|
||||
<RangeInput name="inputRadius" :label="$t('settings.inputRadius')" v-model="inputRadiusLocal" :fallback="previewTheme.radii.input" max="9" hardMin="0"/>
|
||||
<RangeInput name="checkboxRadius" :label="$t('settings.checkboxRadius')" v-model="checkboxRadiusLocal" :fallback="previewTheme.radii.checkbox" max="16" hardMin="0"/>
|
||||
<RangeInput name="panelRadius" :label="$t('settings.panelRadius')" v-model="panelRadiusLocal" :fallback="previewTheme.radii.panel" max="50" hardMin="0"/>
|
||||
<RangeInput name="avatarRadius" :label="$t('settings.avatarRadius')" v-model="avatarRadiusLocal" :fallback="previewTheme.radii.avatar" max="28" hardMin="0"/>
|
||||
<RangeInput name="avatarAltRadius" :label="$t('settings.avatarAltRadius')" v-model="avatarAltRadiusLocal" :fallback="previewTheme.radii.avatarAlt" max="28" hardMin="0"/>
|
||||
<RangeInput name="attachmentRadius" :label="$t('settings.attachmentRadius')" v-model="attachmentRadiusLocal" :fallback="previewTheme.radii.attachment" max="50" hardMin="0"/>
|
||||
<RangeInput name="tooltipRadius" :label="$t('settings.tooltipRadius')" v-model="tooltipRadiusLocal" :fallback="previewTheme.radii.tooltip" max="50" hardMin="0"/>
|
||||
</div>
|
||||
|
||||
<div :label="$t('settings.style.shadows._tab_label')" class="shadow-container">
|
||||
<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">
|
||||
<option v-for="shadow in shadowsAvailable"
|
||||
:value="shadow">
|
||||
{{$t('settings.style.shadows.components.' + shadow)}}
|
||||
</option>
|
||||
</select>
|
||||
<i class="icon-down-open"/>
|
||||
</label>
|
||||
</div>
|
||||
<div class="override">
|
||||
<label for="override" class="label">
|
||||
{{$t('settings.style.shadows.override')}}
|
||||
</label>
|
||||
<input
|
||||
v-model="currentShadowOverriden"
|
||||
name="override"
|
||||
id="override"
|
||||
class="input-override"
|
||||
type="checkbox">
|
||||
<label class="checkbox-label" for="override"></label>
|
||||
</div>
|
||||
<button class="btn" @click="clearShadows">{{$t('settings.style.switcher.clear_all')}}</button>
|
||||
</div>
|
||||
<shadow-control :ready="!!currentShadowFallback" :fallback="currentShadowFallback" v-model="currentShadow"/>
|
||||
<div v-if="shadowSelected === 'avatar' || shadowSelected === 'avatarStatus'">
|
||||
<i18n path="settings.style.shadows.filter_hint.always_drop_shadow" tag="p">
|
||||
<code>filter: drop-shadow()</code>
|
||||
</i18n>
|
||||
<p>{{$t('settings.style.shadows.filter_hint.avatar_inset')}}</p>
|
||||
<i18n path="settings.style.shadows.filter_hint.drop_shadow_syntax" tag="p">
|
||||
<code>drop-shadow</code>
|
||||
<code>spread-radius</code>
|
||||
<code>inset</code>
|
||||
</i18n>
|
||||
<i18n path="settings.style.shadows.filter_hint.inset_classic" tag="p">
|
||||
<code>box-shadow</code>
|
||||
</i18n>
|
||||
<p>{{$t('settings.style.shadows.filter_hint.spread_zero')}}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div :label="$t('settings.style.fonts._tab_label')" class="fonts-container">
|
||||
<div class="tab-header">
|
||||
<p>{{$t('settings.style.fonts.help')}}</p>
|
||||
<button class="btn" @click="clearFonts">{{$t('settings.style.switcher.clear_all')}}</button>
|
||||
</div>
|
||||
<FontControl
|
||||
name="ui"
|
||||
v-model="fontsLocal.interface"
|
||||
:label="$t('settings.style.fonts.components.interface')"
|
||||
:fallback="previewTheme.fonts.interface"
|
||||
no-inherit="1"/>
|
||||
<FontControl
|
||||
name="input"
|
||||
v-model="fontsLocal.input"
|
||||
:label="$t('settings.style.fonts.components.input')"
|
||||
:fallback="previewTheme.fonts.input"/>
|
||||
<FontControl
|
||||
name="post"
|
||||
v-model="fontsLocal.post"
|
||||
:label="$t('settings.style.fonts.components.post')"
|
||||
:fallback="previewTheme.fonts.post"/>
|
||||
<FontControl
|
||||
name="postCode"
|
||||
v-model="fontsLocal.postCode"
|
||||
:label="$t('settings.style.fonts.components.postCode')"
|
||||
:fallback="previewTheme.fonts.postCode"/>
|
||||
</div>
|
||||
</tab-switcher>
|
||||
</keep-alive>
|
||||
|
||||
<div class="apply-container">
|
||||
<button class="btn submit" @click="setCustomTheme">{{$t('general.apply')}}</button>
|
||||
<button class="btn submit" :disabled="!themeValid" @click="setCustomTheme">{{$t('general.apply')}}</button>
|
||||
<button class="btn" @click="clearAll">{{$t('settings.style.switcher.reset')}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script src="./style_switcher.js"></script>
|
||||
|
||||
<style lang="scss">
|
||||
@import '../../_variables.scss';
|
||||
.style-switcher {
|
||||
margin-right: 1em;
|
||||
}
|
||||
|
||||
.import-warning {
|
||||
color: $fallback--cRed;
|
||||
color: var(--cRed, $fallback--cRed);
|
||||
}
|
||||
|
||||
.apply-container,
|
||||
.radius-container,
|
||||
.color-container,
|
||||
.presets-container {
|
||||
display: flex;
|
||||
|
||||
p {
|
||||
flex: 2 0 100%;
|
||||
margin-top: 2em;
|
||||
margin-bottom: .5em;
|
||||
}
|
||||
}
|
||||
|
||||
.radius-container {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.color-container {
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.presets-container {
|
||||
justify-content: center;
|
||||
.import-export {
|
||||
display: flex;
|
||||
|
||||
.btn {
|
||||
margin-left: .5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.preview-container {
|
||||
border-top: 1px dashed;
|
||||
border-bottom: 1px dashed;
|
||||
border-color: $fallback--border;
|
||||
border-color: var(--border, $fallback--border);
|
||||
margin: 1em -1em 0;
|
||||
padding: 1em;
|
||||
|
||||
.btn {
|
||||
margin-top: 1em;
|
||||
min-height: 30px;
|
||||
width: 10em;
|
||||
}
|
||||
}
|
||||
|
||||
.apply-container {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.radius-item,
|
||||
.color-item {
|
||||
min-width: 20em;
|
||||
display:flex;
|
||||
flex: 1 1 0;
|
||||
align-items: baseline;
|
||||
margin: 5px 6px 5px 0;
|
||||
|
||||
label {
|
||||
color: var(--faint, $fallback--faint);
|
||||
}
|
||||
}
|
||||
|
||||
.radius-item {
|
||||
flex-basis: auto;
|
||||
}
|
||||
|
||||
.theme-radius-rn,
|
||||
.theme-color-cl {
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
background: transparent;
|
||||
color: var(--faint, $fallback--faint);
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
.theme-color-cl,
|
||||
.theme-radius-in,
|
||||
.theme-color-in {
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.theme-color-in {
|
||||
min-width: 4em;
|
||||
}
|
||||
|
||||
.theme-radius-in {
|
||||
min-width: 1em;
|
||||
}
|
||||
|
||||
.theme-radius-in,
|
||||
.theme-color-in {
|
||||
max-width: 7em;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.theme-radius-lb,
|
||||
.theme-color-lb {
|
||||
flex: 2;
|
||||
min-width: 7em;
|
||||
}
|
||||
|
||||
.theme-radius-lb{
|
||||
max-width: 50em;
|
||||
}
|
||||
|
||||
.theme-color-lb {
|
||||
max-width: 10em;
|
||||
}
|
||||
|
||||
.theme-color-cl {
|
||||
padding: 1px;
|
||||
max-width: 8em;
|
||||
height: 100%;
|
||||
flex: 0;
|
||||
min-width: 2em;
|
||||
cursor: pointer;
|
||||
max-height: 29px;
|
||||
}
|
||||
|
||||
.theme-preview-content {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.dummy {
|
||||
.avatar {
|
||||
background: linear-gradient(135deg, #b8e1fc 0%,#a9d2f3 10%,#90bae4 25%,#90bcea 37%,#90bff0 50%,#6ba8e5 51%,#a2daf5 83%,#bdf3fd 100%);
|
||||
color: black;
|
||||
text-align: center;
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
width: 48px;
|
||||
float: left;
|
||||
margin-right: 1em;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style src="./style_switcher.scss" lang="scss"></style>
|
||||
|
@ -0,0 +1,12 @@
|
||||
import { capitalize } from 'lodash'
|
||||
|
||||
export function humanizeErrors (errors) {
|
||||
return Object.entries(errors).reduce((errs, [k, val]) => {
|
||||
let message = val.reduce((acc, message) => {
|
||||
let key = capitalize(k.replace(/_/g, ' '))
|
||||
return acc + [key, message].join(' ') + '. '
|
||||
}, '')
|
||||
return [...errs, message]
|
||||
}, [])
|
||||
}
|
||||
|
@ -0,0 +1,69 @@
|
||||
import runtime from 'serviceworker-webpack-plugin/lib/runtime'
|
||||
|
||||
function urlBase64ToUint8Array (base64String) {
|
||||
const padding = '='.repeat((4 - base64String.length % 4) % 4)
|
||||
const base64 = (base64String + padding)
|
||||
.replace(/-/g, '+')
|
||||
.replace(/_/g, '/')
|
||||
|
||||
const rawData = window.atob(base64)
|
||||
return Uint8Array.from([...rawData].map((char) => char.charCodeAt(0)))
|
||||
}
|
||||
|
||||
function isPushSupported () {
|
||||
return 'serviceWorker' in navigator && 'PushManager' in window
|
||||
}
|
||||
|
||||
function registerServiceWorker () {
|
||||
return runtime.register()
|
||||
.catch((err) => console.error('Unable to register service worker.', err))
|
||||
}
|
||||
|
||||
function subscribe (registration, isEnabled, vapidPublicKey) {
|
||||
if (!isEnabled) return Promise.reject(new Error('Web Push is disabled in config'))
|
||||
if (!vapidPublicKey) return Promise.reject(new Error('VAPID public key is not found'))
|
||||
|
||||
const subscribeOptions = {
|
||||
userVisibleOnly: true,
|
||||
applicationServerKey: urlBase64ToUint8Array(vapidPublicKey)
|
||||
}
|
||||
return registration.pushManager.subscribe(subscribeOptions)
|
||||
}
|
||||
|
||||
function sendSubscriptionToBackEnd (subscription, token) {
|
||||
return window.fetch('/api/v1/push/subscription/', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${token}`
|
||||
},
|
||||
body: JSON.stringify({
|
||||
subscription,
|
||||
data: {
|
||||
alerts: {
|
||||
follow: true,
|
||||
favourite: true,
|
||||
mention: true,
|
||||
reblog: true
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
.then((response) => {
|
||||
if (!response.ok) throw new Error('Bad status code from server.')
|
||||
return response.json()
|
||||
})
|
||||
.then((responseData) => {
|
||||
if (!responseData.id) throw new Error('Bad response from server.')
|
||||
return responseData
|
||||
})
|
||||
}
|
||||
|
||||
export default function registerPushNotifications (isEnabled, vapidPublicKey, token) {
|
||||
if (isPushSupported()) {
|
||||
registerServiceWorker()
|
||||
.then((registration) => subscribe(registration, isEnabled, vapidPublicKey))
|
||||
.then((subscription) => sendSubscriptionToBackEnd(subscription, token))
|
||||
.catch((e) => console.warn(`Failed to setup Web Push Notifications: ${e.message}`))
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/* eslint-env serviceworker */
|
||||
|
||||
import localForage from 'localforage'
|
||||
|
||||
function isEnabled () {
|
||||
return localForage.getItem('vuex-lz')
|
||||
.then(data => data.config.webPushNotifications)
|
||||
}
|
||||
|
||||
function getWindowClients () {
|
||||
return clients.matchAll({ includeUncontrolled: true })
|
||||
.then((clientList) => clientList.filter(({ type }) => type === 'window'))
|
||||
}
|
||||
|
||||
self.addEventListener('push', (event) => {
|
||||
if (event.data) {
|
||||
event.waitUntil(isEnabled().then((isEnabled) => {
|
||||
return isEnabled && getWindowClients().then((list) => {
|
||||
const data = event.data.json()
|
||||
|
||||
if (list.length === 0) return self.registration.showNotification(data.title, data)
|
||||
})
|
||||
}))
|
||||
}
|
||||
})
|
||||
|
||||
self.addEventListener('notificationclick', (event) => {
|
||||
event.notification.close()
|
||||
|
||||
event.waitUntil(getWindowClients().then((list) => {
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
var client = list[i]
|
||||
if (client.url === '/' && 'focus' in client) { return client.focus() }
|
||||
}
|
||||
|
||||
if (clients.openWindow) return clients.openWindow('/')
|
||||
}))
|
||||
})
|
File diff suppressed because one or more lines are too long
Binary file not shown.
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 17 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,139 @@
|
||||
{
|
||||
"_pleroma_theme_version": 2,
|
||||
"name": "Breezy Dark (beta)",
|
||||
"theme": {
|
||||
"shadows": {
|
||||
"panel": [
|
||||
{
|
||||
"x": "1",
|
||||
"y": "2",
|
||||
"blur": "6",
|
||||
"spread": 0,
|
||||
"color": "#000000",
|
||||
"alpha": 0.6
|
||||
}
|
||||
],
|
||||
"button": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": "0",
|
||||
"blur": "0",
|
||||
"spread": "1",
|
||||
"color": "#ffffff",
|
||||
"alpha": "0.15",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "1",
|
||||
"y": "1",
|
||||
"blur": "1",
|
||||
"spread": 0,
|
||||
"color": "#000000",
|
||||
"alpha": "0.3",
|
||||
"inset": false
|
||||
}
|
||||
],
|
||||
"panelHeader": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": "40",
|
||||
"blur": "40",
|
||||
"spread": "-40",
|
||||
"inset": true,
|
||||
"color": "#ffffff",
|
||||
"alpha": "0.1"
|
||||
}
|
||||
],
|
||||
"buttonHover": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": "0",
|
||||
"blur": 0,
|
||||
"spread": "1",
|
||||
"color": "--link",
|
||||
"alpha": "0.3",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "1",
|
||||
"y": "1",
|
||||
"blur": "1",
|
||||
"spread": 0,
|
||||
"color": "#000000",
|
||||
"alpha": "0.3",
|
||||
"inset": false
|
||||
}
|
||||
],
|
||||
"buttonPressed": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"blur": "0",
|
||||
"spread": "50",
|
||||
"color": "--faint",
|
||||
"alpha": 1,
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": "0",
|
||||
"blur": 0,
|
||||
"spread": "1",
|
||||
"color": "#ffffff",
|
||||
"alpha": 0.2,
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "1",
|
||||
"y": "1",
|
||||
"blur": 0,
|
||||
"spread": 0,
|
||||
"color": "#000000",
|
||||
"alpha": "0.3",
|
||||
"inset": false
|
||||
}
|
||||
],
|
||||
"input": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": "0",
|
||||
"blur": 0,
|
||||
"spread": "1",
|
||||
"color": "#FFFFFF",
|
||||
"alpha": "0.2",
|
||||
"inset": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"fonts": {},
|
||||
"opacity": {
|
||||
"input": "1",
|
||||
"panel": "0"
|
||||
},
|
||||
"colors": {
|
||||
"bg": "#31363b",
|
||||
"text": "#eff0f1",
|
||||
"link": "#3daee9",
|
||||
"fg": "#31363b",
|
||||
"panel": "#31363b",
|
||||
"input": "#232629",
|
||||
"topBarLink": "#eff0f1",
|
||||
"btn": "#31363b",
|
||||
"border": "#4c545b",
|
||||
"cRed": "#da4453",
|
||||
"cBlue": "#3daee9",
|
||||
"cGreen": "#27ae60",
|
||||
"cOrange": "#f67400"
|
||||
},
|
||||
"radii": {
|
||||
"btn": "2",
|
||||
"input": "2",
|
||||
"checkbox": "1",
|
||||
"panel": "2",
|
||||
"avatar": "2",
|
||||
"avatarAlt": "2",
|
||||
"tooltip": "2",
|
||||
"attachment": "2"
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,139 @@
|
||||
{
|
||||
"_pleroma_theme_version": 2,
|
||||
"name": "Breezy Light (beta)",
|
||||
"theme": {
|
||||
"shadows": {
|
||||
"panel": [
|
||||
{
|
||||
"x": "1",
|
||||
"y": "2",
|
||||
"blur": "6",
|
||||
"spread": 0,
|
||||
"color": "#000000",
|
||||
"alpha": 0.6
|
||||
}
|
||||
],
|
||||
"button": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": "0",
|
||||
"blur": "0",
|
||||
"spread": "1",
|
||||
"color": "#000000",
|
||||
"alpha": "0.3",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "1",
|
||||
"y": "1",
|
||||
"blur": "1",
|
||||
"spread": 0,
|
||||
"color": "#000000",
|
||||
"alpha": "0.3",
|
||||
"inset": false
|
||||
}
|
||||
],
|
||||
"panelHeader": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": "40",
|
||||
"blur": "40",
|
||||
"spread": "-40",
|
||||
"inset": true,
|
||||
"color": "#ffffff",
|
||||
"alpha": "0.1"
|
||||
}
|
||||
],
|
||||
"buttonHover": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": "0",
|
||||
"blur": 0,
|
||||
"spread": "1",
|
||||
"color": "--link",
|
||||
"alpha": "0.3",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "1",
|
||||
"y": "1",
|
||||
"blur": "1",
|
||||
"spread": 0,
|
||||
"color": "#000000",
|
||||
"alpha": "0.3",
|
||||
"inset": false
|
||||
}
|
||||
],
|
||||
"buttonPressed": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"blur": "0",
|
||||
"spread": "50",
|
||||
"color": "--faint",
|
||||
"alpha": 1,
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": 0,
|
||||
"y": "0",
|
||||
"blur": 0,
|
||||
"spread": "1",
|
||||
"color": "#ffffff",
|
||||
"alpha": 0.2,
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "1",
|
||||
"y": "1",
|
||||
"blur": 0,
|
||||
"spread": 0,
|
||||
"color": "#000000",
|
||||
"alpha": "0.3",
|
||||
"inset": false
|
||||
}
|
||||
],
|
||||
"input": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": "0",
|
||||
"blur": 0,
|
||||
"spread": "1",
|
||||
"color": "#000000",
|
||||
"alpha": "0.2",
|
||||
"inset": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"fonts": {},
|
||||
"opacity": {
|
||||
"input": "1"
|
||||
},
|
||||
"colors": {
|
||||
"bg": "#eff0f1",
|
||||
"text": "#232627",
|
||||
"link": "#2980b9",
|
||||
"fg": "#bcc2c7",
|
||||
"panel": "#475057",
|
||||
"panelText": "#fcfcfc",
|
||||
"input": "#fcfcfc",
|
||||
"topBar": "#475057",
|
||||
"topBarLink": "#eff0f1",
|
||||
"btn": "#eff0f1",
|
||||
"cRed": "#da4453",
|
||||
"cBlue": "#2980b9",
|
||||
"cGreen": "#27ae60",
|
||||
"cOrange": "#f67400"
|
||||
},
|
||||
"radii": {
|
||||
"btn": "2",
|
||||
"input": "2",
|
||||
"checkbox": "1",
|
||||
"panel": "2",
|
||||
"avatar": "2",
|
||||
"avatarAlt": "2",
|
||||
"tooltip": "2",
|
||||
"attachment": "2"
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,297 @@
|
||||
{
|
||||
"_pleroma_theme_version": 2,
|
||||
"name": "Redmond XX SE",
|
||||
"theme": {
|
||||
"shadows": {
|
||||
"panel": [
|
||||
{
|
||||
"x": "-1",
|
||||
"y": "-1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#000000",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "1",
|
||||
"y": "1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#dfdfdf",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "-2",
|
||||
"y": "-2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#848484",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "2",
|
||||
"y": "2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#FFFFFF",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "0",
|
||||
"y": "0",
|
||||
"blur": "0",
|
||||
"spread": "3",
|
||||
"color": "--bg",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
}
|
||||
],
|
||||
"panelHeader": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"blur": 0,
|
||||
"spread": "3",
|
||||
"inset": true,
|
||||
"color": "#c0c0c0",
|
||||
"alpha": 1
|
||||
},
|
||||
{
|
||||
"x": "-2200",
|
||||
"y": 0,
|
||||
"blur": "200",
|
||||
"spread": "-2000",
|
||||
"inset": true,
|
||||
"color": "#1084d0",
|
||||
"alpha": 1
|
||||
}
|
||||
],
|
||||
"button": [
|
||||
{
|
||||
"x": "-1",
|
||||
"y": "-1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#000000",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "1",
|
||||
"y": "1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#FFFFFF",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "-2",
|
||||
"y": "-2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#848484",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "2",
|
||||
"y": "2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#dfdfdf",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "0",
|
||||
"y": "0",
|
||||
"blur": "0",
|
||||
"spread": "3",
|
||||
"color": "--bg",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
}
|
||||
],
|
||||
"buttonHover": [
|
||||
{
|
||||
"x": "-1",
|
||||
"y": "-1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#000000",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "1",
|
||||
"y": "1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#FFFFFF",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "-2",
|
||||
"y": "-2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#848484",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "2",
|
||||
"y": "2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#dfdfdf",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "0",
|
||||
"y": "0",
|
||||
"blur": "0",
|
||||
"spread": "3",
|
||||
"color": "--bg",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
}
|
||||
],
|
||||
"buttonPressed": [
|
||||
{
|
||||
"x": "1",
|
||||
"y": "1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#000000",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "-1",
|
||||
"y": "-1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#FFFFFF",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "2",
|
||||
"y": "2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#848484",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "-2",
|
||||
"y": "-2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#dfdfdf",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "0",
|
||||
"y": "0",
|
||||
"blur": "0",
|
||||
"spread": "3",
|
||||
"color": "--bg",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
}
|
||||
],
|
||||
"input": [
|
||||
{
|
||||
"x": "-1",
|
||||
"y": "-1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#FFFFFF",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "1",
|
||||
"y": "1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#848484",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "-2",
|
||||
"y": "-2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#dfdfdf",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "2",
|
||||
"y": "2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#000000",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "0",
|
||||
"y": "0",
|
||||
"blur": "0",
|
||||
"spread": "3",
|
||||
"color": "--input",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"fonts": {},
|
||||
"opacity": {
|
||||
"input": "1",
|
||||
"faint": "1"
|
||||
},
|
||||
"colors": {
|
||||
"bg": "#c0c0c0",
|
||||
"text": "#000000",
|
||||
"link": "#0000ff",
|
||||
"fg": "#c0c0c0",
|
||||
"panel": "#000080",
|
||||
"panelFaint": "#c0c0c0",
|
||||
"input": "#ffffff",
|
||||
"topBar": "#000080",
|
||||
"topBarLink": "#ffffff",
|
||||
"btn": "#c0c0c0",
|
||||
"faint": "#3f3f3f",
|
||||
"faintLink": "#404080",
|
||||
"border": "#808080",
|
||||
"cRed": "#FF0000",
|
||||
"cBlue": "#008080",
|
||||
"cGreen": "#008000",
|
||||
"cOrange": "#808000"
|
||||
},
|
||||
"radii": {
|
||||
"btn": "0",
|
||||
"input": "0",
|
||||
"checkbox": "0",
|
||||
"panel": "0",
|
||||
"avatar": "0",
|
||||
"avatarAlt": "0",
|
||||
"tooltip": "0",
|
||||
"attachment": "0"
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,288 @@
|
||||
{
|
||||
"_pleroma_theme_version": 2,
|
||||
"name": "Redmond XX",
|
||||
"theme": {
|
||||
"shadows": {
|
||||
"panel": [
|
||||
{
|
||||
"x": "-1",
|
||||
"y": "-1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#000000",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "1",
|
||||
"y": "1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#dfdfdf",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "-2",
|
||||
"y": "-2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#848484",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "2",
|
||||
"y": "2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#FFFFFF",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "0",
|
||||
"y": "0",
|
||||
"blur": "0",
|
||||
"spread": "3",
|
||||
"color": "--bg",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
}
|
||||
],
|
||||
"panelHeader": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"blur": 0,
|
||||
"spread": "3",
|
||||
"inset": true,
|
||||
"color": "#c0c0c0",
|
||||
"alpha": 1
|
||||
}
|
||||
],
|
||||
"button": [
|
||||
{
|
||||
"x": "-1",
|
||||
"y": "-1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#000000",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "1",
|
||||
"y": "1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#FFFFFF",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "-2",
|
||||
"y": "-2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#848484",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "2",
|
||||
"y": "2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#dfdfdf",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "0",
|
||||
"y": "0",
|
||||
"blur": "0",
|
||||
"spread": "3",
|
||||
"color": "--bg",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
}
|
||||
],
|
||||
"buttonHover": [
|
||||
{
|
||||
"x": "-1",
|
||||
"y": "-1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#000000",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "1",
|
||||
"y": "1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#FFFFFF",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "-2",
|
||||
"y": "-2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#848484",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "2",
|
||||
"y": "2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#dfdfdf",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "0",
|
||||
"y": "0",
|
||||
"blur": "0",
|
||||
"spread": "3",
|
||||
"color": "--bg",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
}
|
||||
],
|
||||
"buttonPressed": [
|
||||
{
|
||||
"x": "1",
|
||||
"y": "1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#000000",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "-1",
|
||||
"y": "-1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#FFFFFF",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "2",
|
||||
"y": "2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#848484",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "-2",
|
||||
"y": "-2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#dfdfdf",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "0",
|
||||
"y": "0",
|
||||
"blur": "0",
|
||||
"spread": "3",
|
||||
"color": "--bg",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
}
|
||||
],
|
||||
"input": [
|
||||
{
|
||||
"x": "-1",
|
||||
"y": "-1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#FFFFFF",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "1",
|
||||
"y": "1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#848484",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "-2",
|
||||
"y": "-2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#dfdfdf",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "2",
|
||||
"y": "2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#000000",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "0",
|
||||
"y": "0",
|
||||
"blur": "0",
|
||||
"spread": "3",
|
||||
"color": "--input",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"fonts": {},
|
||||
"opacity": {
|
||||
"input": "1",
|
||||
"faint": "1"
|
||||
},
|
||||
"colors": {
|
||||
"bg": "#c0c0c0",
|
||||
"text": "#000000",
|
||||
"link": "#0000ff",
|
||||
"fg": "#c0c0c0",
|
||||
"panel": "#000080",
|
||||
"panelFaint": "#c0c0c0",
|
||||
"input": "#ffffff",
|
||||
"topBar": "#000080",
|
||||
"topBarLink": "#ffffff",
|
||||
"btn": "#c0c0c0",
|
||||
"faint": "#3f3f3f",
|
||||
"faintLink": "#404080",
|
||||
"border": "#808080",
|
||||
"cRed": "#FF0000",
|
||||
"cBlue": "#008080",
|
||||
"cGreen": "#008000",
|
||||
"cOrange": "#808000"
|
||||
},
|
||||
"radii": {
|
||||
"btn": "0",
|
||||
"input": "0",
|
||||
"checkbox": "0",
|
||||
"panel": "0",
|
||||
"avatar": "0",
|
||||
"avatarAlt": "0",
|
||||
"tooltip": "0",
|
||||
"attachment": "0"
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,270 @@
|
||||
{
|
||||
"_pleroma_theme_version": 2,
|
||||
"name": "Redmond XXI",
|
||||
"theme": {
|
||||
"shadows": {
|
||||
"panel": [
|
||||
{
|
||||
"x": "-1",
|
||||
"y": "-1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#404040",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "1",
|
||||
"y": "1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#dfdfdf",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "-2",
|
||||
"y": "-2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#848484",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "2",
|
||||
"y": "2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#FFFFFF",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "0",
|
||||
"y": "0",
|
||||
"blur": "0",
|
||||
"spread": "3",
|
||||
"color": "--bg",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
}
|
||||
],
|
||||
"panelHeader": [
|
||||
{
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"blur": 0,
|
||||
"spread": "3",
|
||||
"inset": true,
|
||||
"color": "#d6d6ce",
|
||||
"alpha": 1
|
||||
},
|
||||
{
|
||||
"x": "-2200",
|
||||
"y": 0,
|
||||
"blur": "200",
|
||||
"spread": "-2000",
|
||||
"inset": true,
|
||||
"color": "#a5cef7",
|
||||
"alpha": 1
|
||||
}
|
||||
],
|
||||
"button": [
|
||||
{
|
||||
"x": "-1",
|
||||
"y": "-1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#404040",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "1",
|
||||
"y": "1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#FFFFFF",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "-2",
|
||||
"y": "-2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#848484",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "0",
|
||||
"y": "0",
|
||||
"blur": "0",
|
||||
"spread": "3",
|
||||
"color": "--bg",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
}
|
||||
],
|
||||
"buttonHover": [
|
||||
{
|
||||
"x": "-1",
|
||||
"y": "-1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#404040",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "1",
|
||||
"y": "1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#FFFFFF",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "-2",
|
||||
"y": "-2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#848484",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "0",
|
||||
"y": "0",
|
||||
"blur": "0",
|
||||
"spread": "3",
|
||||
"color": "--bg",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
}
|
||||
],
|
||||
"buttonPressed": [
|
||||
{
|
||||
"x": "1",
|
||||
"y": "1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#404040",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "-1",
|
||||
"y": "-1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#FFFFFF",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "2",
|
||||
"y": "2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#848484",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "0",
|
||||
"y": "0",
|
||||
"blur": "0",
|
||||
"spread": "3",
|
||||
"color": "--bg",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
}
|
||||
],
|
||||
"input": [
|
||||
{
|
||||
"x": "-1",
|
||||
"y": "-1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#FFFFFF",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "1",
|
||||
"y": "1",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#848484",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "-2",
|
||||
"y": "-2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#d4d0c8",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "2",
|
||||
"y": "2",
|
||||
"blur": "0",
|
||||
"spread": 0,
|
||||
"color": "#404040",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
},
|
||||
{
|
||||
"x": "0",
|
||||
"y": "0",
|
||||
"blur": "0",
|
||||
"spread": "3",
|
||||
"color": "--input",
|
||||
"alpha": "1",
|
||||
"inset": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"fonts": {},
|
||||
"opacity": {
|
||||
"input": "1",
|
||||
"faint": "1"
|
||||
},
|
||||
"colors": {
|
||||
"bg": "#d6d6ce",
|
||||
"text": "#000000",
|
||||
"link": "#0000ff",
|
||||
"fg": "#d6d6ce",
|
||||
"panel": "#042967",
|
||||
"panelFaint": "#FFFFFF",
|
||||
"input": "#ffffff",
|
||||
"topBar": "#042967",
|
||||
"topBarLink": "#ffffff",
|
||||
"btn": "#d6d6ce",
|
||||
"faint": "#3f3f3f",
|
||||
"faintLink": "#404080",
|
||||
"border": "#808080",
|
||||
"cRed": "#c42726",
|
||||
"cBlue": "#6699cc",
|
||||
"cGreen": "#669966",
|
||||
"cOrange": "#cc6633"
|
||||
},
|
||||
"radii": {
|
||||
"btn": "0",
|
||||
"input": "0",
|
||||
"checkbox": "0",
|
||||
"panel": "0",
|
||||
"avatar": "0",
|
||||
"avatarAlt": "0",
|
||||
"tooltip": "0",
|
||||
"attachment": "0"
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in new issue