Skip to content

Commit

Permalink
Fix the spontaneous deletion, add modals
Browse files Browse the repository at this point in the history
  • Loading branch information
SaphireLattice committed Oct 30, 2024
1 parent c874857 commit 0f13ee3
Show file tree
Hide file tree
Showing 12 changed files with 1,342 additions and 2,409 deletions.
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
</div>
<noscript class="text-center mx-auto my-2 w-50">Sorry, this app is built with Vue and needs JavaScript loading enabled! It is too difficult to make a web app that would do this without any JS, as that would require a server to hold the state of your personal notes. This was developed solely for quick note taking for myself!</noscript>
<footer class="text-center mx-auto px-4 pb-2 d-flex flex-column">
<span>Tunic decoder/translator notebook app - <a href="https://github.com/SaphireLattice/tunic-decoder">Sources and hotkeys</a> - Made with love by <a href="https://saphi.re/">Saphire Lattice</a> © 2022</span>
<span>Tunic decoder/translator notebook app - <a href="https://github.com/SaphireLattice/tunic-decoder">Source code</a> - <a href="#" id="keybinds-button">Help</a> - Made with love by <a href="https://saphi.re/">Saphire Lattice</a> © 2022</span>
<span><a href="https://tunicgame.com/">TUNIC game</a> and glyph language @ ISOMETRICORP Games Ltd, Finji LLC, 2022</span>
</footer>
<script type="module" src="/src/main.ts"></script>
Expand Down
3,330 changes: 966 additions & 2,364 deletions package-lock.json

Large diffs are not rendered by default.

20 changes: 11 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
{
"name": "tunic-decoder",
"version": "0.0.0",
"version": "0.2.0",
"type": "module",
"scripts": {
"dev": "vite",
"dev": "vite --port 3000",
"build": "vue-tsc --noEmit && vite build",
"preview": "vite preview --port 5050",
"typecheck": "vue-tsc --noEmit"
},
"dependencies": {
"bootstrap": "^5.1.3",
"bootstrap-icons": "^1.8.1",
"vue": "^3.2.31"
"vue": "^3.5.12"
},
"devDependencies": {
"@types/node": "^16.11.25",
"@vitejs/plugin-vue": "^2.2.2",
"@vue/tsconfig": "^0.1.3",
"typescript": "~4.5.5",
"vite": "^2.8.4",
"vue-tsc": "^0.31.4"
"@tsconfig/node20": "^20.1.4",
"@types/node": "^20.17.0",
"@vitejs/plugin-vue": "^5.1.4",
"@vue/tsconfig": "^0.5.1",
"typescript": "~5.6.0",
"vite": "^5.4.10",
"vue-tsc": "^2.1.6"
}
}
120 changes: 113 additions & 7 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import WordInput from "./components/WordInput.vue";
import WordList from "./components/WordList.vue";
import Toast from "./components/Toast.vue";
import Modal from "./components/Modal.vue";
import "bootstrap/dist/css/bootstrap.min.css";
import "bootstrap-icons/font/bootstrap-icons.css";
Expand All @@ -11,6 +12,8 @@ import { Glyph, Paragraph, Word } from "./glyphs";
type SavedState = {
spoilerMode?: boolean;
spoilHidden?: boolean;
spoilerSpecificFeature?: boolean;
words: { glyphs: string; text?: string }[];
texts: { glyphs: string[]; description?: string }[];
};
Expand All @@ -30,7 +33,11 @@ const state = reactive({
glyphOnly: false,
showPhonetic: false,
toastText: undefined as string | undefined,
modalHelp: false,
spoilerMode: false,
spoilHidden: false,
spoilerConfirmShowModal: false,
page: "input",
});
Expand Down Expand Up @@ -62,6 +69,7 @@ async function onKeyInput(event: KeyboardEvent) {
if (!notHandled) return;
if (event.key == "Escape" && state.selectedWord) state.selectedWord = undefined;
if (event.key == "F1") state.modalHelp = !state.modalHelp;
}
watch(
Expand Down Expand Up @@ -107,6 +115,20 @@ watch(
}
);
watch(
() => state.spoilHidden,
(val) => {
console.log("Hide?", val, state.spoilHidden);
let wasOn = state.spoilerMode;
if (state.spoilHidden) {
state.showPhonetic = false;
state.spoilerMode = false;
}
if (wasOn)
refreshWords(val)
}
);
async function restoreEditing(target?: Word, alreadySaved: boolean = false) {
if (!target && !state.stashedWord) return;
const editedWord = state.word;
Expand Down Expand Up @@ -166,6 +188,13 @@ onMounted(() => {
loadData();
document.addEventListener("keydown", onKeyInput);
const keybindsButton = document.getElementById("keybinds-button") as HTMLAnchorElement;
keybindsButton.addEventListener("click", (e) => {
e.preventDefault();
state.modalHelp = true;
})
});
onUnmounted(() => {
Expand All @@ -188,7 +217,12 @@ async function loadData() {
if (!json) return;
const data = JSON.parse(json) as SavedState;
state.spoilerMode = data.spoilerMode ?? false;
state.spoilHidden = data.spoilHidden ?? false;
if (!state.spoilHidden) {
state.spoilerMode = data.spoilerMode ?? false;
state.showPhonetic = data.spoilerSpecificFeature ?? false;
}
console.log("Loading all words");
state.words.push(
...(await Promise.all(
Expand All @@ -205,17 +239,28 @@ async function loadData() {
data.texts.map(
(t) =>
new Paragraph(
t.glyphs.map((g) => state.words.find((w) => w.toGlyphString() == g)!),
t.glyphs
.map((g) => state.words.find((w) => w.toGlyphString() == g)!)
.filter((w) => w != null),
t.description
)
)
))
);
}
function spoilerConfirm(event: MouseEvent) {
if (state.spoilerMode) return;
event.preventDefault();
state.spoilerConfirmShowModal = true;
}
function saveData() {
let data: SavedState = {
spoilerMode: state.spoilerMode,
spoilerSpecificFeature: state.showPhonetic,
spoilHidden: state.spoilHidden,
words: state.words.map((w) => ({
glyphs: w.toGlyphString(),
text: w.plaintext,
Expand Down Expand Up @@ -275,7 +320,7 @@ html {
</style>

<template>
<main class="container my-4">
<main class="container my-4" @keydown.question="console.log('hi')">
<ul class="nav nav-tabs d-flex d-lg-none">
<li class="nav-item" v-for="page in ['input', 'words', 'texts']">
<a
Expand Down Expand Up @@ -305,6 +350,7 @@ html {
:glyph="state.glyph"
:words="state.words"
v-model:selected="state.selectedWord"
v-model:spoilHidden="state.spoilHidden"
@deleted="saveData()"
@add-word="addTextWord"
/>
Expand All @@ -314,7 +360,7 @@ html {
<div class="card-header">
<h2 class="card-title d-flex justify-content-end align-items-end">
<span class="flex-fill">Texts</span>
<div v-if="state.spoilerMode" class="form-check font-size-1">
<div v-if="state.spoilerMode && !state.spoilHidden" class="form-check font-size-1">
<input
class="form-check-input"
type="checkbox"
Expand All @@ -323,16 +369,17 @@ html {
/>
<label class="form-check-label" for="spoilerGatedFeatureCheckbox"> Phonetic </label>
</div>
<div class="form-check font-size-1 ms-2">
<div v-if="!state.spoilHidden" class="form-check font-size-1 ms-2" title="Away with the theatre, show me everything!">
<input
class="form-check-input"
type="checkbox"
v-model="state.spoilerMode"
@click="spoilerConfirm"
id="spoilerCheckbox"
/>
<label class="form-check-label" for="spoilerCheckbox"> Spoil! </label>
</div>
<div class="form-check font-size-1 ms-2">
<div class="form-check font-size-1 ms-2" title="Show only glyphs, no translations!">
<input
class="form-check-input"
type="checkbox"
Expand All @@ -344,9 +391,12 @@ html {
</h2>
</div>
<ul class="list-group list-group-flush">
<div class="list-group-item text-center text-muted" v-if="state.texts.length == 0">
<div class="list-group-item text-center text-muted my-2" v-if="state.texts.length == 0">
Press "New text" to add a text
</div>
<div class="list-group-item text-center text-muted my-2" v-if="state.texts.length != 0 && !state.texts.some((t) => filterCheckText(t))">
No texts with selected word found. <a href="#" @click="state.selectedWord = undefined">Reset selected word?</a>
</div>
<template v-for="text in state.texts">
<li
v-if="filterCheckText(text)"
Expand Down Expand Up @@ -457,4 +507,60 @@ html {
<Toast :text="state.toastText" @done="state.toastText = undefined"></Toast>
</div>
</main>
<div id="modals">
</div>

<Modal modal-id="spoiler-confirm" title="The last line between" v-model="state.spoilerConfirmShowModal">
<p>Are you sure you want to enable the spoiler mode? If you've not finished the game yet, there will be hints that show up later!</p>
<p>You can disable this checkbox by typing <code>@hide spoiler</code> into the search box, and reveal it again with <code>@show spoiler</code>!</p>
<template v-slot:footer="footerSlot">
<button class="btn btn-outline-primary" @click="footerSlot.close">Go back</button>
<button class="btn btn-danger" @click="() => { state.spoilerMode = true; footerSlot.close(); }">Spoil!</button>
</template>
</Modal>
<Modal modal-id="help" title="Help and Keybinds" v-model="state.modalHelp">
<p>
Hi! Thanks for taking a look at this web app. This is made for figuring out TUNIC's writing <em>on your own</em>.
No this does <em>not</em> translate things automatically for you! I wrote this while playing the game and figuring things out myself, and realized that using just paper will be rather difficult if I want to search through things and cross-reference them.
As such, there's a lot of little things to help you figure out the writing yourself, though potentially biased by my own attempts at figuring it out in some places, whether they were right or wrong.
</p>
<hr>
<p>
This application was made with extensive keyboard input support, to make typing in patterns quick and easy. It's oriented towards input with the left half of a QWERTY keyboard, and sadly there's no right handed mode.
Feel free to poke me on <a href="https://github.com/SaphireLattice/tunic-decoder/issues">GitHub issues</a> or via email if you want more extensive keybinds support!
</p>
<p class="mb-0"><strong>Keybinds:</strong></p>
<ul>
<li><code>QWER</code> to toggle lines 1-2-3-4 out of the currently highlit with blue ones. There's no highlight until you first use the keyboard input!</li>
<li><code>F</code> and <code>Shift + F</code> for choosing next and previous 4 lines to input</li>
<li><code>A</code> and <code>Shift + A</code> to delete/pop, and to add a blank/push a glyph respectively. If the glyph is not empty, it will be saved into a temporary secondary buffer (shown to the right of the fully black cursor). This can be useful to copy a word! Note that the buffer is not saved between app reloads</li>
<li><code>C</code> to clear current glyph input</li>
<li><code>Shift + D</code> to push the current word into the list of words, including the text/descriping in the field under the input panel. The secondary buffer is not cleared</li>
<li><code>Esc</code> to hide the highlight and stop keyboard input session. The glyph, word and buffer are not cleared</li>
<li><code>F1</code> to show this dialog</li>
</ul>
<hr>
<p><strong>Search box:</strong></p>
<p>You can search for any text that you've put into the word's assigned note, or for hex code of a glyph within a word.</p>
<p>The search box also supports a weird way of searching for patterns!</p>
<p class="mb-0">
Type <code>\</code> and then...
</p>
<ul>
<li>one or a few of <code>v^|o</code> to search for glyphs that have as many similar line patterns to the searched thing as you put in. Play around with it!</li>
<li><code>lr</code> searches for lines on the "left" and "right" half of it respectively.</li>
<li>Replace <code>\</code> with one <code>=</code> to require exact count of patterns you've entered, not counting the ones you didn't search for. Two <code>==</code> to search for EXACT match in count, and assume 0 for anything not entered.</li>
</ul>
<p class="mb-0">
Search patterns that depend on current Glyph Input state:
</p>
<ul>
<li><code>@</code> - glyphs that have at least the same lines active as current Glyph Input state</li>
<li><code>@@</code> - glyphs that are identical to the Glyph Input </li>
<li v-if="state.spoilerMode"><code>@i [optional hex]</code> - glyphs that match the Glyph Input on the "inside", or match the hex input in same way</li>
<li v-if="state.spoilerMode"><code>@o [hex?]</code> - same as above, but "outside"</li>
</ul>
<hr>
<p>To hide the <strong>Spoil!</strong> checkbox (don't worry, it now has a modal confirmation!), type <code>@hide spoilers</code> into search box, and it'll disappear. If you do want it back, just type <code>@show spoilers</code> - this only shows the checkbox, it doesn't activate it!</p>
</Modal>
</template>
Loading

0 comments on commit 0f13ee3

Please sign in to comment.