extension: Add log level option

This commit is contained in:
relrelb 2021-09-25 13:02:01 +03:00 committed by relrelb
parent 1d324e81b0
commit d5b223c1b3
9 changed files with 126 additions and 48 deletions

View File

@ -47,13 +47,15 @@ body {
margin-top: 24px;
}
.option input {
.option input,
.option select {
position: absolute;
right: 0;
}
.option.checkbox input {
width: 40px;
height: 20px;
top: 0;
bottom: 0;
right: 0;
margin: auto;
cursor: pointer;
z-index: 1;
@ -65,8 +67,8 @@ body {
padding-right: 40px;
}
.option label::before,
.option label::after {
.option.checkbox label::before,
.option.checkbox label::after {
content: "";
position: absolute;
border-radius: 10px;
@ -76,25 +78,25 @@ body {
transition: background 0.2s, right 0.2s;
}
.option label::before {
.option.checkbox label::before {
height: 20px;
width: 40px;
right: 0;
background: gray;
}
.option label::after {
.option.checkbox label::after {
height: 18px;
width: 18px;
right: 21px;
background: silver;
}
.option input:checked + label::before {
.option.checkbox input:checked + label::before {
background: var(--ruffle-dark-orange);
}
.option input:checked + label::after {
.option.checkbox input:checked + label::after {
background: var(--ruffle-orange);
right: 1px;
}

View File

@ -19,18 +19,26 @@
</a>
</div>
<div class="container">
<div class="option">
<div class="option checkbox">
<input type="checkbox" id="ruffle_enable" />
<label for="ruffle_enable">Play Flash content in Ruffle</label>
</div>
<div class="option">
<div class="option checkbox">
<input type="checkbox" id="ignore_optout" />
<label for="ignore_optout">Ignore website compatibility warnings</label>
</div>
<div class="option">
<div class="option checkbox">
<input type="checkbox" id="warn_on_unsupported_content" />
<label for="warn_on_unsupported_content">Warn on unsupported content</label>
</div>
<div class="option select">
<select id="log_level">
<option value="info">Info</option>
<option value="warn">Warning</option>
<option value="error">Error</option>
</select>
<label for="log_level">Log level</label>
</div>
</div>
<script src="dist/options.js"></script>
</body>

View File

@ -23,11 +23,11 @@
<span id="status-text">Ruffle is running.</span>
</div>
<div class="container">
<div class="option">
<div class="option checkbox">
<input type="checkbox" id="ruffle_enable" />
<label for="ruffle_enable">Play Flash content in Ruffle</label>
</div>
<div class="option">
<div class="option checkbox">
<input type="checkbox" id="ignore_optout" />
<label for="ignore_optout">Ignore website compatibility warnings</label>
</div>

View File

@ -1,57 +1,122 @@
import * as utils from "./utils";
import type { LogLevel } from "ruffle-core";
export interface Options {
ruffleEnable: boolean;
ignoreOptout: boolean;
warnOnUnsupportedContent: boolean;
logLevel: LogLevel;
}
function getBooleanElements() {
interface OptionElement<T> {
readonly input: Element;
readonly label: HTMLLabelElement;
value: T;
}
class CheckboxOption implements OptionElement<boolean> {
private checkbox: HTMLInputElement;
readonly label: HTMLLabelElement;
constructor(checkbox: HTMLInputElement, label: HTMLLabelElement) {
this.checkbox = checkbox;
this.label = label;
}
get input() {
return this.checkbox;
}
get value() {
return this.checkbox.checked;
}
set value(value: boolean) {
this.checkbox.checked = value;
}
}
class SelectOption implements OptionElement<string> {
private select: HTMLSelectElement;
readonly label: HTMLLabelElement;
constructor(select: HTMLSelectElement, label: HTMLLabelElement) {
this.select = select;
this.label = label;
}
get input() {
return this.select;
}
get value() {
const index = this.select.selectedIndex;
const option = this.select.options[index];
return option.value;
}
set value(value: string) {
const options = Array.from(this.select.options);
const index = options.findIndex((option) => option.value === value);
this.select.selectedIndex = index;
}
}
function getElement(option: Element): OptionElement<unknown> {
const [label] = option.getElementsByTagName("label");
const [checkbox] = option.getElementsByTagName("input");
if (checkbox && checkbox.type === "checkbox") {
return new CheckboxOption(checkbox, label);
}
const [select] = option.getElementsByTagName("select");
if (select) {
return new SelectOption(select, label);
}
throw new Error("Unknown option element");
}
function findOptionElements() {
const camelize = (s: string) =>
s.replace(/[^a-z\d](.)/gi, (_, char) => char.toUpperCase());
const elements = new Map<
keyof Options,
{ option: Element; checkbox: HTMLInputElement; label: HTMLLabelElement }
>();
const elements = new Map<keyof Options, OptionElement<unknown>>();
for (const option of document.getElementsByClassName("option")) {
const [checkbox] = option.getElementsByTagName("input");
if (checkbox.type !== "checkbox") {
continue;
}
const [label] = option.getElementsByTagName("label");
const key = camelize(checkbox.id) as keyof Options;
elements.set(key, { option, checkbox, label });
const element = getElement(option);
const key = camelize(element.input.id) as keyof Options;
elements.set(key, element);
}
return elements;
}
export async function bindBooleanOptions(
export async function bindOptions(
onChange?: (options: Options) => void
): Promise<void> {
const elements = getBooleanElements();
const elements = findOptionElements();
const options = await utils.getOptions(Array.from(elements.keys()));
for (const [key, { checkbox, label }] of elements.entries()) {
for (const [key, element] of elements.entries()) {
// Bind initial value.
checkbox.checked = options[key];
element.value = options[key];
// Prevent transition on load.
// Method from https://stackoverflow.com/questions/11131875.
label.classList.add("notransition");
label.offsetHeight; // Trigger a reflow, flushing the CSS changes.
label.classList.remove("notransition");
element.label.classList.add("notransition");
element.label.offsetHeight; // Trigger a reflow, flushing the CSS changes.
element.label.classList.remove("notransition");
// Localize label.
const message = utils.i18n.getMessage(`settings_${checkbox.id}`);
const message = utils.i18n.getMessage(`settings_${element.input.id}`);
if (message) {
label.textContent = message;
element.label.textContent = message;
}
// Listen for user input.
checkbox.addEventListener("change", () => {
const value = checkbox.checked;
options[key] = value;
element.input.addEventListener("change", () => {
const value = element.value;
options[key] = value as never;
utils.storage.sync.set({ [key]: value });
});
}
@ -67,8 +132,8 @@ export async function bindBooleanOptions(
if (!element) {
continue;
}
element.checkbox.checked = option.newValue;
options[key as keyof Options] = option.newValue;
element.value = option.newValue;
options[key as keyof Options] = option.newValue as never;
}
if (onChange) {

View File

@ -110,6 +110,7 @@ function isXMLDocument(): boolean {
"ruffleEnable",
"ignoreOptout",
"warnOnUnsupportedContent",
"logLevel",
]);
const pageOptout = checkPageOptout();
const shouldLoad =
@ -175,6 +176,7 @@ function isXMLDocument(): boolean {
type: "load",
config: {
warnOnUnsupportedContent: options.warnOnUnsupportedContent,
logLevel: options.logLevel,
},
});
})();

View File

@ -1,7 +1,7 @@
import * as utils from "./utils";
import { bindBooleanOptions } from "./common";
import { bindOptions } from "./common";
window.addEventListener("DOMContentLoaded", () => {
document.title = utils.i18n.getMessage("settings_page");
bindBooleanOptions();
bindOptions();
});

View File

@ -1,5 +1,5 @@
import * as utils from "./utils";
import { PublicAPI, SourceAPI, Letterbox, LogLevel } from "ruffle-core";
import { PublicAPI, SourceAPI, Letterbox } from "ruffle-core";
const api = PublicAPI.negotiate(
window.RufflePlayer!,
@ -30,8 +30,7 @@ window.addEventListener("DOMContentLoaded", async () => {
const config = {
letterbox: Letterbox.On,
logLevel: LogLevel.Warn,
...(await utils.getOptions(["warnOnUnsupportedContent"])),
...(await utils.getOptions(["warnOnUnsupportedContent", "logLevel"])),
};
player.load({ url: swfUrl, base: swfUrl, ...config });
});

View File

@ -1,5 +1,5 @@
import * as utils from "./utils";
import { Options, bindBooleanOptions } from "./common";
import { Options, bindOptions } from "./common";
let activeTab: chrome.tabs.Tab | browser.tabs.Tab;
let savedOptions: Options;
@ -114,7 +114,7 @@ function displayTabStatus() {
}
window.addEventListener("DOMContentLoaded", () => {
bindBooleanOptions((options) => {
bindOptions((options) => {
savedOptions = options;
optionsChanged();
});

View File

@ -1,9 +1,11 @@
import { Options } from "./common";
import { LogLevel } from "ruffle-core";
const DEFAULT_OPTIONS: Options = {
ruffleEnable: true,
ignoreOptout: false,
warnOnUnsupportedContent: true,
logLevel: LogLevel.Error,
};
export let i18n: {