[Themes] Rework the theme config page (#752)

This commit is contained in:
Cinder 2024-09-08 16:28:06 -07:00 committed by GitHub
parent aa5a7fb6fb
commit d69c34ee9a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 164 additions and 77 deletions

View File

@ -50,6 +50,7 @@ export { default as Shortcuts } from '../src/javascripts/shortcuts.js';
export { default as Utility } from '../src/javascripts/utility.js';
export { default as TagRelationships } from '../src/javascripts/tag_relationships.js';
export { default as Takedown } from '../src/javascripts/takedowns.js';
export { default as Theme } from "../src/javascripts/themes.js";
export { default as Thumbnails } from '../src/javascripts/thumbnails.js';
export { default as Uploader } from '../src/javascripts/uploader.js';
export { default as VoteManager } from '../src/javascripts/vote_manager.js';

View File

@ -256,7 +256,7 @@ class E6Swipe extends ZingTouch.Swipe {
}
Post.initialize_gestures = function () {
if (!LStorage.Posts.Gestures) return;
if (!LStorage.Theme.Gestures) return;
if (!(("ontouchstart" in window) || (navigator.maxTouchPoints > 0)))
return;
// Need activeElement to make sure that this doesn't go off during input.

View File

@ -0,0 +1,42 @@
import Page from "./utility/page";
import LStorage from "./utility/storage";
const Theme = {};
Theme.Values = ["Main", "Extra", "Palette", "Navbar", "Gestures"];
for (const one of Theme.Values) {
Object.defineProperty(Theme, one, {
get () { return LStorage.Theme[one]; },
set (value) {
// No value checking, we die like men
LStorage.Theme[one] = value;
$("body").attr("data-th-" + one.toLowerCase(), value);
},
});
}
Theme.initialize_selector = function () {
if (!LStorage.isAvailable()) {
// This is here purely because it was in the old code.
// All browsers made after 2008 should support this.
$("#no_save_warning").show();
return false;
}
for (const one of Theme.Values) {
$("#theme_" + one.toLowerCase())
.val(LStorage.Theme[one] + "")
.on("change", (event) => {
const data = event.target.value;
Theme[one] = data;
});
}
};
$(() => {
if (Page.matches("static", "theme"))
Theme.initialize_selector();
});
export default Theme;

View File

@ -0,0 +1,41 @@
export default class Page {
static _controller;
static _action;
static _init () {
const data = document.body.dataset;
this._controller = data.controller;
this._action = data.action;
}
/** @returns {string} Controller for the current page */
static get Controller () {
if (!this._controller) this._init();
return this._controller;
}
/** @returns {string} Action for the current page */
static get Action () {
if (!this._action) this._init();
return this._action;
}
/**
* Checks if the current page matches the provided parameters.
* If both params are provided, checks against both of them.
* If only the controller is provided, action is ignored.
* @param {string} controller Controller to match against
* @param {string} action Action to match against
* @returns {boolean} True if the params match, false otherwise
*/
static matches (controller, action = "") {
if (!this._controller) this._init();
if (action)
return this._controller == controller && this._action == action;
return this._controller == controller;
}
}

View File

@ -23,6 +23,14 @@ LStorage.putObject = function (name, value) {
this.put(name, JSON.stringify(value));
};
LStorage.isAvailable = function () {
try {
localStorage.setItem("test", "a");
localStorage.removeItem("test");
} catch { return false; }
return true;
};
// Content that does not belong anywhere else
LStorage.Site = {
/** @returns {number} Currently displayed Mascot ID, or 0 if none is selected */
@ -34,14 +42,33 @@ LStorage.Site = {
StorageUtils.bootstrapMany(LStorage.Site);
// Site themes and other visual options
// Note that these are HARD-CODED in theme_include.html.erb
// Any changes here must be reflected there as well
LStorage.Theme = {
/** @returns {string} Main theme */
Main: ["theme", "hexagon"],
/** @returns {string} Extra theme / seasonal decotrations */
Extra: ["theme-extra", "hexagon"],
/** @returns {string} Colorblind-friendly palette (default / deut / trit) */
Palette: ["theme-palette", "default"],
/** @returns {string} Position of the navbar on the post page (top / bottom / both / none) */
Navbar: ["theme-nav", "top"],
/** @returns {boolean} True if the mobile gestures should be enabled */
Gestures: ["emg", false],
};
StorageUtils.bootstrapMany(LStorage.Theme);
// Values relevant to the posts pages
LStorage.Posts = {
/** @returns {string} Viewing mode on the search page */
Mode: ["mode", "view"],
/** @returns {boolean} True if the mobile gestures should be enabled */
Gestures: ["emg", false],
/** @returns {boolean} True if parent/child posts preview should be visible */
ShowPostChildren: ["show-relationship-previews", false],

View File

@ -73,6 +73,7 @@
@import "specific/tags.scss";
@import "specific/takedowns.scss";
@import "specific/terms_of_service.scss";
@import "specific/themes.scss";
@import "specific/tickets.scss";
@import "specific/uploads.scss";
@import "specific/uploads_file.scss";

View File

@ -0,0 +1,19 @@
.theme-form {
display: grid;
grid-template-columns: 1fr;
gap: 0.5em 1em;
@include window-larger-than(30rem) {
grid-template-columns: min-content auto;
max-width: 30rem;
gap: 1em;
h3, br, p.theme-info { grid-column: 1 / -1; }
label { text-align: right; }
.hint { grid-column: 2; }
}
h3, br, p.theme-info { text-align: center; }
h3 { margin-top: 0.5em; }
.hint { max-width: unset; }
}

View File

@ -10,7 +10,6 @@
b.setAttribute('data-th-extra', extra);
b.setAttribute('data-th-palette', palette);
b.setAttribute('data-th-nav', nav);
} catch(e) {
}
} catch(e) {}
})();
<% end -%>

View File

@ -1,24 +1,30 @@
<p>Theme settings are saved using cookies and javascript. This means that they will not persist across private browsing
sessions, or work inside incognito mode on mobile devices.</p>
<h3 class="text-error" id="no_save_warning" style="display:none;">Your device does not allow the site to save theme
settings.</h3>
<h3 class="text-error" id="no_save_warning" style="display:none;">
Your device does not allow the site to save theme settings.
</h3>
<noscript>
<h3 class="text-error" id="no_save_warning">Your device does not allow the site to save theme settings.</h3>
</noscript>
<div class="simple_form">
<div class="input">
<label for="theme_name">Theme</label>
<select id="theme_name">
<div class="simple_form theme-form">
<h3>Theme Preferences</h3>
<p class="theme-info">
Theme settings are saved locally in your browser.
This means that they will not persist across multiple devices, or in incognito mode.
</p>
<label for="theme_main">Theme</label>
<select id="theme_main">
<option value="hexagon">Hexagon</option>
<option value="bloodlust">Bloodlust</option>
<option value="serpent">Serpent</option>
<option value="pony">Pony</option>
<option value="serpent">Serpent</option>
<option value="hotdog">Hotdog</option>
</select>
</div>
<div class="input">
<label for="theme_extra">Embellishments</label>
<select id="theme_extra">
<option value="none">(None)</option>
@ -30,82 +36,33 @@
<option value="stars">Stars</option>
<option value="winter">Eternal Winter</option>
</select>
</div>
<div class="input">
<h3>Accessibility</h3>
<label for="theme_palette">Palette</label>
<select id="theme_palette">
<option value="default">Default</option>
<option value="deut">Protanopia & Deuteranopia</option>
<option value="trit">Tritanopia</option>
</select>
</div>
<div class="input">
<label for="theme_navbar">Navigation bar location</label>
<h3>Navigation</h3>
<label for="theme_navbar">Navbar location</label>
<select id="theme_navbar">
<option value="top">Top (default)</option>
<option value="bottom">Bottom</option>
<option value="both">Both</option>
<option value="none">Off (not recommended)</option>
</select>
</div>
<hr>
<div class="input">
<label for="gestures_enable">Enable Mobile Gestures</label>
<select id="gestures_enable">
<option value="false">No</option>
<option value="true">Yes</option>
<label for="theme_gestures">Mobile Gestures</label>
<select id="theme_gestures">
<option value="false">Disabled</option>
<option value="true">Enabled</option>
</select>
<div class="hint">Swipe left for next page/image. Swipe right for previous page/image.</div>
</div>
</div>
<%= javascript_tag nonce: true do -%>
$(function() {
var $body = $(document.body);
try {
var ls = window.localStorage;
ls.setItem('test', 'a');
ls.removeItem('test');
var theme = ls.getItem('theme') || 'hexagon';
var extra = ls.getItem('theme-extra') || 'hexagon';
var palette = ls.getItem('theme-palette') || 'default';
var nav = ls.getItem('theme-nav') || 'top';
var emg = ls.getItem('emg') || 'false';
$('#theme_name').val(theme);
$('#theme_extra').val(extra);
$('#theme_palette').val(palette);
$('#theme_navbar').val(nav);
$('#gestures_enable').val(emg);
} catch(e) {
$("#no_save_warning").show();
}
$("#theme_name").on('change', function(e) {
var theme = e.target.value;
$body.attr('data-th-main', theme);
window.localStorage.setItem('theme', theme);
});
$("#theme_extra").on('change', function(e) {
var extra = e.target.value;
$body.attr('data-th-extra', extra);
window.localStorage.setItem('theme-extra', extra);
});
$("#theme_palette").on('change', function(e) {
var palette = e.target.value;
$body.attr('data-th-palette', palette);
window.localStorage.setItem('theme-palette', palette);
});
$("#theme_navbar").on('change', function(e) {
var pos = e.target.value;
$body.attr('data-th-nav', pos);
window.localStorage.setItem('theme-nav', pos);
});
$("#gestures_enable").on('change', function(e) {
var emg = e.target.value;
window.localStorage.setItem('emg', emg);
});
});
<% end -%>
<% content_for(:page_title) do %>
Themes
<% end %>