From f6405095dbf47cf25776ea9dc06a2e7ca8f2e1f6 Mon Sep 17 00:00:00 2001 From: "Thomas M. Edwards" Date: Sat, 1 Aug 2020 07:45:41 -0500 Subject: [PATCH 1/9] [Update] Disable save button in Saves dialog if the `Config.saves.isAllowed` query yields `false`. Resolves #69 . --- src/ui.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ui.js b/src/ui.js index 22fd8ae..8402bb8 100644 --- a/src/ui.js +++ b/src/ui.js @@ -202,6 +202,8 @@ var UI = (() => { // eslint-disable-line no-unused-vars, no-var } function uiBuildSaves() { + const savesAllowed = typeof Config.saves.isAllowed !== 'function' || Config.saves.isAllowed(); + function createActionItem(bId, bClass, bText, bAction) { const $btn = jQuery(document.createElement('button')) .attr('id', `saves-${bId}`) @@ -363,7 +365,7 @@ var UI = (() => { // eslint-disable-line no-unused-vars, no-var else { // Add the save button. $tdLoad.append( - createButton('save', 'ui-close', L10n.get('savesLabelSave'), i, Save.slots.save) + createButton('save', 'ui-close', L10n.get('savesLabelSave'), i, savesAllowed ? Save.slots.save : null) ); // Add the description. @@ -409,7 +411,7 @@ var UI = (() => { // eslint-disable-line no-unused-vars, no-var 'export', 'ui-close', L10n.get('savesLabelExport'), - () => Save.export() + savesAllowed ? () => Save.export() : null )); $btnBar.append(createActionItem( 'import', From 4cedaa1e659042cf8d7ea3647e2aa500d945a44f Mon Sep 17 00:00:00 2001 From: "Thomas M. Edwards" Date: Mon, 3 Aug 2020 17:05:08 -0500 Subject: [PATCH 2/9] [Fix] Fixed `<>` thowing. Resolves #70 . --- src/macros/macrolib.js | 226 +++++++++++++++++++++++------------------ 1 file changed, 126 insertions(+), 100 deletions(-) diff --git a/src/macros/macrolib.js b/src/macros/macrolib.js index cbfc9d4..798a6a3 100644 --- a/src/macros/macrolib.js +++ b/src/macros/macrolib.js @@ -389,6 +389,7 @@ Macro.add('type', { isAsync : true, tags : null, + typeId : 0, handler() { if (this.args.length === 0) { @@ -535,126 +536,151 @@ // If the queue is empty at this point, set the start typing flag. const startTyping = TempState.macroTypeQueue.length === 0; + // Generate our unique ID. + const selfId = ++this.self.typeId; + // Push our typing handler onto the queue. - TempState.macroTypeQueue.push(() => { - const $wrapper = jQuery(document.createElement(elTag)) - .addClass(className); + TempState.macroTypeQueue.push({ + id : selfId, - // Add the user ID, if any. - if (elId) { - $wrapper.attr('id', elId); - } + handler() { + const $wrapper = jQuery(document.createElement(elTag)) + .addClass(className); - // Add the user class(es), if any. - if (elClass) { - $wrapper.addClass(elClass); - } + // Add the user ID, if any. + if (elId) { + $wrapper.attr('id', elId); + } - new Wikifier($wrapper, contents); + // Add the user class(es), if any. + if (elClass) { + $wrapper.addClass(elClass); + } - const passage = State.passage; + new Wikifier($wrapper, contents); - // Skip typing if…. - if ( - // …we've visited the passage before. - !Config.macros.typeVisitedPassages - && State.passages.slice(0, -1).some(title => title === passage) + const passage = State.passage; + const turn = State.length; - // …there were any content errors. - || $wrapper.find('.error').length > 0 - ) { - $target.replaceWith($wrapper); + // Skip typing if…. + if ( + // …we've visited the passage before. + !Config.macros.typeVisitedPassages + && State.passages.slice(0, -1).some(title => title === passage) - // Remove this handler from the queue. - TempState.macroTypeQueue.shift(); + // …there were any content errors. + || $wrapper.find('.error').length > 0 + ) { + $target.replaceWith($wrapper); - // Run the next typing handler in the queue, if any. - if (TempState.macroTypeQueue.length > 0) { - TempState.macroTypeQueue.first()(); - } + // Remove this handler from the queue. + TempState.macroTypeQueue.shift(); - return; - } - - // Create a new `NodeTyper` instance for the wrapper's contents and - // replace the target with the typing wrapper. - const typer = new NodeTyper({ - targetNode : $wrapper.get(0), - classNames : cursor === 'none' ? null : `${className}-cursor` - }); - $target.replaceWith($wrapper); - - // Set up event IDs. - const typingCompleteId = ':typingcomplete'; - const typingStartId = ':typingstart'; - const typingStopId = ':typingstop'; - const keydownAndNS = `keydown${namespace}`; - const typingStopAndNS = `${typingStopId}${namespace}`; - - // Set up handlers for spacebar aborting and continuations. - $(document) - .off(keydownAndNS) - .on(keydownAndNS, ev => { - // Finish typing if the player aborts via the skip key. - if ( - Util.scrubEventKey(ev.key) === skipKey - && (ev.target === document.body || ev.target === document.documentElement) - ) { - ev.preventDefault(); - $(document).off(keydownAndNS); - typer.finish(); - } - }) - .one(typingStopAndNS, () => { - // Fire the typing complete event and return, if the queue is empty. - if (TempState.macroTypeQueue.length === 0) { - jQuery.event.trigger(typingCompleteId); - return; + // Run the next typing handler in the queue, if any. + if (TempState.macroTypeQueue.length > 0) { + TempState.macroTypeQueue.first().handler(); } - // Run the next typing handler in the queue. - TempState.macroTypeQueue.first()(); + return; + } + + // Create a new `NodeTyper` instance for the wrapper's contents and + // replace the target with the typing wrapper. + const typer = new NodeTyper({ + targetNode : $wrapper.get(0), + classNames : cursor === 'none' ? null : `${className}-cursor` }); + $target.replaceWith($wrapper); - // Set up the typing interval and start/stop event firing. - const typeNode = function typeNode() { - // Fire the typing start event. - $wrapper.trigger(typingStartId); + // Set up event IDs. + const typingCompleteId = ':typingcomplete'; + const typingStartId = ':typingstart'; + const typingStopId = ':typingstop'; + const keydownAndNS = `keydown${namespace}`; + const typingStopAndNS = `${typingStopId}${namespace}`; + + // Set up handlers for spacebar aborting and continuations. + $(document) + .off(keydownAndNS) + .on(keydownAndNS, ev => { + // Finish typing if the player aborts via the skip key. + if ( + Util.scrubEventKey(ev.key) === skipKey + && (ev.target === document.body || ev.target === document.documentElement) + ) { + ev.preventDefault(); + $(document).off(keydownAndNS); + typer.finish(); + } + }) + .one(typingStopAndNS, () => { + if (TempState.macroTypeQueue) { + // If the queue is empty, fire the typing complete event. + if (TempState.macroTypeQueue.length === 0) { + jQuery.event.trigger(typingCompleteId); + } + // Elsewise, run the next typing handler in the queue. + else { + TempState.macroTypeQueue.first().handler(); + } + } + }); - const typeNodeId = setInterval(() => { - // Stop typing if…. - if ( - // …we've navigated away. - State.passage !== passage + // Set up the typing interval and start/stop event firing. + const typeNode = function typeNode() { + // Fire the typing start event. + $wrapper.trigger(typingStartId); + + const typeNodeId = setInterval(() => { + // Stop typing if…. + if ( + // …we've navigated away. + State.passage !== passage + || State.length !== turn + + // …we're done typing. + || !typer.type() + ) { + if (TempState.macroTypeQueue) { + console.log(`[type interval (${selfId})] clearing interval, queue length=${TempState.macroTypeQueue.length}`); + } + else { + console.log(`[type interval (${selfId})] clearing interval, no queue`); + } - // …we're done typing. - || !typer.type() - ) { - clearInterval(typeNodeId); + clearInterval(typeNodeId); - // Remove this handler from the queue. - TempState.macroTypeQueue.shift(); + // Remove this handler from the queue, if the queue still exists and the + // handler IDs match. + if ( + TempState.macroTypeQueue + && TempState.macroTypeQueue.length > 0 + && TempState.macroTypeQueue.first().id === selfId + ) { + TempState.macroTypeQueue.shift(); + } - // Fire the typing stop event. - $wrapper.trigger(typingStopId); + // Fire the typing stop event. + $wrapper.trigger(typingStopId); - // Add the done class to the wrapper. - $wrapper.addClass(`${className}-done`); + // Add the done class to the wrapper. + $wrapper.addClass(`${className}-done`); - // Add the cursor class to the wrapper, if we're keeping it. - if (cursor === 'keep') { - $wrapper.addClass(`${className}-cursor`); + // Add the cursor class to the wrapper, if we're keeping it. + if (cursor === 'keep') { + $wrapper.addClass(`${className}-cursor`); + } } - } - }, speed); - }; + }, speed); + }; - // Kick off typing the node. - if (start) { - setTimeout(typeNode, start); - } - else { - typeNode(); + // Kick off typing the node. + if (start) { + setTimeout(typeNode, start); + } + else { + typeNode(); + } } }); @@ -662,10 +688,10 @@ // to do so or start it immediately, depending on the engine state. if (startTyping) { if (Engine.isPlaying()) { - $(document).one(`:passageend${namespace}`, () => TempState.macroTypeQueue.first()()); + $(document).one(`:passageend${namespace}`, () => TempState.macroTypeQueue.first().handler()); } else { - TempState.macroTypeQueue.first()(); + TempState.macroTypeQueue.first().handler(); } } } From 2ee35349ece3a2bf35712dd14b60c2074838923e Mon Sep 17 00:00:00 2001 From: "Thomas M. Edwards" Date: Tue, 4 Aug 2020 09:59:46 -0500 Subject: [PATCH 3/9] [Fix, Update] More fixing of `<>` and cleanup. --- src/macros/macrolib.js | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/macros/macrolib.js b/src/macros/macrolib.js index 798a6a3..a3015c0 100644 --- a/src/macros/macrolib.js +++ b/src/macros/macrolib.js @@ -557,10 +557,12 @@ $wrapper.addClass(elClass); } + // Wikify the contents into `$wrapper`. new Wikifier($wrapper, contents); + // Cache info about the current turn. const passage = State.passage; - const turn = State.length; + const turn = State.turns; // Skip typing if…. if ( @@ -581,6 +583,7 @@ TempState.macroTypeQueue.first().handler(); } + // Exit. return; } @@ -636,18 +639,12 @@ if ( // …we've navigated away. State.passage !== passage - || State.length !== turn + || State.turns !== turn // …we're done typing. || !typer.type() ) { - if (TempState.macroTypeQueue) { - console.log(`[type interval (${selfId})] clearing interval, queue length=${TempState.macroTypeQueue.length}`); - } - else { - console.log(`[type interval (${selfId})] clearing interval, no queue`); - } - + // Terminate the timer. clearInterval(typeNodeId); // Remove this handler from the queue, if the queue still exists and the From e8ce867c2ea3eb74d8cfb9eed3726b40dbaa395e Mon Sep 17 00:00:00 2001 From: "Thomas M. Edwards" Date: Tue, 4 Aug 2020 10:00:56 -0500 Subject: [PATCH 4/9] [Update] Improve `<>` and `<>` wrt. navigating away. --- src/macros/macrolib.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/macros/macrolib.js b/src/macros/macrolib.js index a3015c0..7383bd0 100644 --- a/src/macros/macrolib.js +++ b/src/macros/macrolib.js @@ -3388,14 +3388,18 @@ throw new TypeError('callback parameter must be a function'); } - const turnId = State.turns; + // Cache info about the current turn. + const passage = State.passage; + const turn = State.turns; + + // Timer info. const timers = this.timers; let timerId = null; // Set up the interval. timerId = setInterval(() => { - // Terminate the timer if the turn IDs do not match. - if (turnId !== State.turns) { + // Terminate if we've navigated away. + if (State.passage !== passage || State.turns !== turn) { clearInterval(timerId); timers.delete(timerId); return; @@ -3562,7 +3566,11 @@ throw new TypeError('callback parameter must be a function'); } - const turnId = State.turns; + // Cache info about the current turn. + const passage = State.passage; + const turn = State.turns; + + // Timer info. const timers = this.timers; let timerId = null; let nextItem = items.shift(); @@ -3571,7 +3579,8 @@ // Bookkeeping. timers.delete(timerId); - if (turnId !== State.turns) { + // Terminate if we've navigated away. + if (State.passage !== passage || State.turns !== turn) { return; } From 28951f4c31d92f5ced0540dd4b77370358fb8b2e Mon Sep 17 00:00:00 2001 From: "Thomas M. Edwards" Date: Wed, 12 Aug 2020 07:21:58 -0500 Subject: [PATCH 5/9] [Fix] Fixed misplaced outline hiding call. Resolves #71 . --- src/engine.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/engine.js b/src/engine.js index 2285bfa..f21892b 100644 --- a/src/engine.js +++ b/src/engine.js @@ -124,6 +124,7 @@ var Engine = (() => { // eslint-disable-line no-unused-vars, no-var .appendTo(document.head) .get(0) // return the \n\n\n\n\n\n\n\n\n\n\n\n\n\t
\n\t\t
\n\t\t
Your browser lacks required capabilities. Please upgrade it or switch to another to continue.
\n\t\t
Loading…
\n\t
\n\t{{STORY_DATA}}\n\t\n\n\n"}); \ No newline at end of file +window.storyFormat({"name":"SugarCube","version":"2.33.2","description":"A full featured, highly customizable story format. See its documentation.","author":"Thomas Michael Edwards","image":"icon.svg","url":"http://www.motoslave.net/sugarcube/","license":"BSD-2-Clause","proofing":false,"source":"\n\n\n\n{{STORY_NAME}}\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\t
\n\t\t
\n\t\t
Your browser lacks required capabilities. Please upgrade it or switch to another to continue.
\n\t\t
Loading…
\n\t
\n\t{{STORY_DATA}}\n\t\n\n\n"}); \ No newline at end of file