Skip to content

Commit

Permalink
refactor app and slightly improve interface
Browse files Browse the repository at this point in the history
  • Loading branch information
tifv committed Jul 15, 2024
1 parent 0326468 commit 642f3b9
Show file tree
Hide file tree
Showing 2 changed files with 87 additions and 75 deletions.
19 changes: 13 additions & 6 deletions webconv/www/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@
.note {
font-size: smaller;
}
.error {
color: red;
}
.spoiler.spoiler__hidden .spoiler--inner {
display: none;
}
Expand Down Expand Up @@ -136,15 +139,19 @@ <h2 class="pane_title"></h1>
</fieldset>
</div>
</div>
<div id="pane__encoded" class="pane"
<div id="encoded--pane" class="pane"
hidden data-show_state="encoded" >
<div class="errors"></div>
<textarea class="contents" placeholder="Blueprint string…"></textarea>
<div class="error"></div>
<label>Blueprint string:<br/>
<textarea id="encoded-contents" class="contents"></textarea>
</label>
</div>
<div id="pane__decoded" class="pane"
<div id="decoded--pane" class="pane"
hidden data-show_state="decoded" >
<div class="errors"></div>
<textarea class="contents" placeholder="Decoded blueprint…"></textarea>
<div class="error"></div>
<label>Decoded blueprint:<br/>
<textarea id="decoded-contents" class="contents"></textarea>
</label>
</div>
</div>
</body>
Expand Down
143 changes: 74 additions & 69 deletions webconv/www/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,11 @@ import * as desynced_lib from "./lib/desynced_exchange_web.js";
*/

class StateMaintainer {
/**
* @type {{[x: string]: StateConfig}}
*/

/** @type {{[x: string]: StateConfig}} */
states;

/**
* @type {string | null}
*/
/** @type {string | null} */
state;

/**
Expand All @@ -45,6 +42,7 @@ class StateMaintainer {
this._checkState(startState);
this.state = startState;
}

/**
* @param {string} state
*/
Expand All @@ -56,6 +54,7 @@ class StateMaintainer {
throw new Error("Undefined state " + state);
}
}

/**
* @param {Action} action
* @param {string} oldState
Expand Down Expand Up @@ -83,8 +82,48 @@ class StateMaintainer {
}
return result;
}

}

class Side {

/** @type {string} */
name;

/** @type {HTMLElement} */
pane;

/** @type {HTMLTextAreaElement} */
contents;

/** @type {HTMLElement} */
error;

/**
* @param {string} name
*/
constructor(name) {
let pane = document.getElementById(name + "--pane");
if (pane === null) {
throw new Error("unreachable");
}
let contents = pane.querySelector(".contents");
if (contents === null || !(contents instanceof HTMLTextAreaElement)) {
throw new Error("unreachable");
}
let error = pane.querySelector('.error');
if (error == null || !(error instanceof HTMLElement)) {
throw new Error("unreachable");
}
this.name = name;
this.pane = pane;
this.contents = contents;
this.error = error;
}

}


/**
* @param {string} name
* @returns {string}
Expand Down Expand Up @@ -136,42 +175,36 @@ function getInterRepr() {

async function main() {
await desynced_lib.default();
let encoded_state = new Side("encoded");
let decoded_state = new Side("decoded");
/**
* @param {string} state
* @param {Side} side
* @returns {StateConfig}
*/
function setupState(state) {
let section = document.getElementById("pane__" + state);
if (section === null) {
throw new Error("unreachable");
}
function setupState(side) {
let {name, contents, error} = side;
return {
enter({value}) {
section.querySelectorAll('.errors')
.forEach((el) => el.innerHTML = "");
error.innerHTML = "";
if (value !== undefined) {
section.querySelectorAll('textarea')
.forEach((el) => el.value = value);
contents.value = value;
}
document
.querySelectorAll("[data-show_state=" + state + "]")
.querySelectorAll("[data-show_state=" + name + "]")
.forEach((el) => el.removeAttribute('hidden'));
section.querySelectorAll('textarea')
.forEach((el) => {
el.setSelectionRange(0, 0);
el.focus();
});
contents.setSelectionRange(0, 0);
contents.focus();
},
exit() {
document
.querySelectorAll("[data-show_state=" + state + "]")
.querySelectorAll("[data-show_state=" + name + "]")
.forEach((el) => el.setAttribute('hidden', ""));
},
}
}
let state = new StateMaintainer({
"encoded": setupState("encoded"),
"decoded": setupState("decoded"),
"encoded": setupState(encoded_state),
"decoded": setupState(decoded_state),
}, "encoded");
state.states.decoded.exit();
state.states.encoded.enter({value: ""});
Expand All @@ -180,57 +213,35 @@ async function main() {
document.querySelectorAll('.stage__main')
.forEach((el) => el.removeAttribute('hidden'));
function decode() {
let input_pane = document.getElementById("pane__encoded");
if (input_pane == null) {
throw new Error("unreachable");
}
let input = input_pane.querySelector('textarea');
if (input == null) {
throw new Error("unreachable");
}
let {contents, error: errors} = encoded_state;
state.switchState(() => {
try {
return {value: desynced_lib.decode(
input.value.trim(),
contents.value.trim(),
{
decodeFormat: getDecodeFormat(),
decodeStyle: getDecodeStyle(),
interRepr: getInterRepr(),
},
)};
} catch (error) {
let errors = input_pane.querySelector('.errors');
if (errors == null) {
throw new Error("unreachable");
}
errors.innerHTML = error;
throw error;
}
}, "encoded", "decoded")
}
function encode() {
let input_pane = document.getElementById("pane__decoded");
if (input_pane == null) {
throw new Error("unreachable");
}
let input = input_pane.querySelector('textarea');
if (input == null) {
throw new Error("unreachable");
}
let {contents, error: errors} = decoded_state;
state.switchState(() => {
try {
return {value: desynced_lib.encode(
input.value.trim(),
contents.value.trim(),
{
decodeFormat: getDecodeFormat(),
interRepr: getInterRepr(),
},
)};
} catch (error) {
let errors = input_pane.querySelector('.errors');
if (errors == null) {
throw new Error("unreachable");
}
errors.innerHTML = error;
throw error;
}
Expand All @@ -249,27 +260,21 @@ async function main() {
})
);
document.querySelectorAll("button[data-action=cv_to_decoded]").forEach(
(button) => button.addEventListener('click', decode)
);
document.querySelectorAll("#pane__encoded > textarea").forEach(
(button) => /** @type {HTMLElement} */ (button)
.addEventListener('keydown', (event) => {
if (event.key == "Enter" && event.ctrlKey) {
decode();
}
})
(button) => button.addEventListener('click', () => decode())
);
encoded_state.contents.addEventListener('keydown', (event) => {
if (event.key == "Enter" && event.ctrlKey) {
decode();
}
});
document.querySelectorAll("button[data-action=cv_to_encoded]").forEach(
(button) => button.addEventListener('click', encode)
);
document.querySelectorAll("#pane__decoded > textarea").forEach(
(button) => /** @type {HTMLElement} */ (button)
.addEventListener('keydown', (event) => {
if (event.key == "Enter" && event.ctrlKey) {
encode();
}
})
(button) => button.addEventListener('click', () => encode())
);
decoded_state.contents.addEventListener('keydown', (event) => {
if (event.key == "Enter" && event.ctrlKey) {
encode();
}
});
}

main();
Expand Down

0 comments on commit 642f3b9

Please sign in to comment.