palettes that actually work

This commit is contained in:
Henry Jameson 2024-10-01 00:42:33 +03:00
parent 07a48315a1
commit f0957bdb4f
12 changed files with 393 additions and 170 deletions

View file

@ -63,11 +63,17 @@ export default {
} }
}, },
{ {
state: ['hover', 'pressed'], state: ['pressed', 'hover'],
directives: { directives: {
shadow: ['--defaultButtonHoverGlow', '--pressedButtonBevel'] shadow: ['--defaultButtonHoverGlow', '--pressedButtonBevel']
} }
}, },
{
state: ['pressed', 'hover', 'focused'],
directives: {
shadow: ['--pressedButtonBevel']
}
},
{ {
state: ['toggled'], state: ['toggled'],
directives: { directives: {

View file

@ -1,21 +1,73 @@
<template> <template>
<div class="PaletteEditor"> <div class="PaletteEditor">
<ColorInput <div class="colors">
v-for="key in paletteKeys" <ColorInput
:key="key" v-for="key in paletteKeys"
:model-value="props.modelValue[key]" :key="key"
:fallback="fallback(key)" :model-value="props.modelValue[key]"
:label="$t('settings.style.themes3.editor.palette.' + key)" :fallback="fallback(key)"
@update:modelValue="value => updatePalette(key, value)" :label="$t('settings.style.themes3.palette.' + key)"
/> @update:modelValue="value => updatePalette(key, value)"
/>
</div>
<div class="controls">
<button
class="btn button-default"
@click="importPalette"
>
<FAIcon icon="file-import"/>
{{ $t('settings.style.themes3.palette.import') }}
</button>
<button
class="btn button-default"
@click="exportPalette"
>
<FAIcon icon="file-export"/>
{{ $t('settings.style.themes3.palette.export') }}
</button>
</div>
</div> </div>
</template> </template>
<script setup> <script setup>
import ColorInput from 'src/components/color_input/color_input.vue' import ColorInput from 'src/components/color_input/color_input.vue'
import {
// newImporter,
newExporter
} from 'src/services/export_import/export_import.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {
faFileImport,
faFileExport
} from '@fortawesome/free-solid-svg-icons'
library.add(
faFileImport,
faFileExport
)
const props = defineProps(['modelValue']) const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue']) const emit = defineEmits(['update:modelValue'])
const paletteExporter = newExporter({
filename: 'pleroma.palette.json',
getExportedObject: () => props.modelValue
})
/*
const themeImporter = newImporter({
validator: importValidator,
onImport,
onImportFailure,
})
*/
const exportPalette = () => {
paletteExporter.exportData()
}
const importPalette = () => {
// TODO
}
const paletteKeys = [ const paletteKeys = [
'bg', 'bg',
@ -40,7 +92,7 @@ const fallback = (key) => {
return props.modelValue.accent return props.modelValue.accent
} }
if (key.startsWith('extra')) { if (key.startsWith('extra')) {
return '#000000' return '#008080'
} }
} }
@ -54,10 +106,18 @@ const updatePalette = (paletteKey, value) => {
<style lang="scss"> <style lang="scss">
.PaletteEditor { .PaletteEditor {
display: grid; .colors {
justify-content: space-around; display: grid;
grid-template-columns: repeat(4, min-content); justify-content: space-around;
grid-template-rows: repeat(auto-fit, min-content); grid-template-columns: repeat(4, min-content);
grid-gap: 0.5em; grid-template-rows: repeat(auto-fit, min-content);
grid-gap: 0.5em;
}
.controls {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 0.5em;
}
} }
</style> </style>

View file

@ -9,7 +9,7 @@ import FontControl from 'src/components/font_control/font_control.vue'
import { normalizeThemeData } from 'src/modules/interface' import { normalizeThemeData } from 'src/modules/interface'
import { import {
getThemes getThemeResources
} from 'src/services/style_setter/style_setter.js' } from 'src/services/style_setter/style_setter.js'
import { convertTheme2To3 } from 'src/services/theme_data/theme2_to_theme3.js' import { convertTheme2To3 } from 'src/services/theme_data/theme2_to_theme3.js'
import { init } from 'src/services/theme_data/theme_data_3.service.js' import { init } from 'src/services/theme_data/theme_data_3.service.js'
@ -35,6 +35,17 @@ const AppearanceTab = {
data () { data () {
return { return {
availableStyles: [], availableStyles: [],
availablePalettes: [],
palettesKeys: [
'background',
'foreground',
'link',
'text',
'cRed',
'cBlue',
'cGreen',
'cOrange'
],
intersectionObserver: null, intersectionObserver: null,
thirdColumnModeOptions: ['none', 'notifications', 'postform'].map(mode => ({ thirdColumnModeOptions: ['none', 'notifications', 'postform'].map(mode => ({
key: mode, key: mode,
@ -64,29 +75,36 @@ const AppearanceTab = {
Preview Preview
}, },
mounted () { mounted () {
getThemes() getThemeResources('/static/styles.json')
.then((promises) => { .then((themes) => {
return Promise.all( this.availableStyles = Object
Object.entries(promises) .entries(themes)
.map(([k, v]) => v.then(res => [k, res])) .map(([key, data]) => ({ key, data, name: data.name || data[0], version: 'v2' }))
)
}) })
.then(themes => themes.reduce((acc, [k, v]) => {
if (v) { getThemeResources('/static/palettes/index.json')
return [ .then((palettes) => {
...acc, const result = {}
{ console.log(palettes)
name: v.name || v[0], Object.entries(palettes).forEach(([k, v]) => {
key: k, if (Array.isArray(v)) {
data: v const [
} name,
] background,
} else { foreground,
return acc text,
} link,
}, [])) cRed = '#FF0000',
.then((themesComplete) => { cBlue = '#0000FF',
this.availableStyles = themesComplete cGreen = '#00FF00',
cOrange = '#E3FF00'
] = v
result[k] = { name, background, foreground, text, link, cRed, cBlue, cGreen, cOrange }
} else {
result[k] = v
}
})
this.availablePalettes = result
}) })
if (window.IntersectionObserver) { if (window.IntersectionObserver) {
@ -171,18 +189,30 @@ const AppearanceTab = {
setTheme (name) { setTheme (name) {
this.$store.dispatch('setTheme', { themeName: name, saveData: true, recompile: true }) this.$store.dispatch('setTheme', { themeName: name, saveData: true, recompile: true })
}, },
setPalette (name) {
this.$store.dispatch('setPalette', { paletteData: name })
},
previewTheme (key, input) { previewTheme (key, input) {
const style = normalizeThemeData(input) let theme3
const x = 2 if (input) {
if (x === 1) return const style = normalizeThemeData(input)
const theme2 = convertTheme2To3(style) const theme2 = convertTheme2To3(style)
const theme3 = init({ theme3 = init({
inputRuleset: theme2, inputRuleset: theme2,
ultimateBackgroundColor: '#000000', ultimateBackgroundColor: '#000000',
liteMode: true, liteMode: true,
debug: true, debug: true,
onlyNormalState: true onlyNormalState: true
}) })
} else {
theme3 = init({
inputRuleset: [],
ultimateBackgroundColor: '#000000',
liteMode: true,
debug: true,
onlyNormalState: true
})
}
return getScopedVersion( return getScopedVersion(
getCssRules(theme3.eager), getCssRules(theme3.eager),

View file

@ -0,0 +1,76 @@
.appearance-tab {
.palette,
.theme-notice {
padding: 0.5em;
margin: 1em;
}
.palettes {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 0.5em;
}
.palette-entry {
display: flex;
align-items: center;
> label {
flex: 1 0 auto;
}
.palette-square {
flex: 0 0 auto;
display: inline-block;
min-width: 1em;
min-height: 1em;
}
}
.column-settings {
display: flex;
justify-content: space-evenly;
flex-wrap: wrap;
}
.column-settings .size-label {
display: block;
margin-bottom: 0.5em;
margin-top: 0.5em;
}
.theme-list {
list-style: none;
display: flex;
flex-wrap: wrap;
margin: -0.5em 0;
height: 25em;
overflow-x: hidden;
overflow-y: auto;
scrollbar-gutter: stable;
border-radius: var(--roundness);
border: 1px solid var(--border);
padding: 0;
.theme-preview {
font-size: 1rem; // fix for firefox
width: 19rem;
display: flex;
flex-direction: column;
align-items: center;
margin: 0.5em;
&.placeholder {
opacity: 0.2;
}
.theme-preview-container {
pointer-events: none;
zoom: 0.5;
border: none;
border-radius: var(--roundness);
text-align: left;
}
}
}
}

View file

@ -6,13 +6,33 @@
class="theme-list" class="theme-list"
ref="themeList" ref="themeList"
> >
<button
class="button-default theme-preview"
data-theme-key="stock"
@click="setTheme(null)"
>
<!-- eslint-disable vue/no-v-text-v-html-on-component -->
<component
:is="'style'"
v-html="previewTheme('stock')"
/>
<!-- eslint-enable vue/no-v-text-v-html-on-component -->
<preview />
<h4 class="theme-name">
{{ $t('settings.style.stock_theme_used') }}
<span class="alert neutral version">v3</span>
</h4>
</button>
<button <button
v-if="isCustomThemeUsed" v-if="isCustomThemeUsed"
disabled disabled
class="button-default theme-preview" class="button-default theme-preview"
> >
<preview /> <preview />
<h4 class="theme-name">{{ $t('settings.style.custom_theme_used') }}</h4> <h4 class="theme-name">
{{ $t('settings.style.custom_theme_used') }}
<span class="alert neutral version">v2</span>
</h4>
</button> </button>
<button <button
v-for="style in availableStyles" v-for="style in availableStyles"
@ -30,9 +50,31 @@
/> />
<!-- eslint-enable vue/no-v-text-v-html-on-component --> <!-- eslint-enable vue/no-v-text-v-html-on-component -->
<preview :class="{ placeholder: ready }" :id="'theme-preview-' + style.key"/> <preview :class="{ placeholder: ready }" :id="'theme-preview-' + style.key"/>
<h4 class="theme-name">{{ style.name }}</h4> <h4 class="theme-name">
{{ style.name }}
<span class="alert neutral version">{{ style.version }}</span>
</h4>
</button> </button>
</ul> </ul>
<h3>{{ $t('settings.style.themes3.palette.label') }}</h3>
<div class="palettes">
<button
v-for="p in availablePalettes"
class="btn button-default palette-entry"
:key="p.name"
@click="() => setPalette(p)"
>
<label>
{{ p.name }}
</label>
<span
v-for="c in palettesKeys"
:key="c"
class="palette-square"
:style="{ backgroundColor: p[c], border: '1px solid ' + (p[c] ?? 'var(--text)') }"
/>
</button>
</div>
</div> </div>
<div class="alert neutral theme-notice"> <div class="alert neutral theme-notice">
{{ $t("settings.style.appearance_tab_note") }} {{ $t("settings.style.appearance_tab_note") }}
@ -256,58 +298,4 @@
<script src="./appearance_tab.js"></script> <script src="./appearance_tab.js"></script>
<style lang="scss"> <style lang="scss" src="./appearance_tab.scss"></style>
.appearance-tab {
.theme-notice {
padding: 0.5em;
margin: 1em;
}
.column-settings {
display: flex;
justify-content: space-evenly;
flex-wrap: wrap;
}
.column-settings .size-label {
display: block;
margin-bottom: 0.5em;
margin-top: 0.5em;
}
.theme-list {
list-style: none;
display: flex;
flex-wrap: wrap;
margin: -0.5em 0;
height: 25em;
overflow-x: hidden;
overflow-y: auto;
scrollbar-gutter: stable;
border-radius: var(--roundness);
border: 1px solid var(--border);
padding: 0;
.theme-preview {
font-size: 1rem; // fix for firefox
width: 19rem;
display: flex;
flex-direction: column;
align-items: center;
margin: 0.5em;
&.placeholder {
opacity: 0.2;
}
.theme-preview-container {
pointer-events: none;
zoom: 0.5;
border: none;
border-radius: var(--roundness);
text-align: left;
}
}
}
}
</style>

View file

@ -54,7 +54,7 @@
<div class="setting-item palette-editor"> <div class="setting-item palette-editor">
<div class="label"> <div class="label">
<label for="palette-selector"> <label for="palette-selector">
{{ $t('settings.style.themes3.editor.palette.label') }} {{ $t('settings.style.themes3.palette.label') }}
{{ ' ' }} {{ ' ' }}
</label> </label>
<Select <Select
@ -62,10 +62,10 @@
id="palette-selector" id="palette-selector"
> >
<option key="dark" value="dark"> <option key="dark" value="dark">
{{ $t('settings.style.themes3.editor.palette.dark') }} {{ $t('settings.style.themes3.palette.dark') }}
</option> </option>
<option key="light" value="light"> <option key="light" value="light">
{{ $t('settings.style.themes3.editor.palette.light') }} {{ $t('settings.style.themes3.palette.light') }}
</option> </option>
</Select> </Select>
</div> </div>

View file

@ -5,7 +5,7 @@ import {
relativeLuminance relativeLuminance
} from 'src/services/color_convert/color_convert.js' } from 'src/services/color_convert/color_convert.js'
import { import {
getThemes getThemeResources
} from 'src/services/style_setter/style_setter.js' } from 'src/services/style_setter/style_setter.js'
import { import {
newImporter, newImporter,
@ -125,25 +125,9 @@ export default {
created () { created () {
const self = this const self = this
getThemes() getThemeResources('/static/styles.json')
.then((promises) => {
return Promise.all(
Object.entries(promises)
.map(([k, v]) => v.then(res => [k, res]))
)
})
.then(themes => themes.reduce((acc, [k, v]) => {
if (v) {
return {
...acc,
[k]: v
}
} else {
return acc
}
}, {}))
.then((themesComplete) => { .then((themesComplete) => {
self.availableStyles = themesComplete self.availableStyles = Object.values(themesComplete)
}) })
}, },
mounted () { mounted () {
@ -412,9 +396,6 @@ export default {
forceUseSource = false forceUseSource = false
) { ) {
this.dismissWarning() this.dismissWarning()
if (!source && !theme) {
throw new Error('Can\'t load theme: empty')
}
const version = (origin === 'localStorage' && !theme.colors) const version = (origin === 'localStorage' && !theme.colors)
? 'l1' ? 'l1'
: fileVersion : fileVersion
@ -494,14 +475,7 @@ export default {
customTheme: theme, customTheme: theme,
customThemeSource: source customThemeSource: source
} = this.$store.getters.mergedConfig } = this.$store.getters.mergedConfig
if (!theme && !source) { if (theme || source) {
// Anon user or never touched themes
this.loadTheme(
this.$store.state.instance.themeData,
'defaults',
confirmLoadSource
)
} else {
this.loadTheme( this.loadTheme(
{ {
theme, theme,

View file

@ -748,11 +748,31 @@
"more_settings": "More settings", "more_settings": "More settings",
"style": { "style": {
"custom_theme_used": "(Custom theme)", "custom_theme_used": "(Custom theme)",
"stock_theme_used": "(Stock theme)",
"themes2_outdated": "Editor for Themes V2 is being phased out and will eventually be replaced with a new one that takes advantage of new Themes V3 engine. It should still work but experience might be degraded and inconsistent.", "themes2_outdated": "Editor for Themes V2 is being phased out and will eventually be replaced with a new one that takes advantage of new Themes V3 engine. It should still work but experience might be degraded and inconsistent.",
"appearance_tab_note": "Changes on this tab do not affect the theme used, so exported theme will be different from what seen in the UI", "appearance_tab_note": "Changes on this tab do not affect the theme used, so exported theme will be different from what seen in the UI",
"update_preview": "Update preview", "update_preview": "Update preview",
"themes3": { "themes3": {
"define": "Override", "define": "Override",
"palette": {
"label": "Palette",
"import": "Import",
"export": "Export",
"dark": "Dark mode",
"light": "Light mode",
"bg": "Panel background",
"fg": "Buttons etc.",
"text": "Text",
"link": "Links",
"accent": "Accent color",
"cRed": "Red color",
"cBlue": "Blue color",
"cGreen": "Green color",
"cOrange": "Orange color",
"extra1": "Extra 1",
"extra2": "Extra 2",
"extra3": "Extra 3"
},
"editor": { "editor": {
"title": "Style", "title": "Style",
"new_style": "New", "new_style": "New",
@ -778,23 +798,6 @@
"preserve": "Keep color", "preserve": "Keep color",
"no-auto": "Disabled" "no-auto": "Disabled"
}, },
"palette": {
"label": "Palette",
"dark": "Dark mode",
"light": "Light mode",
"bg": "Panel background",
"fg": "Buttons etc.",
"text": "Text",
"link": "Links",
"accent": "Accent color",
"cRed": "Red color",
"cBlue": "Blue color",
"cGreen": "Green color",
"cOrange": "Orange color",
"extra1": "Extra 1",
"extra2": "Extra 2",
"extra3": "Extra 3"
},
"components": { "components": {
"normal": { "normal": {
"state": "Normal", "state": "Normal",

View file

@ -212,6 +212,11 @@ const interfaceMod = {
setLastTimeline ({ commit }, value) { setLastTimeline ({ commit }, value) {
commit('setLastTimeline', value) commit('setLastTimeline', value)
}, },
setPalette ({ dispatch, commit }, { paletteData }) {
console.log('PAL', paletteData)
commit('setOption', { name: 'userPalette', value: paletteData })
dispatch('setTheme', { themeName: null, recompile: true })
},
setTheme ({ commit, rootState }, { themeName, themeData, recompile, saveData } = {}) { setTheme ({ commit, rootState }, { themeName, themeData, recompile, saveData } = {}) {
const { const {
theme: instanceThemeName theme: instanceThemeName
@ -221,21 +226,52 @@ const interfaceMod = {
theme: userThemeName, theme: userThemeName,
customTheme: userThemeSnapshot, customTheme: userThemeSnapshot,
customThemeSource: userThemeSource, customThemeSource: userThemeSource,
userPalette,
forceThemeRecompilation, forceThemeRecompilation,
themeDebug, themeDebug,
theme3hacks theme3hacks
} = rootState.config } = rootState.config
const userPaletteIss = (() => {
if (!userPalette) return null
const result = {
component: 'Root',
directives: {}
}
Object
.entries(userPalette)
.filter(([k]) => k !== 'name')
.forEach(([k, v]) => {
let issRootDirectiveName
switch (k) {
case 'background':
issRootDirectiveName = 'bg'
break
case 'foreground':
issRootDirectiveName = 'fg'
break
default:
issRootDirectiveName = k
}
result.directives['--' + issRootDirectiveName] = 'color | ' + v
})
return result
})()
const actualThemeName = userThemeName || instanceThemeName const actualThemeName = userThemeName || instanceThemeName
const forceRecompile = forceThemeRecompilation || recompile const forceRecompile = forceThemeRecompilation || recompile
let promise = null let promise = null
console.log('TEST', actualThemeName, themeData)
if (themeData) { if (themeData) {
promise = Promise.resolve(normalizeThemeData(themeData)) promise = Promise.resolve(normalizeThemeData(themeData))
} else if (themeName) { } else if (themeName) {
promise = getPreset(themeName).then(themeData => normalizeThemeData(themeData)) promise = getPreset(themeName).then(themeData => normalizeThemeData(themeData))
} else if (themeName === null) {
promise = Promise.resolve(null)
} else if (userThemeSource || userThemeSnapshot) { } else if (userThemeSource || userThemeSnapshot) {
promise = Promise.resolve(normalizeThemeData({ promise = Promise.resolve(normalizeThemeData({
_pleroma_theme_version: 2, _pleroma_theme_version: 2,
@ -264,13 +300,14 @@ const interfaceMod = {
promise promise
.then(realThemeData => { .then(realThemeData => {
const theme2ruleset = convertTheme2To3(realThemeData) const theme2ruleset = realThemeData ? convertTheme2To3(realThemeData) : null
if (saveData) { if (saveData) {
commit('setOption', { name: 'theme', value: themeName || actualThemeName }) commit('setOption', { name: 'theme', value: themeName || actualThemeName })
commit('setOption', { name: 'customTheme', value: realThemeData }) commit('setOption', { name: 'customTheme', value: realThemeData })
commit('setOption', { name: 'customThemeSource', value: realThemeData }) commit('setOption', { name: 'customThemeSource', value: realThemeData })
} }
const hacks = [] const hacks = []
Object.entries(theme3hacks).forEach(([key, value]) => { Object.entries(theme3hacks).forEach(([key, value]) => {
@ -336,9 +373,15 @@ const interfaceMod = {
}) })
const ruleset = [ const ruleset = [
...theme2ruleset,
...hacks ...hacks
] ]
if (!theme2ruleset && userPaletteIss) {
ruleset.unshift(userPaletteIss)
}
if (theme2ruleset) {
ruleset.unshift(...theme2ruleset)
}
applyTheme( applyTheme(
ruleset, ruleset,
@ -355,6 +398,7 @@ const interfaceMod = {
export default interfaceMod export default interfaceMod
export const normalizeThemeData = (input) => { export const normalizeThemeData = (input) => {
console.log(input)
if (Array.isArray(input)) { if (Array.isArray(input)) {
const themeData = { colors: {} } const themeData = { colors: {} }
themeData.colors.bg = input[1] themeData.colors.bg = input[1]
@ -365,7 +409,7 @@ export const normalizeThemeData = (input) => {
themeData.colors.cGreen = input[6] themeData.colors.cGreen = input[6]
themeData.colors.cBlue = input[7] themeData.colors.cBlue = input[7]
themeData.colors.cOrange = input[8] themeData.colors.cOrange = input[8]
return generatePreset(themeData).theme return generatePreset(themeData).source || generatePreset(themeData).theme
} }
let themeData, themeSource let themeData, themeSource

View file

@ -256,13 +256,13 @@ export const applyConfig = (input) => {
body.classList.remove('hidden') body.classList.remove('hidden')
} }
export const getThemes = () => { export const getThemeResources = (url) => {
const cache = 'no-store' const cache = 'no-store'
return window.fetch('/static/styles.json', { cache }) return window.fetch(url, { cache })
.then((data) => data.json()) .then((data) => data.json())
.then((themes) => { .then((resources) => {
return Object.entries(themes).map(([k, v]) => { return Object.entries(resources).map(([k, v]) => {
let promise = null let promise = null
if (typeof v === 'object') { if (typeof v === 'object') {
promise = Promise.resolve(v) promise = Promise.resolve(v)
@ -284,10 +284,26 @@ export const getThemes = () => {
return acc return acc
}, {}) }, {})
}) })
.then((promises) => {
return Promise.all(
Object.entries(promises)
.map(([k, v]) => v.then(res => [k, res]))
)
})
.then(themes => themes.reduce((acc, [k, v]) => {
if (v) {
return {
...acc,
[k]: v
}
} else {
return acc
}
}, {}))
} }
export const getPreset = (val) => { export const getPreset = (val) => {
return getThemes() return getThemeResources('/static/styles.json')
.then((themes) => themes[val] ? themes[val] : themes['pleroma-dark']) .then((themes) => themes[val] ? themes[val] : themes['pleroma-dark'])
.then((theme) => { .then((theme) => {
const isV1 = Array.isArray(theme) const isV1 = Array.isArray(theme)

View file

@ -0,0 +1,32 @@
{
"pleroma-light": [ "Pleroma Light", "#f2f4f6", "#dbe0e8", "#304055", "#f86f0f", "#d31014", "#0fa00f", "#0095ff", "#ffa500" ],
"pleroma-dark": [ "Pleroma Dark", "#121a24", "#182230", "#b9b9ba", "#d8a070", "#d31014", "#0fa00f", "#0095ff", "#ffa500" ],
"classic-dark": {
"name": "Classic Dark",
"background": "#161c20",
"foreground": "#282e32",
"text": "#b9b9b9",
"link": "#baaa9c",
"cRed": "#d31014",
"cBlue": "#0fa00f",
"cGreen": "#0095ff",
"cOrange": "#ffa500"
},
"pleroma-amoled": [ "Pleroma Dark AMOLED", "#000000", "#111111", "#b0b0b1", "#d8a070", "#aa0000", "#0fa00f", "#0095ff", "#d59500"],
"tomorrow-night": {
"name": "Tomorrow Night",
"background": "#1d1f21",
"foreground": "#373b41",
"link": "#81a2be",
"text": "#c5c8c6",
"cRed": "#cc6666",
"cBlue": "#8abeb7",
"cGreen": "#b5bd68",
"cOrange": "#de935f",
"_cYellow": "#f0c674",
"_cPurple": "#b294bb"
},
"bird": [ "Bird", "#f8fafd", "#e6ecf0", "#14171a", "#0084b8", "#e0245e", "#17bf63", "#1b95e0", "#fab81e"],
"ir-black": [ "Ir Black", "#000000", "#242422", "#b5b3aa", "#ff6c60", "#FF6C60", "#A8FF60", "#96CBFE", "#FFFFB6" ],
"monokai": [ "Monokai", "#272822", "#383830", "#f8f8f2", "#f92672", "#F92672", "#a6e22e", "#66d9ef", "#f4bf75" ]
}

View file

@ -1,12 +1,6 @@
{ {
"pleroma-dark": "/static/themes/pleroma-dark.json", "pleroma-dark": "/static/themes/pleroma-dark.json",
"pleroma-light": "/static/themes/pleroma-light.json", "pleroma-light": "/static/themes/pleroma-light.json",
"pleroma-amoled": [ "Pleroma Dark AMOLED", "#000000", "#111111", "#b0b0b1", "#d8a070", "#aa0000", "#0fa00f", "#0095ff", "#d59500"],
"classic-dark": [ "Classic Dark", "#161c20", "#282e32", "#b9b9b9", "#baaa9c", "#d31014", "#0fa00f", "#0095ff", "#ffa500" ],
"bird": [ "Bird", "#f8fafd", "#e6ecf0", "#14171a", "#0084b8", "#e0245e", "#17bf63", "#1b95e0", "#fab81e"],
"ir-black": [ "Ir Black", "#000000", "#242422", "#b5b3aa", "#ff6c60", "#FF6C60", "#A8FF60", "#96CBFE", "#FFFFB6" ],
"monokai": [ "Monokai", "#272822", "#383830", "#f8f8f2", "#f92672", "#F92672", "#a6e22e", "#66d9ef", "#f4bf75" ],
"redmond-xx": "/static/themes/redmond-xx.json", "redmond-xx": "/static/themes/redmond-xx.json",
"redmond-xx-se": "/static/themes/redmond-xx-se.json", "redmond-xx-se": "/static/themes/redmond-xx-se.json",
"redmond-xxi": "/static/themes/redmond-xxi.json", "redmond-xxi": "/static/themes/redmond-xxi.json",