@media-quest/engine 0.0.9 → 0.0.11
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/public-api.js +3 -3
- package/dist/public-api.mjs +3 -3
- package/package.json +1 -1
- package/src/dto/DElement.dto.ts +20 -24
- package/src/services/sequence-manager.ts +100 -99
- package/src/utils/ID.ts +2 -2
package/package.json
CHANGED
package/src/dto/DElement.dto.ts
CHANGED
|
@@ -1,50 +1,46 @@
|
|
|
1
1
|
import { DStyle } from "../Delement/DStyle";
|
|
2
2
|
import { DEventHandler, QueryChangedHandler } from "../event-handlers/DEventHandler";
|
|
3
3
|
import { DCommand } from "../commands/DCommand";
|
|
4
|
-
|
|
5
|
-
// export interface CanBlockMedia {
|
|
6
|
-
// readonly isMediaBlocking:
|
|
7
|
-
// }
|
|
8
4
|
export type DElementDto = DTextDto | DImgDto | DDivDto;
|
|
9
5
|
|
|
10
6
|
interface DStateListener {
|
|
11
|
-
|
|
7
|
+
readonly onStateChange?: ReadonlyArray<QueryChangedHandler>;
|
|
12
8
|
}
|
|
13
9
|
|
|
14
10
|
export interface DElementBaseDto extends DStateListener {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
readonly id: string;
|
|
12
|
+
readonly style: Partial<DStyle>;
|
|
13
|
+
readonly eventHandlers?: ReadonlyArray<DEventHandler>;
|
|
14
|
+
readonly onClick?: ReadonlyArray<DCommand>;
|
|
19
15
|
}
|
|
20
16
|
|
|
21
17
|
export interface DTextDto extends DElementBaseDto {
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
readonly _tag: "p";
|
|
19
|
+
readonly text: string;
|
|
24
20
|
}
|
|
25
21
|
|
|
26
22
|
export interface DDivDto extends DElementBaseDto {
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
readonly _tag: "div";
|
|
24
|
+
readonly children: Array<DTextDto | DImgDto>;
|
|
29
25
|
}
|
|
30
26
|
|
|
31
27
|
export interface DImgDto extends DElementBaseDto {
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
readonly _tag: "img";
|
|
29
|
+
readonly url: string;
|
|
34
30
|
}
|
|
35
31
|
|
|
36
32
|
export interface DVideoDto extends DElementBaseDto {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
33
|
+
readonly _tag: "video";
|
|
34
|
+
readonly url: string;
|
|
35
|
+
// readonly mode: "gif" | "autoplay" | "on-demand";
|
|
36
|
+
// readonly isMediaBlocking: boolean;
|
|
41
37
|
}
|
|
42
38
|
|
|
43
39
|
export interface DAudioDto {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
40
|
+
readonly id: string;
|
|
41
|
+
readonly _tag: "audio";
|
|
42
|
+
readonly url: string;
|
|
43
|
+
// readonly eventHandlers: ReadonlyArray<DEventHandler>;
|
|
48
44
|
|
|
49
|
-
|
|
45
|
+
// readonly isMediaBlocking: boolean;
|
|
50
46
|
}
|
|
@@ -1,132 +1,133 @@
|
|
|
1
1
|
import { DTimestamp } from "../common/DTimestamp";
|
|
2
2
|
|
|
3
3
|
export interface DelayTask {
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
readonly kind: "delay-task";
|
|
5
|
+
readonly duration: number;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
8
|
export interface NoopTask {
|
|
9
|
-
|
|
9
|
+
readonly kind: "noop-task";
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export interface AudioTask {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
readonly kind: "autoplay-audio-task";
|
|
14
|
+
readonly url: string;
|
|
15
|
+
readonly audioId: string;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export interface VideoTask {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
readonly kind: "autoplay-video-task";
|
|
20
|
+
readonly url: string;
|
|
21
|
+
readonly videoId: string;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
export type AutoplayTask = VideoTask | AudioTask | DelayTask;
|
|
25
25
|
type TaskHistory = {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
readonly startedAt: DTimestamp;
|
|
27
|
+
readonly completedAt: DTimestamp;
|
|
28
|
+
readonly task: AutoplayTask;
|
|
29
29
|
};
|
|
30
30
|
class SequenceHistory {
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
private taskHistory: Array<TaskHistory> = [];
|
|
32
|
+
constructor(private readonly startedAt: DTimestamp) {}
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
add(task: TaskHistory) {
|
|
35
|
+
this.taskHistory.push(task);
|
|
36
|
+
}
|
|
37
37
|
}
|
|
38
|
+
|
|
38
39
|
export class SequenceManager {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
40
|
+
private runningTask: { task: AutoplayTask; startedAt: DTimestamp } | false;
|
|
41
|
+
private taskList: Array<DelayTask | AudioTask | VideoTask>;
|
|
42
|
+
private readonly t0: DTimestamp;
|
|
43
|
+
private readonly history: SequenceHistory;
|
|
44
|
+
|
|
45
|
+
constructor(private readonly tasks: ReadonlyArray<AudioTask | DelayTask | VideoTask>) {
|
|
46
|
+
this.t0 = DTimestamp.now();
|
|
47
|
+
const [first, ...rest] = tasks;
|
|
48
|
+
if (first && first.kind === "delay-task") {
|
|
49
|
+
this.runningTask = { task: first, startedAt: this.t0 };
|
|
50
|
+
this.taskList = [...rest];
|
|
51
|
+
} else {
|
|
52
|
+
this.runningTask = false;
|
|
53
|
+
this.taskList = [...tasks];
|
|
54
|
+
}
|
|
55
|
+
this.history = new SequenceHistory(this.t0);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
audioCompleted(audio: { audioId: string; url: string }) {
|
|
59
|
+
const curr = this.runningTask;
|
|
60
|
+
if (curr && curr.task.kind === "autoplay-audio-task") {
|
|
61
|
+
const { audioId, url } = curr.task;
|
|
62
|
+
if (url === audio.url) {
|
|
63
|
+
this.runningTask = false;
|
|
64
|
+
} else {
|
|
65
|
+
// WARN ABOUT UNEXPECTED AUDIO ID && URL ??
|
|
66
|
+
console.warn("Unexpected audio completed url.");
|
|
67
|
+
}
|
|
55
68
|
}
|
|
69
|
+
}
|
|
56
70
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
71
|
+
videoCompleted(video: { videoId: string; url: string }) {
|
|
72
|
+
const curr = this.runningTask;
|
|
73
|
+
if (curr && curr.task.kind === "autoplay-video-task") {
|
|
74
|
+
const { url } = curr.task;
|
|
75
|
+
if (url === video.url) {
|
|
76
|
+
this.runningTask = false;
|
|
77
|
+
} else {
|
|
78
|
+
// WARN ABOUT UNEXPECTED AUDIO ID && URL ??
|
|
79
|
+
console.warn("Unexpected video completed url.");
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
abort() {
|
|
85
|
+
this.taskList = [];
|
|
86
|
+
this.runningTask = false;
|
|
87
|
+
}
|
|
88
|
+
get isCompleted() {
|
|
89
|
+
return !this.isRunning;
|
|
90
|
+
}
|
|
91
|
+
get isRunning() {
|
|
92
|
+
return this.runningTask || this.taskList.length;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
nextTask(now: DTimestamp): NoopTask | AudioTask | VideoTask {
|
|
96
|
+
const curr = this.runningTask;
|
|
97
|
+
|
|
98
|
+
if (curr && curr.task.kind === "delay-task") {
|
|
99
|
+
const progress = DTimestamp.diff(curr.startedAt, now);
|
|
100
|
+
// DELAY COMPLETED.
|
|
101
|
+
if (progress >= curr.task.duration) {
|
|
102
|
+
this.runningTask = false;
|
|
103
|
+
}
|
|
68
104
|
}
|
|
69
105
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const { url } = curr.task;
|
|
74
|
-
if (url === video.url) {
|
|
75
|
-
this.runningTask = false;
|
|
76
|
-
} else {
|
|
77
|
-
// WARN ABOUT UNEXPECTED AUDIO ID && URL ??
|
|
78
|
-
console.warn("Unexpected video completed url.");
|
|
79
|
-
}
|
|
80
|
-
}
|
|
106
|
+
// RETURN IF A TASK IS RUNNING.
|
|
107
|
+
if (this.runningTask) {
|
|
108
|
+
return { kind: "noop-task" };
|
|
81
109
|
}
|
|
82
110
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
111
|
+
const first = this.taskList.shift();
|
|
112
|
+
if (!first) {
|
|
113
|
+
return { kind: "noop-task" };
|
|
86
114
|
}
|
|
87
|
-
|
|
88
|
-
|
|
115
|
+
|
|
116
|
+
if (first.kind === "delay-task") {
|
|
117
|
+
this.runningTask = { task: first, startedAt: now };
|
|
118
|
+
return { kind: "noop-task" };
|
|
89
119
|
}
|
|
90
|
-
|
|
91
|
-
|
|
120
|
+
|
|
121
|
+
if (first.kind === "autoplay-video-task") {
|
|
122
|
+
this.runningTask = { task: first, startedAt: now };
|
|
123
|
+
return first;
|
|
92
124
|
}
|
|
93
125
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (curr && curr.task.kind === "delay-task") {
|
|
98
|
-
const progress = DTimestamp.diff(curr.startedAt, now);
|
|
99
|
-
// DELAY COMPLETED.
|
|
100
|
-
if (progress >= curr.task.duration) {
|
|
101
|
-
this.runningTask = false;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// RETURN IF A TASK IS RUNNING.
|
|
106
|
-
if (this.runningTask) {
|
|
107
|
-
return { kind: "noop-task" };
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
const first = this.taskList.shift();
|
|
111
|
-
if (!first) {
|
|
112
|
-
return { kind: "noop-task" };
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
if (first.kind === "delay-task") {
|
|
116
|
-
this.runningTask = { task: first, startedAt: now };
|
|
117
|
-
return { kind: "noop-task" };
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (first.kind === "autoplay-video-task") {
|
|
121
|
-
this.runningTask = { task: first, startedAt: now };
|
|
122
|
-
return first;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (first.kind === "autoplay-audio-task") {
|
|
126
|
-
this.runningTask = { task: first, startedAt: now };
|
|
127
|
-
return first;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return { kind: "noop-task" };
|
|
126
|
+
if (first.kind === "autoplay-audio-task") {
|
|
127
|
+
this.runningTask = { task: first, startedAt: now };
|
|
128
|
+
return first;
|
|
131
129
|
}
|
|
130
|
+
|
|
131
|
+
return { kind: "noop-task" };
|
|
132
|
+
}
|
|
132
133
|
}
|
package/src/utils/ID.ts
CHANGED
|
@@ -11,7 +11,7 @@ const isID = <const B extends string>(idName: B, id?: string): id is ID<B> => {
|
|
|
11
11
|
return id.length >= MIN_LENGTH;
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
-
const
|
|
14
|
+
const createIDByName = <const B extends string>(idName: B): ID<B> => {
|
|
15
15
|
const letters = "abcdefghijklmnopqrstuvyz";
|
|
16
16
|
const all = letters + letters.toUpperCase();
|
|
17
17
|
let result = "";
|
|
@@ -30,7 +30,7 @@ export const createTypedIdSingleton = <const B extends string>(idName: B) => {
|
|
|
30
30
|
/**
|
|
31
31
|
* Creates a new ID of the correct type
|
|
32
32
|
*/
|
|
33
|
-
const create = (): ID<B> =>
|
|
33
|
+
const create = (): ID<B> => createIDByName(idName);
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
36
|
* Checks if the id is of the correct type
|