@audiowalk/sdk 1.2.2 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from "./player/player-controller";
2
2
  export * from "./storage/local-storage";
3
+ export * from "./story/story-controller";
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AACxC,cAAc,0BAA0B,CAAC"}
package/dist/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from "./player/player-controller";
2
2
  export * from "./storage/local-storage";
3
+ export * from "./story/story-controller";
@@ -1 +1 @@
1
- {"version":3,"file":"player-controller.d.ts","sourceRoot":"","sources":["../../src/player/player-controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAsB,OAAO,EAAE,MAAM,MAAM,CAAC;AAGpE,MAAM,WAAW,uBAAuB;IACtC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,oBAAY,YAAY;IACtB,SAAS,YAAY;IACrB,QAAQ,WAAW;IACnB,OAAO,UAAU;CAClB;AAED,qBAAa,gBAAgB;IAiBf,OAAO,CAAC,QAAQ,CAAC,aAAa;IAAoB,OAAO,CAAC,OAAO;IAhB7E,SAAgB,MAAM,gBAAuB;IAC7C,SAAgB,OAAO,gBAAuB;IAC9C,SAAgB,MAAM,gBAAuB;IAE7C,SAAgB,WAAW,0BAAkC;IAC7D,SAAgB,SAAS,0BAAkC;IAC3D,SAAgB,QAAQ,oCAEtB;IAEF,SAAgB,MAAM,uCAAkD;IAExE,SAAgB,OAAO,qCAA2D;IAElF,OAAO,CAAC,YAAY,CAAsB;gBAEb,aAAa,EAAE,gBAAgB,EAAU,OAAO,GAAE,uBAA4B;IAmErG,IAAI,CAAC,IAAI,EAAE,MAAM;IASvB,WAAW,CAAC,QAAQ,EAAE,iBAAiB;IAIvC,KAAK;IAYL,IAAI;IAOJ,KAAK;IAML,MAAM,CAAC,OAAO,EAAE,MAAM;IAOtB,IAAI,CAAC,OAAO,GAAE,MAAW;IAOzB,OAAO,CAAC,OAAO,GAAE,MAAW;YAQd,YAAY;IAK1B,OAAO,CAAC,GAAG;CAOZ"}
1
+ {"version":3,"file":"player-controller.d.ts","sourceRoot":"","sources":["../../src/player/player-controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAsB,OAAO,EAAE,MAAM,MAAM,CAAC;AAGpE,MAAM,WAAW,uBAAuB;IACtC,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,oBAAY,YAAY;IACtB,SAAS,YAAY;IACrB,QAAQ,WAAW;IACnB,OAAO,UAAU;CAClB;AAED,qBAAa,gBAAgB;IAiBf,OAAO,CAAC,QAAQ,CAAC,aAAa;IAAoB,OAAO,CAAC,OAAO;IAhB7E,SAAgB,MAAM,gBAAuB;IAC7C,SAAgB,OAAO,gBAAuB;IAC9C,SAAgB,MAAM,gBAAuB;IAE7C,SAAgB,WAAW,0BAAkC;IAC7D,SAAgB,SAAS,0BAAkC;IAC3D,SAAgB,QAAQ,oCAEtB;IAEF,SAAgB,MAAM,uCAAkD;IAExE,SAAgB,OAAO,qCAA2D;IAElF,OAAO,CAAC,YAAY,CAAsB;gBAEb,aAAa,EAAE,gBAAgB,EAAU,OAAO,GAAE,uBAA4B;IAmErG,IAAI,CAAC,IAAI,EAAE,MAAM;IAYvB,WAAW,CAAC,QAAQ,EAAE,iBAAiB;IAIvC,KAAK;IAYL,IAAI;IAOJ,KAAK;IAML,MAAM,CAAC,OAAO,EAAE,MAAM;IAOtB,IAAI,CAAC,OAAO,GAAE,MAAW;IAOzB,OAAO,CAAC,OAAO,GAAE,MAAW;YAQd,YAAY;IAK1B,OAAO,CAAC,GAAG;CAOZ"}
@@ -79,9 +79,9 @@ export class PlayerController {
79
79
  }
80
80
  async open(file) {
81
81
  this.playerElement.src = file;
82
- const position = await this.localStorage.get(`progress-${this.playerElement.src}`);
82
+ const position = await this.localStorage.get(`progress-${this.playerElement.src}`, (value) => typeof value === "number");
83
83
  if (position && this.options.autoSave)
84
- this.playerElement.currentTime = parseFloat(position);
84
+ this.playerElement.currentTime = position;
85
85
  if (this.options.playOnInit)
86
86
  await this.playerElement.play();
87
87
  }
@@ -4,8 +4,9 @@ export interface LocalStorageOptions {
4
4
  export declare class LocalStorage {
5
5
  private options;
6
6
  constructor(options?: Partial<LocalStorageOptions>);
7
- get(key: string): Promise<string | null>;
7
+ get<T = unknown>(key: string, validate?: (value: unknown) => value is T): Promise<T | null>;
8
8
  set(key: string, value: any): Promise<void>;
9
+ private parseData;
9
10
  private getPrefixedKey;
10
11
  }
11
12
  //# sourceMappingURL=local-storage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"local-storage.d.ts","sourceRoot":"","sources":["../../src/storage/local-storage.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,YAAY;IACX,OAAO,CAAC,OAAO;gBAAP,OAAO,GAAE,OAAO,CAAC,mBAAmB,CAAM;IAExD,GAAG,CAAC,GAAG,EAAE,MAAM;IAIf,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG;IAIjC,OAAO,CAAC,cAAc;CAQvB"}
1
+ {"version":3,"file":"local-storage.d.ts","sourceRoot":"","sources":["../../src/storage/local-storage.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,qBAAa,YAAY;IACX,OAAO,CAAC,OAAO;gBAAP,OAAO,GAAE,OAAO,CAAC,mBAAmB,CAAM;IAExD,GAAG,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAiB3F,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG;IAKjC,OAAO,CAAC,SAAS;IAQjB,OAAO,CAAC,cAAc;CAQvB"}
@@ -3,11 +3,34 @@ export class LocalStorage {
3
3
  constructor(options = {}) {
4
4
  this.options = options;
5
5
  }
6
- async get(key) {
7
- return window.localStorage.getItem(this.getPrefixedKey(key));
6
+ async get(key, validate) {
7
+ const data = window.localStorage.getItem(this.getPrefixedKey(key));
8
+ if (data === null)
9
+ return null;
10
+ const value = this.parseData(data);
11
+ if (typeof validate === "function") {
12
+ if (validate(value)) {
13
+ return this.parseData(data);
14
+ }
15
+ else {
16
+ return null;
17
+ }
18
+ }
19
+ else {
20
+ return value;
21
+ }
8
22
  }
9
23
  async set(key, value) {
10
- return window.localStorage.setItem(this.getPrefixedKey(key), value);
24
+ const data = JSON.stringify(value);
25
+ return window.localStorage.setItem(this.getPrefixedKey(key), data);
26
+ }
27
+ parseData(data) {
28
+ try {
29
+ return JSON.parse(data);
30
+ }
31
+ catch (e) {
32
+ return data;
33
+ }
11
34
  }
12
35
  getPrefixedKey(key) {
13
36
  const keyParts = ["audiowalk"];
@@ -0,0 +1,38 @@
1
+ import { BehaviorSubject, Subject } from "rxjs";
2
+ export interface BasicChapterDefinition<ChapterId extends string = string, StoryState extends {} = {}> {
3
+ id: ChapterId;
4
+ nextChapter: ChapterId | ((state: StoryState) => ChapterId) | ((state: StoryState) => Promise<ChapterId>) | null;
5
+ }
6
+ export interface BasicStoryState<ChapterId extends string = string> {
7
+ currentChapter: ChapterId;
8
+ }
9
+ export interface StoryControllerOptions<StoryState> {
10
+ stateStorageKey?: string;
11
+ validateState?: (state: any) => state is StoryState;
12
+ }
13
+ export interface StoryDefinition<ChapterId extends string = string, StoryState extends {
14
+ currentChapter?: ChapterId;
15
+ } = BasicStoryState<ChapterId>, ChapterDefinition extends BasicChapterDefinition<ChapterId, StoryState> = BasicChapterDefinition<ChapterId, StoryState>> {
16
+ chapters: Record<ChapterId, ChapterDefinition>;
17
+ initialState: StoryState;
18
+ }
19
+ export declare class StoryController<ChapterId extends string = string, StoryState extends {
20
+ currentChapter?: ChapterId;
21
+ } = BasicStoryState<ChapterId>, ChapterDefinition extends BasicChapterDefinition<ChapterId, StoryState> = BasicChapterDefinition<ChapterId, StoryState>> {
22
+ readonly story: StoryDefinition<ChapterId, StoryState, ChapterDefinition>;
23
+ private options;
24
+ readonly storyState: BehaviorSubject<StoryState>;
25
+ readonly currentChapter: BehaviorSubject<ChapterDefinition | null>;
26
+ readonly end: Subject<void>;
27
+ private readonly localStorage;
28
+ private readonly stateStorageKey;
29
+ constructor(story: StoryDefinition<ChapterId, StoryState, ChapterDefinition>, options?: StoryControllerOptions<StoryState>);
30
+ setState(state: StoryState): Promise<void>;
31
+ updateState(update: Partial<StoryState> | ((state: StoryState) => StoryState)): Promise<void>;
32
+ setChapter(string: ChapterId): Promise<void>;
33
+ nextChapter(): Promise<void | null>;
34
+ endStory(): void;
35
+ private loadState;
36
+ private saveState;
37
+ }
38
+ //# sourceMappingURL=story-controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"story-controller.d.ts","sourceRoot":"","sources":["../../src/story/story-controller.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAO,OAAO,EAAE,MAAM,MAAM,CAAC;AAGrD,MAAM,WAAW,sBAAsB,CAAC,SAAS,SAAS,MAAM,GAAG,MAAM,EAAE,UAAU,SAAS,EAAE,GAAG,EAAE;IACnG,EAAE,EAAE,SAAS,CAAC;IACd,WAAW,EAAE,SAAS,GAAG,CAAC,CAAC,KAAK,EAAE,UAAU,KAAK,SAAS,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,UAAU,KAAK,OAAO,CAAC,SAAS,CAAC,CAAC,GAAG,IAAI,CAAC;CAClH;AAED,MAAM,WAAW,eAAe,CAAC,SAAS,SAAS,MAAM,GAAG,MAAM;IAChE,cAAc,EAAE,SAAS,CAAC;CAC3B;AAED,MAAM,WAAW,sBAAsB,CAAC,UAAU;IAChD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,KAAK,IAAI,UAAU,CAAC;CACrD;AAED,MAAM,WAAW,eAAe,CAC9B,SAAS,SAAS,MAAM,GAAG,MAAM,EACjC,UAAU,SAAS;IAAE,cAAc,CAAC,EAAE,SAAS,CAAA;CAAE,GAAG,eAAe,CAAC,SAAS,CAAC,EAC9E,iBAAiB,SAAS,sBAAsB,CAAC,SAAS,EAAE,UAAU,CAAC,GAAG,sBAAsB,CAC9F,SAAS,EACT,UAAU,CACX;IAED,QAAQ,EAAE,MAAM,CAAC,SAAS,EAAE,iBAAiB,CAAC,CAAC;IAC/C,YAAY,EAAE,UAAU,CAAC;CAC1B;AAED,qBAAa,eAAe,CAC1B,SAAS,SAAS,MAAM,GAAG,MAAM,EACjC,UAAU,SAAS;IAAE,cAAc,CAAC,EAAE,SAAS,CAAA;CAAE,GAAG,eAAe,CAAC,SAAS,CAAC,EAC9E,iBAAiB,SAAS,sBAAsB,CAAC,SAAS,EAAE,UAAU,CAAC,GAAG,sBAAsB,CAC9F,SAAS,EACT,UAAU,CACX;aAWiB,KAAK,EAAE,eAAe,CAAC,SAAS,EAAE,UAAU,EAAE,iBAAiB,CAAC;IAChF,OAAO,CAAC,OAAO;IAVjB,SAAgB,UAAU,8BAA8C;IACxE,SAAgB,cAAc,4CAAuD;IACrF,SAAgB,GAAG,gBAAuB;IAE1C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAe;IAE5C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAW;gBAGzB,KAAK,EAAE,eAAe,CAAC,SAAS,EAAE,UAAU,EAAE,iBAAiB,CAAC,EACxE,OAAO,GAAE,sBAAsB,CAAC,UAAU,CAAM;IAcpD,QAAQ,CAAC,KAAK,EAAE,UAAU;IAK1B,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,UAAU,KAAK,UAAU,CAAC;IAa7E,UAAU,CAAC,MAAM,EAAE,SAAS;IAI5B,WAAW;IAuBjB,QAAQ;YAIM,SAAS;YAaT,SAAS;CAGxB"}
@@ -0,0 +1,78 @@
1
+ import { BehaviorSubject, map, Subject } from "rxjs";
2
+ import { LocalStorage } from "../storage/local-storage";
3
+ export class StoryController {
4
+ story;
5
+ options;
6
+ storyState = new BehaviorSubject({});
7
+ currentChapter = new BehaviorSubject(null);
8
+ end = new Subject();
9
+ localStorage;
10
+ stateStorageKey = "state";
11
+ constructor(story, options = {}) {
12
+ this.story = story;
13
+ this.options = options;
14
+ this.localStorage = new LocalStorage({ prefix: options.stateStorageKey ?? "story-state" });
15
+ this.storyState
16
+ .pipe(map((state) => (state.currentChapter ? story.chapters[state.currentChapter] : null)))
17
+ .subscribe(this.currentChapter);
18
+ this.loadState().then((state) => {
19
+ if (state)
20
+ this.storyState.next(state);
21
+ else
22
+ this.setState(story.initialState);
23
+ });
24
+ }
25
+ async setState(state) {
26
+ await this.saveState(state);
27
+ this.storyState.next(state);
28
+ }
29
+ async updateState(update) {
30
+ const oldState = (await this.loadState()) ?? this.storyState.value;
31
+ let newState = oldState;
32
+ if (typeof update === "function") {
33
+ newState = update(oldState);
34
+ }
35
+ else if (typeof update === "object") {
36
+ newState = { ...oldState, ...update };
37
+ }
38
+ this.setState(newState);
39
+ }
40
+ async setChapter(string) {
41
+ this.updateState((state) => ({ ...state, currentChapter: string }));
42
+ }
43
+ async nextChapter() {
44
+ const chapter = this.currentChapter.value;
45
+ if (!chapter)
46
+ return null;
47
+ if (chapter.nextChapter === null) {
48
+ return this.endStory();
49
+ }
50
+ if (typeof chapter.nextChapter === "string") {
51
+ return this.setChapter(chapter.nextChapter);
52
+ }
53
+ if (typeof chapter.nextChapter === "function") {
54
+ const storyState = this.storyState.value;
55
+ const string = await chapter.nextChapter(storyState);
56
+ this.setChapter(string);
57
+ }
58
+ throw new Error(`Invalid nextChapter type in chapter ${chapter.id}`);
59
+ }
60
+ endStory() {
61
+ this.end.next();
62
+ }
63
+ async loadState() {
64
+ try {
65
+ const stateData = await this.localStorage.get(this.stateStorageKey, this.options.validateState);
66
+ if (!stateData)
67
+ return null;
68
+ return stateData;
69
+ }
70
+ catch (error) {
71
+ console.error("Story state is invalid", error);
72
+ return null;
73
+ }
74
+ }
75
+ async saveState(state) {
76
+ await this.localStorage.set(this.stateStorageKey, state);
77
+ }
78
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@audiowalk/sdk",
3
- "version": "1.2.2",
3
+ "version": "1.3.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/audiowalk-cz/components.git"
@@ -12,8 +12,9 @@
12
12
  ],
13
13
  "type": "module",
14
14
  "scripts": {
15
- "dev": "tsc -w",
15
+ "dev": "npm run build:watch",
16
16
  "build": "tsc",
17
+ "build:watch": "tsc -w",
17
18
  "prepublishOnly": "npm run build",
18
19
  "release:patch": "git switch master && npm version patch && git switch release && git merge master --ff-only && git push --follow-tags && git switch master && git push",
19
20
  "release:minor": "git switch master && npm version minor && git switch release && git merge master --ff-only && git push --follow-tags && git switch master && git push",