web: Add extension option for setting 'playerVersion'.

Basic input validation UI and logic is also added and improved.
This commit is contained in:
iwannabethedev 2023-04-27 21:06:53 +02:00 committed by relrelb
parent 5eb14572ac
commit 1f956ffe55
5 changed files with 45 additions and 17 deletions

View File

@ -166,6 +166,10 @@ export interface ObsoleteDuration {
nanos: number;
}
/**
* Any new duration-based setting should use 'number' or 'SecsDuration' for its type,
* instead of this type.
*/
export type Duration = SecsDuration | ObsoleteDuration;
/**

View File

@ -23,6 +23,9 @@
"settings_max_execution_duration": {
"message": "How long can ActionScript execute for before being forcefully stopped (in seconds)"
},
"settings_player_version": {
"message": "Flash player version number to emulate (range 1-32)"
},
"status_init": {
"message": "Reading current tab…"
},

View File

@ -63,6 +63,13 @@
/>
<label for="max_execution_duration">How long can ActionScript execute for before being forcefully stopped (in seconds)</label>
</div>
<div class="option number-input">
<input type="number" id="player_version"
min="1"
max="32"
/>
<label for="player_version">Flash player version number to emulate (range 1-32)</label>
</div>
</div>
<script src="dist/options.js"></script>
</body>

View File

@ -1,5 +1,5 @@
import * as utils from "./utils";
import type { BaseLoadOptions, Duration } from "ruffle-core";
import type { BaseLoadOptions } from "ruffle-core";
export interface Options extends BaseLoadOptions {
ruffleEnable: boolean;
@ -32,27 +32,43 @@ class CheckboxOption implements OptionElement<boolean> {
}
}
/**
* Number input option for 'maxExecutionDuration'.
*/
class MaxExecutionDurationOption implements OptionElement<Duration> {
class NumberOption implements OptionElement<number | null> {
constructor(
private readonly numberInput: HTMLInputElement,
readonly label: HTMLLabelElement
) {}
) {
this.numberInput.addEventListener("input", () => {
this.numberInput.reportValidity();
});
}
get input() {
return this.numberInput;
}
get value() {
return Math.max(1, Math.round(this.numberInput.valueAsNumber));
get value(): number | null {
const ni = this.numberInput;
const num = ni.valueAsNumber;
if (Number.isNaN(num)) {
return null;
}
if (ni.min) {
const min = Number(ni.min);
if (min > num) {
return min;
}
}
if (ni.max) {
const max = Number(ni.max);
if (num > max) {
return max;
}
}
return num;
}
set value(value: Duration) {
// Ignoring the 'nanos' part from the old format type ObsoleteDuration.
const newValue = typeof value === "number" ? value : value.secs;
this.numberInput.value = newValue.toString();
set value(value: number | null) {
this.numberInput.value = value?.toString() ?? "";
}
}
@ -89,9 +105,7 @@ function getElement(option: Element): OptionElement<unknown> {
}
if (input.type === "number") {
if (input.id === "max_execution_duration") {
return new MaxExecutionDurationOption(input, label);
}
return new NumberOption(input, label);
}
}

View File

@ -133,7 +133,7 @@ where
tracing::Level::from_str(&value).map_err(Error::custom)
}
fn deserialize_max_execution_duration<'de, D>(deserializer: D) -> Result<Duration, D::Error>
fn deserialize_duration<'de, D>(deserializer: D) -> Result<Duration, D::Error>
where
D: serde::Deserializer<'de>,
{
@ -242,7 +242,7 @@ struct Config {
#[serde(deserialize_with = "deserialize_log_level")]
log_level: tracing::Level,
#[serde(deserialize_with = "deserialize_max_execution_duration")]
#[serde(deserialize_with = "deserialize_duration")]
max_execution_duration: Duration,
player_version: Option<u8>,