@audiowalk/sdk 1.3.0 → 1.4.0
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 +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/player/player-controller.d.ts +2 -1
- package/dist/player/player-controller.d.ts.map +1 -1
- package/dist/player/player-controller.js +10 -6
- package/dist/storage/local-storage.d.ts +2 -1
- package/dist/storage/local-storage.d.ts.map +1 -1
- package/dist/storage/local-storage.js +26 -3
- package/dist/story/story-controller.d.ts +39 -0
- package/dist/story/story-controller.d.ts.map +1 -0
- package/dist/story/story-controller.js +81 -0
- package/package.json +3 -2
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -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
|
@@ -17,11 +17,12 @@ export declare class PlayerController {
|
|
|
17
17
|
readonly currentTime: BehaviorSubject<number>;
|
|
18
18
|
readonly totalTime: BehaviorSubject<number>;
|
|
19
19
|
readonly progress: import("rxjs").Observable<number>;
|
|
20
|
+
private trackId;
|
|
20
21
|
readonly status: BehaviorSubject<PlayerStatus | null>;
|
|
21
22
|
readonly playing: import("rxjs").Observable<boolean>;
|
|
22
23
|
private localStorage;
|
|
23
24
|
constructor(playerElement: HTMLAudioElement, options?: PlayerControllerOptions);
|
|
24
|
-
open(file: string): Promise<void>;
|
|
25
|
+
open(id: string, file: string): Promise<void>;
|
|
25
26
|
setMetadata(metadata: MediaMetadataInit): void;
|
|
26
27
|
close(): void;
|
|
27
28
|
play(): void;
|
|
@@ -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;
|
|
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;IAmBf,OAAO,CAAC,QAAQ,CAAC,aAAa;IAAoB,OAAO,CAAC,OAAO;IAlB7E,SAAgB,MAAM,gBAAuB;IAC7C,SAAgB,OAAO,gBAAuB;IAC9C,SAAgB,MAAM,gBAAuB;IAE7C,SAAgB,WAAW,0BAAkC;IAC7D,SAAgB,SAAS,0BAAkC;IAC3D,SAAgB,QAAQ,oCAEtB;IAEF,OAAO,CAAC,OAAO,CAAuB;IAEtC,SAAgB,MAAM,uCAAkD;IAExE,SAAgB,OAAO,qCAA2D;IAElF,OAAO,CAAC,YAAY,CAAsB;gBAEb,aAAa,EAAE,gBAAgB,EAAU,OAAO,GAAE,uBAA4B;IAoErG,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAUnC,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"}
|
|
@@ -15,6 +15,7 @@ export class PlayerController {
|
|
|
15
15
|
currentTime = new BehaviorSubject(0);
|
|
16
16
|
totalTime = new BehaviorSubject(0);
|
|
17
17
|
progress = combineLatest([this.currentTime, this.totalTime]).pipe(map(([currentTime, totalTime]) => currentTime / totalTime));
|
|
18
|
+
trackId = null;
|
|
18
19
|
status = new BehaviorSubject(null);
|
|
19
20
|
playing = this.status.pipe(map((status) => status === "playing"));
|
|
20
21
|
localStorage = new LocalStorage();
|
|
@@ -74,14 +75,17 @@ export class PlayerController {
|
|
|
74
75
|
if (this.playerElement.duration) {
|
|
75
76
|
this.totalTime.next(this.playerElement.duration);
|
|
76
77
|
}
|
|
77
|
-
|
|
78
|
+
if (this.options.autoSave) {
|
|
79
|
+
this.savePosition(this.playerElement.currentTime);
|
|
80
|
+
}
|
|
78
81
|
});
|
|
79
82
|
}
|
|
80
|
-
async open(file) {
|
|
83
|
+
async open(id, file) {
|
|
84
|
+
this.trackId = id;
|
|
81
85
|
this.playerElement.src = file;
|
|
82
|
-
const position = await this.localStorage.get(`progress-${this.
|
|
86
|
+
const position = await this.localStorage.get(`progress-${this.trackId}`, (value) => typeof value === "number");
|
|
83
87
|
if (position && this.options.autoSave)
|
|
84
|
-
this.playerElement.currentTime =
|
|
88
|
+
this.playerElement.currentTime = position;
|
|
85
89
|
if (this.options.playOnInit)
|
|
86
90
|
await this.playerElement.play();
|
|
87
91
|
}
|
|
@@ -90,7 +94,7 @@ export class PlayerController {
|
|
|
90
94
|
}
|
|
91
95
|
close() {
|
|
92
96
|
this.playerElement.pause();
|
|
93
|
-
this.playerElement.src = "";
|
|
97
|
+
// this.playerElement.src = "";
|
|
94
98
|
navigator.mediaSession.setActionHandler("play", null);
|
|
95
99
|
navigator.mediaSession.setActionHandler("pause", null);
|
|
96
100
|
navigator.mediaSession.setActionHandler("previoustrack", null);
|
|
@@ -132,7 +136,7 @@ export class PlayerController {
|
|
|
132
136
|
async savePosition(currentTime) {
|
|
133
137
|
if (!this.playerElement.src)
|
|
134
138
|
return;
|
|
135
|
-
await this.localStorage.set(`progress-${this.
|
|
139
|
+
await this.localStorage.set(`progress-${this.trackId}`, currentTime);
|
|
136
140
|
}
|
|
137
141
|
log(message) {
|
|
138
142
|
const time = this.playerElement?.currentTime ? Math.round(this.playerElement?.currentTime) : null;
|
|
@@ -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<
|
|
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;
|
|
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
|
-
|
|
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
|
-
|
|
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,39 @@
|
|
|
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
|
+
resetStory(): Promise<void>;
|
|
35
|
+
endStory(): void;
|
|
36
|
+
private loadState;
|
|
37
|
+
private saveState;
|
|
38
|
+
}
|
|
39
|
+
//# 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;IAuBX,UAAU;IAIhB,QAAQ;YAIM,SAAS;YAaT,SAAS;CAGxB"}
|
|
@@ -0,0 +1,81 @@
|
|
|
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
|
+
async resetStory() {
|
|
61
|
+
await this.setState(this.story.initialState);
|
|
62
|
+
}
|
|
63
|
+
endStory() {
|
|
64
|
+
this.end.next();
|
|
65
|
+
}
|
|
66
|
+
async loadState() {
|
|
67
|
+
try {
|
|
68
|
+
const stateData = await this.localStorage.get(this.stateStorageKey, this.options.validateState);
|
|
69
|
+
if (!stateData)
|
|
70
|
+
return null;
|
|
71
|
+
return stateData;
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
console.error("Story state is invalid", error);
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async saveState(state) {
|
|
79
|
+
await this.localStorage.set(this.stateStorageKey, state);
|
|
80
|
+
}
|
|
81
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@audiowalk/sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
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": "
|
|
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",
|