Add theme selection, default themes

This commit is contained in:
JannisX11 2021-08-23 22:17:59 +02:00
parent 7c2abbfa8a
commit 72bc1d64c9
10 changed files with 163 additions and 116 deletions

View File

@ -534,15 +534,23 @@
float: left;
width: 166px;
padding: 6px;
border: 1px solid transparent;
margin-right: 6px;
border: 2px solid transparent;
background-color: var(--color-ui);
color: var(--color-text);
cursor: pointer;
}
#theme_list .theme:hover {
border-color: var(--color-border);
color: var(--color-light);
background-color: var(--color-back);
}
#theme_list .theme.selected {
border-color: var(--color-accent);
}
#theme_list .theme * {
cursor: inherit;
}
#theme_list .theme_preview {
height: 72px;
width: 100%;
@ -1044,7 +1052,7 @@
background-color: var(--color-bright_ui);
color: var(--color-accent_text);
min-height: 20px;
width: 340px;
width: 100%;
max-height: 400px;
overflow-y: auto;
overflow-x: hidden;
@ -1099,7 +1107,6 @@
overflow-y: scroll;
min-height: 80px;
border: 1px solid var(--color-border);
border-right: none;
}
#bar_item_list li {
padding: 4px;

View File

@ -27,6 +27,14 @@
const isApp = typeof require !== 'undefined';
const appVersion = '4.0.0-beta.0';
if (localStorage.getItem('theme')) {
try {
stored_theme = JSON.parse(localStorage.getItem('theme'));
document.body.style.setProperty('--color-dark', stored_theme.colors.dark);
} catch (err) {}
}
window.onerror = (message, file, line) => {
if (typeof Blockbench != 'undefined' && Blockbench.setup_successful) return;

View File

@ -2058,7 +2058,7 @@ const BARS = {
<dialog id="action_selector" v-if="open">
<input type="text" v-model="search_input" @input="e => search_input = e.target.value" autocomplete="off" autosave="off" autocorrect="off" spellcheck="off" autocapitalize="off">
<i class="material-icons" id="action_search_bar_icon">search</i>
<div>
<div id="action_selector_list">
<ul>
<li v-for="(item, i) in actions"
v-html="item.menu_node.innerHTML"

View File

@ -1,19 +1,15 @@
const CustomTheme = {
data: {
id: 'dark',
name: '',
author: '',
main_font: '',
headline_font: '',
code_font: '',
css: '',
colors: {},
},
theme_options: [
{
id: 'default',
meta: {
name: 'Default (dark)',
}
},
themes: [
...CustomThemeOptions
],
defaultColors: {
@ -36,10 +32,6 @@ const CustomTheme = {
},
setup() {
for (var key in CustomTheme.defaultColors) {
CustomTheme.data.colors[key] = CustomTheme.defaultColors[key];
}
function saveChanges() {
localStorage.setItem('theme', JSON.stringify(CustomTheme.data));
}
@ -58,8 +50,8 @@ const CustomTheme = {
sidebar: {
pages: {
select: tl('layout.select'),
options: tl('layout.options'),
color: tl('layout.color'),
fonts: tl('layout.fonts'),
css: tl('layout.css'),
},
page: 'select',
@ -85,73 +77,59 @@ const CustomTheme = {
data: {
data: CustomTheme.data,
open_category: 'select',
theme_options: CustomTheme.theme_options
themes: CustomTheme.themes
},
components: {
VuePrismEditor
},
watch: {
'data.main_font'() {
document.body.style.setProperty('--font-custom-main', CustomTheme.data.main_font);
CustomTheme.updateSettings();
saveChanges();
},
'data.headline_font'() {
document.body.style.setProperty('--font-custom-headline', CustomTheme.data.headline_font);
CustomTheme.updateSettings();
saveChanges();
},
'data.code_font'() {
document.body.style.setProperty('--font-custom-code', CustomTheme.data.code_font);
CustomTheme.updateSettings();
saveChanges();
},
'data.css'() {
$('style#theme_css').text(CustomTheme.data.css);
CustomTheme.updateSettings();
saveChanges();
},
'data.colors': {
handler() {
for (var key in CustomTheme.data.colors) {
var hex = CustomTheme.data.colors[key];
document.body.style.setProperty('--color-'+key, hex);
}
$('meta[name=theme-color]').attr('content', CustomTheme.data.colors.frame);
var c_outline = parseInt('0x'+CustomTheme.data.colors.accent.replace('#', ''))
if (c_outline !== gizmo_colors.outline.getHex()) {
gizmo_colors.outline.set(c_outline)
Canvas.outlineMaterial.color = gizmo_colors.outline
}
var c_wire = parseInt('0x'+CustomTheme.data.colors.wireframe.replace('#', ''))
if (c_wire !== gizmo_colors.wire.getHex()) {
gizmo_colors.wire.set(c_wire);
Canvas.wireframeMaterial.color = gizmo_colors.wire;
}
var c_grid = parseInt('0x'+CustomTheme.data.colors.grid.replace('#', ''))
if (c_grid !== gizmo_colors.grid.getHex()) {
gizmo_colors.grid.set(c_grid);
three_grid.children.forEach(c => {
if (c.name === 'grid' && c.material) {
c.material.color = gizmo_colors.grid;
}
})
}
CustomTheme.updateColors();
saveChanges();
},
deep: true
},
},
methods: {
selectTheme(theme) {
CustomTheme.loadTheme(theme);
},
getThemeThumbnailStyle(theme) {
let style = {};
for (let key in theme.colors) {
style[`--color-${key}`] = theme.colors[key];
}
return style;
}
},
template: `
<div id="theme_editor">
<div v-if="open_category == 'select'">
<h2 class="i_b">${tl('layout.select')}</h2>
<div id="theme_list">
<div v-for="theme in theme_options" class="theme">
<div v-for="theme in themes" :key="theme.id" class="theme" :class="{selected: theme.id == data.id}" @click="selectTheme(theme)" :style="getThemeThumbnailStyle(theme)">
<div class="theme_preview"></div>
<div class="theme_name">{{ theme.meta.name }}</div>
<div class="theme_author">{{ theme.meta.author || 'Default' }}</div>
<div class="theme_name">{{ theme.name }}</div>
<div class="theme_author">{{ theme.author || 'Default' }}</div>
</div>
</div>
</div>
@ -168,8 +146,21 @@ const CustomTheme = {
</div>
</div>
<div v-if="open_category == 'fonts'">
<h2 class="i_b">${tl('layout.fonts')}</h2>
<div v-if="open_category == 'options'">
<h2 class="i_b">${tl('layout.options')}</h2>
<div class="dialog_bar">
<label class="name_space_left" for="layout_name">${tl('layout.name')}</label>
<input type="text" class="half dark_bordered" id="layout_name" v-model="data.name">
</div>
<div class="dialog_bar">
<label class="name_space_left" for="layout_name">${tl('layout.author')}</label>
<input type="text" class="half dark_bordered" id="layout_name" v-model="data.author">
</div>
<hr />
<div class="dialog_bar">
<label class="name_space_left" for="layout_font_main">${tl('layout.font.main')}</label>
<input style="font-family: var(--font-main)" type="text" class="half dark_bordered" id="layout_font_main" v-model="data.main_font">
@ -199,10 +190,6 @@ const CustomTheme = {
Settings.save();
}
})
Vue.nextTick(function() {
CustomTheme.fetchFromStorage();
})
},
setupDialog() {
var wrapper = $('#color_wrapper');
@ -241,52 +228,57 @@ const CustomTheme = {
}
CustomTheme.dialog_is_setup = true;
},
fetchFromStorage() {
var legacy_colors = 0;
var stored_theme = 0;
try {
if (localStorage.getItem('theme')) {
stored_theme = JSON.parse(localStorage.getItem('theme'))
}
if (localStorage.getItem('app_colors')) {
legacy_colors = JSON.parse(localStorage.getItem('app_colors'))
}
} catch (err) {}
updateColors() {
for (var key in CustomTheme.data.colors) {
var hex = CustomTheme.data.colors[key];
document.body.style.setProperty('--color-'+key, hex);
}
$('meta[name=theme-color]').attr('content', CustomTheme.data.colors.frame);
if (stored_theme) {
for (var key in CustomTheme.data) {
if (stored_theme[key] && typeof CustomTheme.data[key] !== 'object') {
CustomTheme.data[key] = stored_theme[key];
}
if (typeof gizmo_colors != 'undefined') {
var c_outline = parseInt('0x'+CustomTheme.data.colors.accent.replace('#', ''))
if (c_outline !== gizmo_colors.outline.getHex()) {
gizmo_colors.outline.set(c_outline)
Canvas.outlineMaterial.color = gizmo_colors.outline
}
} else if (legacy_colors) {
if (legacy_colors.main) {
CustomTheme.data.main_font = legacy_colors.main.font;
var c_wire = parseInt('0x'+CustomTheme.data.colors.wireframe.replace('#', ''))
if (c_wire !== gizmo_colors.wire.getHex()) {
gizmo_colors.wire.set(c_wire);
Canvas.wireframeMaterial.color = gizmo_colors.wire;
}
if (legacy_colors.headline) {
CustomTheme.data.headline_font = legacy_colors.headline.font;
}
if (legacy_colors.css) {
CustomTheme.data.css = legacy_colors.css;
var c_grid = parseInt('0x'+CustomTheme.data.colors.grid.replace('#', ''))
if (c_grid !== gizmo_colors.grid.getHex()) {
gizmo_colors.grid.set(c_grid);
three_grid.children.forEach(c => {
if (c.name === 'grid' && c.material) {
c.material.color = gizmo_colors.grid;
}
})
}
}
for (var key in CustomTheme.defaultColors) {
if (stored_theme && stored_theme.colors[key]) {
CustomTheme.data.colors[key] = stored_theme.colors[key];
} else if (legacy_colors && legacy_colors[key] && legacy_colors[key].hex) {
CustomTheme.data.colors[key] = legacy_colors[key].hex;
}
},
updateSettings() {
document.body.style.setProperty('--font-custom-main', CustomTheme.data.main_font);
document.body.style.setProperty('--font-custom-headline', CustomTheme.data.headline_font);
document.body.style.setProperty('--font-custom-code', CustomTheme.data.code_font);
$('style#theme_css').text(CustomTheme.data.css);
},
loadTheme(theme) {
var app = CustomTheme.data;
Merge.string(app, theme, 'id')
Merge.string(app, theme, 'name')
Merge.string(app, theme, 'author')
Merge.string(app, theme, 'main_font')
Merge.string(app, theme, 'headline_font')
Merge.string(app, theme, 'code_font')
for (var key in app.colors) {
Merge.string(app.colors, theme.colors, key);
}
Blockbench.onUpdateTo('3.8', () => {
if (CustomTheme.data.colors.checkerboard == '#2f3339') {
CustomTheme.data.colors.checkerboard = CustomTheme.defaultColors.checkerboard;
}
})
Blockbench.onUpdateTo('3.9', () => {
if (CustomTheme.data.colors.selected == '#3c4456') {
CustomTheme.data.colors.selected = CustomTheme.defaultColors.selected;
}
})
Merge.string(app, theme, 'css');
this.updateColors();
this.updateSettings();
},
import(file) {
var data = JSON.parse(file.content)
@ -307,17 +299,28 @@ const CustomTheme = {
} else {
if (data && data.colors) {
Merge.string(app, data, 'main_font')
Merge.string(app, data, 'headline_font')
Merge.string(app, data, 'code_font')
for (var key in app.colors) {
Merge.string(app.colors, data.colors, key);
}
Merge.string(app, data, 'css')
CustomTheme.loadTheme(data);
}
}
}
}
};
(function() {
var stored_theme = 0;
try {
if (localStorage.getItem('theme')) {
stored_theme = JSON.parse(localStorage.getItem('theme'))
}
} catch (err) {}
for (var key in CustomTheme.defaultColors) {
CustomTheme.data.colors[key] = CustomTheme.defaultColors[key];
}
if (stored_theme) {
CustomTheme.loadTheme(stored_theme);
}
})()
BARS.defineActions(function() {

File diff suppressed because one or more lines are too long

View File

@ -447,9 +447,9 @@
"keybindings.recording": "Recording Keybinding",
"keybindings.press": "Press a key or key combination or click anywhere on the screen to record your keybinding.",
"layout.discover": "Discover",
"layout.select": "Select",
"layout.options": "Options",
"layout.color": "Color Scheme",
"layout.fonts": "Fonts",
"layout.css": "Custom CSS",
"layout.documentation": "Documentation",
"layout.color.back": "Back",
@ -484,6 +484,8 @@
"layout.color.subtle_text.desc": "Secondary text color with less contrast",
"layout.color.checkerboard": "Checkerboard",
"layout.color.checkerboard.desc": "Background of canvas and UV editor",
"layout.name": "Name",
"layout.author": "Author",
"layout.font.main": "Main Font",
"layout.font.headline": "Headline Font",
"layout.font.code": "Code Font",

View File

@ -12,8 +12,10 @@ window.KeymapPresets = {
import DarkTheme from './../themes/dark.bbtheme'
import LightTheme from './../themes/light.bbtheme'
import ContrastTheme from './../themes/contrast.bbtheme'
window.CustomThemeOptions = [
DarkTheme,
LightTheme
LightTheme,
ContrastTheme
]

27
themes/contrast.bbtheme Normal file
View File

@ -0,0 +1,27 @@
{
"id": "contrast",
"name": "Contrast",
"author": "",
"main_font": "",
"headline_font": "",
"code_font": "",
"css": ".contextMenu,\ndialog,\n.dialog_close_button,\n#start_screen content,\n#quick_message_box,\naction_selector > #action_selector_list\n{\n border: 1px solid var(--color-border);\n}\n#start_screen section {\n border-bottom: 1px solid var(--color-border);\n}\n.panel {\n margin-top: -1px;\n border-top: 01px solid var(--color-border);\n}\n#right_bar {\n border-left: 1px solid var(--color-border);\n}\n#left_bar {\n border-right: 1px solid var(--color-border);\n}\n.preview .preview_menu {\n right: 0;\n}\n.dialog_sidebar {\n border-right: 1px solid var(--color-border);\n}\n.dialog_handle {\n background: transparent;\n border-bottom: 1px solid var(--color-border);\n}\n.dialog_close_button {\n right: -1px;\n top: -1px;\n height: 31px;\n}\n#work_screen {\n grid-template-rows: 31px minmax(200px, 5000px) 26px;\n}\n#main_toolbar, #tab_bar {\n border-bottom: 01px solid var(--color-border);\n}\n#status_bar {\n border-top: 01px solid var(--color-border);\n}\n\n#mode_selector li {\n padding: 2px 10px;\n}\n#mode_selector li.selected {\n background-color: var(--color-accent);\n color: var(--color-accent_text);\n}\n\n#tab_bar .project_tab.selected,\n.dialog_sidebar_pages li.selected,\n.tool.enabled\n{\n background-color: var(--color-accent) !important;\n color: var(--color-accent_text);\n}\n.contextMenu li {\n height: 34px;\n padding-top: 6px;\n padding-bottom: 6px;\n}\n.contextMenu li.menu_separator {\n height: 2px;\n padding: 0;\n background-color: var(--color-border);\n}\n.dialog_sidebar_pages li.selected {\n background-color: var(--color-accent) !important;\n color: var(--color-accent_text);\n}",
"colors": {
"ui": "#17191d",
"back": "#17191d",
"dark": "#17191d",
"border": "#9ea4b5",
"selected": "#31525f",
"button": "#3a3f4b",
"bright_ui": "#17191d",
"accent": "#1b71d9",
"frame": "#181a1f",
"text": "#d0d0db",
"light": "#f4f3ff",
"accent_text": "#dadae6",
"subtle_text": "#adb2bc",
"grid": "#727683",
"wireframe": "#5f96bc",
"checkerboard": "#1c2026"
}
}

View File

@ -1,8 +1,7 @@
{
"id": "dark",
"meta": {
"name": "Default (Dark)"
},
"name": "Default (Dark)",
"author": "",
"main_font": "",
"headline_font": "",
"code_font": "",

View File

@ -1,8 +1,7 @@
{
"id": "light",
"meta": {
"name": "Default (Light)"
},
"name": "Default (Light)",
"author": "",
"main_font": "",
"headline_font": "",
"code_font": "",