Skip to content

v0.2.0

Latest

Choose a tag to compare

@Daniel-Glz Daniel-Glz released this 29 Oct 14:41
· 6 commits to main since this release
d2441d7

Variables and conditions, multiple-answer and timed questions, cues and player plugins, jumping to any scene, and recovery from videos that fail. Both packages are now licensed under Apache 2.0.

Added

  • @ivkit/core: answerRange(question, offered), the fewest and most options an answer takes. The engine, validateStory and the player now share it.
  • @ivkit/core: StoryEngine.goTo(sceneId, time?), which enters any scene from any state, dismissing the question on screen, and plays it from time, asking its questions from there on. It works before start(), e.g. to resume a saved story. The scene event now carries that time, and MediaController starts the video there.
  • @ivkit/core: StoryEngine.seek(time), which resumes the current scene from time like a seek in the story.
  • @ivkit/core: StoryEngine.destroy(), which cancels a question's timeout and removes every listener, and pauseTimeout() and resumeTimeout(), which stop and go on with a question's countdown.
  • @ivkit/player: goTo(sceneId, time?) on <ivkit-player>, which jumps to a scene and plays it. Use it to branch on a score, resume where the viewer left off or build chapter menus.
  • @ivkit/core: an error event on MediaController when a scene's video can't be loaded or played, and retry(), which loads it again from where it failed. A failed preload is no longer stuck: it's loaded again when its scene comes.
  • @ivkit/player: an error screen with an error slot, an iv-error event and retry(), so a missing or unplayable video no longer leaves the player frozen without notice.
  • @ivkit/player: removing the player from the page pauses a question's timeout until it's back, and keeps a scene that finishes loading meanwhile from playing. Setting another story destroys the previous engine.
  • @ivkit/core: pause on hotspots, which pauses the video when the hotspot appears until it's activated. The engine emits a new pause event, and MediaController pauses on the hotspot's first frame and resumes when it's activated without a goto.
  • @ivkit/core: variables and conditions in the story format. Story.vars declares variables, set changes them on choices, hotspots and scenes, branches pick a scene by condition before falling back to goto or next, and if offers a choice or shows a hotspot only while it holds. validateStory reports undeclared variables with the new missing_variable code.
  • @ivkit/core: StoryEngine.vars, StoryEngine.setVar() and a vars event. The interaction event now includes the options offered, and answer and hotspot include the scene they branch to as goto.
  • @ivkit/player: questions show only the options whose if holds, and iv-interaction, iv-answer and iv-hotspot carry the same new fields as the engine's events.
  • @ivkit/core: correct on choices, reported in the answer event to score quizzes.
  • @ivkit/core: seek on choices and hotspots, which resumes the current scene from another second when they don't branch, asking the questions from there on again. MediaController now seeks on resume when its time isn't the current one.
  • @ivkit/player: href on hotspots, which opens http: and https: links in a new tab when activated.
  • @ivkit/core: multiple-answer questions. multiple: true takes several options, bounded by min and max, and applies each one's set. Questions also take goto, branches and seek, which decide for multiple questions and act as a fallback for single ones. StoryEngine.answer() takes a list of ids, and the answer event adds choices and correct, true when exactly the options marked correct were picked.
  • @ivkit/player: multiple questions show toggle options and a Confirm button, exposed as ::part(submit).
  • @ivkit/core: timeout and default on questions. When nobody answers in time, the engine emits a new timeout event and answers with default, or else lets the question's branches, goto and seek decide.
  • @ivkit/player: a countdown bar for questions with timeout, exposed as ::part(timer), and an iv-timeout event. The player now ignores events from an engine it has replaced.
  • @ivkit/core: cue events in the story format, which mark a span of a scene for plugins and apps, picked by kind. The engine emits a new cues event with the active ones and exposes them as StoryEngine.activeCues.
  • @ivkit/core: data on the story, scenes, events and options, free-form JSON that IVKit carries but never reads. validateStory checks that it's a JSON object.
  • @ivkit/core: validateStory(story, { cues }) runs a plugin's checks on cues of its kind, reporting with the new invalid_cue code.
  • @ivkit/player: plugins through player.use(plugin). A plugin runs for each story with the engine, the media controller, its own layer over the video and an on() that unsubscribes by itself, and may return a cleanup. The player also dispatches iv-cues.
  • @ivkit/core: a time event on MediaController, with each playback time it reports to the engine. <ivkit-player> now moves animated hotspots on it instead of keeping its own frame callbacks.

Changed

  • The license is now the Apache License 2.0 instead of MIT, for both packages.
  • Size budgets: the standalone player now stays under 9.5 KiB gzip (was 8 KiB), and all of @ivkit/core under 6 KiB (was 4 KiB), to fit variables, conditions, multiple-answer questions and timeouts.
  • @ivkit/player: its CSS is now minified at build time, which takes about 500 B off the standalone player.
  • @ivkit/core: MediaController emits blocked only when the autoplay policy rejects play() (a NotAllowedError). A play() interrupted by a pause or a new source no longer shows the player's Play button over a scene that's playing.
  • @ivkit/core: MediaController.play() does nothing while the next scene loads, so the previous scene can't play, heard but hidden, behind it.
  • @ivkit/player: setting story to one whose start isn't a scene throws without resetting the player, instead of leaving it half reset.
  • @ivkit/core: a listener that moves the story, with goTo(), start() or seek(), wins over what the engine was doing. Before, a goTo() from an answer, hotspot or timeout listener was overridden by the answer's own branch or followed by a stale resume.
  • @ivkit/core: a listener that throws no longer stops the other listeners or leaves the engine halfway through a transition. Its error is still reported.
  • @ivkit/player: a plugin that throws, when it runs or cleans up, no longer stops the player or the plugins after it.
  • @ivkit/player: restart(), and so the Replay button, sets the variables back to their initial values. Before, a replay kept the previous run's scores and counters.
  • @ivkit/player: hotspots that stay on screen keep their buttons when others appear or go, so keyboard focus, renderHotspot changes and animations aren't lost. renderHotspot runs once per hotspot while it stays on screen.

npm: npm install @ivkit/player@0.2.0 or @ivkit/core@0.2.0