@applicaster/zapp-react-native-utils 16.0.0-alpha.4416921324 → 16.0.0-alpha.4635728545
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/actionsExecutor/ActionExecutor.ts +50 -3
- package/actionsExecutor/ActionExecutorContext.tsx +99 -17
- package/actionsExecutor/__tests__/ActionExecutor.test.ts +71 -0
- package/actionsExecutor/__tests__/feedDecorator.test.ts +61 -0
- package/actionsExecutor/actions/__tests__/dismissBottomSheet.test.ts +25 -0
- package/actionsExecutor/actions/__tests__/goBack.test.ts +62 -0
- package/actionsExecutor/actions/__tests__/goHome.test.ts +19 -0
- package/actionsExecutor/actions/__tests__/loadItemsFromSource.test.ts +88 -0
- package/actionsExecutor/actions/__tests__/navigateToScreen.test.ts +133 -0
- package/actionsExecutor/actions/__tests__/openBottomSheet.customContent.test.ts +76 -0
- package/actionsExecutor/actions/__tests__/openBottomSheet.inlineItems.test.ts +300 -0
- package/actionsExecutor/actions/__tests__/presentScreen.test.ts +127 -0
- package/actionsExecutor/actions/__tests__/showAlert.test.ts +49 -0
- package/actionsExecutor/actions/__tests__/showToast.test.ts +88 -0
- package/actionsExecutor/actions/dismissBottomSheet.ts +23 -0
- package/actionsExecutor/actions/goBack.ts +60 -0
- package/actionsExecutor/actions/goHome.ts +31 -0
- package/actionsExecutor/actions/index.ts +12 -0
- package/actionsExecutor/actions/navigateToScreen.ts +18 -4
- package/actionsExecutor/actions/openBottomSheet.ts +338 -0
- package/actionsExecutor/actions/presentScreen.ts +78 -0
- package/actionsExecutor/actions/refreshComponent.ts +6 -0
- package/actionsExecutor/actions/sendCloudEvent.ts +6 -1
- package/actionsExecutor/actions/showAlert.ts +51 -0
- package/actionsExecutor/actions/showToast.ts +64 -8
- package/actionsExecutor/consts.ts +27 -0
- package/actionsExecutor/feedDecorator.ts +6 -6
- package/analyticsUtils/PlayerAnalyticsManager.ts +1 -1
- package/appUtils/HooksManager/index.ts +9 -0
- package/appUtils/playerManager/OverlayObserver/OverlaysObserver.ts +142 -59
- package/appUtils/playerManager/OverlayObserver/__tests__/getUpcomingQueue.test.ts +67 -0
- package/appUtils/playerManager/OverlayObserver/__tests__/liveContent.test.ts +205 -0
- package/appUtils/playerManager/OverlayObserver/__tests__/utils.test.ts +56 -0
- package/appUtils/playerManager/OverlayObserver/getUpcomingQueue.android.tv.ts +4 -0
- package/appUtils/playerManager/OverlayObserver/getUpcomingQueue.ios.tv.ts +4 -0
- package/appUtils/playerManager/OverlayObserver/getUpcomingQueue.ts +24 -0
- package/appUtils/playerManager/OverlayObserver/getUpcomingQueue.web.ts +4 -0
- package/appUtils/playerManager/OverlayObserver/utils.ts +51 -20
- package/appUtils/playerManager/__tests__/playerContent.test.ts +403 -0
- package/appUtils/playerManager/__tests__/playerFactory.test.ts +1 -1
- package/appUtils/playerManager/__tests__/playerNative.test.ts +38 -0
- package/appUtils/playerManager/__tests__/usePlayerContent.test.tsx +64 -0
- package/appUtils/playerManager/{conts.ts → const.ts} +20 -0
- package/appUtils/playerManager/index.ts +1 -1
- package/appUtils/playerManager/player.ts +115 -3
- package/appUtils/playerManager/playerFactory.ts +1 -1
- package/appUtils/playerManager/playerNative.ts +6 -4
- package/appUtils/playerManager/usePlayerContent.tsx +43 -0
- package/appUtils/playerManager/usePlayerControllerSetup.tsx +1 -1
- package/appUtils/playerManager/userLanguagePreference.ts +1 -1
- package/arrayUtils/__tests__/reorderByIds.test.ts +63 -0
- package/arrayUtils/index.ts +62 -0
- package/cellUtils/index.ts +30 -3
- package/configurationUtils/__tests__/manifestKeyParser.test.ts +21 -0
- package/configurationUtils/__tests__/modalBlocksParser.test.ts +269 -0
- package/configurationUtils/manifestKeyParser.ts +50 -10
- package/configurationUtils/modalBlocksParser.ts +214 -0
- package/entryActions/__tests__/buildEntryActions.test.ts +235 -0
- package/entryActions/aliasPresentation.ts +108 -0
- package/entryActions/buildEntryActions.ts +167 -0
- package/entryActions/index.ts +15 -0
- package/entryActions/types.ts +39 -0
- package/manifestUtils/__tests__/player.audioControls.test.js +158 -0
- package/manifestUtils/_internals/index.js +8 -3
- package/manifestUtils/defaultManifestConfigurations/generalContent.js +6 -0
- package/manifestUtils/defaultManifestConfigurations/player.js +330 -1
- package/manifestUtils/index.js +3 -0
- package/manifestUtils/modalBlocks.js +304 -0
- package/modalState/ContentViewModel.ts +113 -0
- package/modalState/EditableCollection.ts +17 -0
- package/modalState/EditableCollectionRegistry.ts +51 -0
- package/modalState/ModalOrchestrator.ts +212 -0
- package/modalState/RemoteEditableCollection.ts +235 -0
- package/modalState/__tests__/ContentViewModel.editable.test.ts +69 -0
- package/modalState/__tests__/ContentViewModel.test.ts +165 -0
- package/modalState/__tests__/EditableCollectionRegistry.test.ts +112 -0
- package/modalState/__tests__/ModalOrchestrator.phase3.test.ts +63 -0
- package/modalState/__tests__/RemoteEditableCollection.test.ts +415 -0
- package/modalState/__tests__/index.test.ts +30 -1
- package/modalState/__tests__/useBottomSheetContent.test.ts +349 -0
- package/modalState/__tests__/useModalStoreState.test.ts +142 -0
- package/modalState/index.ts +35 -83
- package/modalState/store.ts +109 -0
- package/modalState/types.ts +162 -0
- package/modalState/useBottomSheetContent.ts +109 -0
- package/package.json +2 -2
- package/playerUtils/__tests__/contentDataKeys.test.ts +297 -0
- package/playerUtils/__tests__/resolvePlayerActions.test.ts +138 -0
- package/playerUtils/__tests__/resolvePlayerTitleSubtitle.test.ts +180 -0
- package/playerUtils/contentDataKeys.ts +134 -0
- package/playerUtils/index.ts +37 -16
- package/playerUtils/isAudioItem.ts +26 -0
- package/playerUtils/resolvePlayerActions.ts +71 -0
- package/playerUtils/resolvePlayerTitleSubtitle.ts +76 -0
- package/pluginUtils/__tests__/pluginUtils.test.js +32 -0
- package/pluginUtils/index.ts +29 -0
- package/reactHooks/actions/index.ts +67 -2
- package/reactHooks/cell-click/__tests__/index.test.js +64 -0
- package/reactHooks/cell-click/index.ts +21 -14
- package/reactHooks/connection/index.tsx +8 -5
- package/reactHooks/index.ts +2 -0
- package/reactHooks/layout/index.ts +1 -1
- package/reactHooks/navigation/__tests__/index.test.tsx +176 -1
- package/reactHooks/navigation/__tests__/usePresentScreen.test.ts +154 -0
- package/reactHooks/navigation/index.ts +2 -0
- package/reactHooks/navigation/usePresentScreen.ts +157 -0
- package/reactHooks/navigation/useRoute.ts +22 -5
- package/reactHooks/usePluginConfiguration.ts +4 -1
- package/reactHooks/utils/__tests__/index.test.js +22 -2
- package/reactHooks/utils/index.ts +11 -1
- package/uiActionsRegistrator/__tests__/resolveActionIdentifiers.test.ts +93 -0
- package/uiActionsRegistrator/__tests__/subscribe.test.ts +107 -0
- package/uiActionsRegistrator/__tests__/usableActionItems.test.ts +52 -0
- package/uiActionsRegistrator/index.ts +25 -203
- package/uiActionsRegistrator/registry.ts +335 -0
- package/uiActionsRegistrator/resolveActionIdentifiers.ts +100 -0
- package/uiActionsRegistrator/usableActionItems.ts +66 -0
- package/zappFrameworkUtils/__tests__/localStorageHelper.test.ts +146 -0
- package/zappFrameworkUtils/localStorageHelper.ts +19 -15
- package/appUtils/playerManager/usePlayerTitleSummaryOverlay.tsx +0 -56
- package/playerUtils/__tests__/getPlayerActionButtons.test.ts +0 -54
- package/playerUtils/getPlayerActionButtons.ts +0 -17
- /package/reactHooks/actions/__tests__/{index.test.js → index.test.tsx} +0 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { createLogger } from "../logger";
|
|
2
|
+
|
|
3
|
+
import { RegisteredAction } from "./registry";
|
|
4
|
+
|
|
5
|
+
const { log_warning } = createLogger({
|
|
6
|
+
subsystem: "UIActionsRegistry",
|
|
7
|
+
category: "ActionRegistration",
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Identifiers already reported as unusable. This runs on every render of the
|
|
12
|
+
* player overlay, so the warning is emitted once per identifier and forgotten
|
|
13
|
+
* again as soon as that action becomes invokable.
|
|
14
|
+
*/
|
|
15
|
+
const reportedUnusable = new Set<string>();
|
|
16
|
+
|
|
17
|
+
function isInvokableAction(
|
|
18
|
+
item: RegisteredAction | undefined
|
|
19
|
+
): item is RegisteredAction {
|
|
20
|
+
return typeof item?.action?.invokeAction === "function";
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Narrows a resolved action list to what can actually be shown and invoked:
|
|
25
|
+
* anything without a usable `invokeAction` is dropped, and a repeated
|
|
26
|
+
* identifier keeps only its first occurrence. Order is preserved.
|
|
27
|
+
*
|
|
28
|
+
* Both the player overflow and the bottom sheet plugin build their list this
|
|
29
|
+
* way, and the player resolver applies it to `player_action_buttons` too - a
|
|
30
|
+
* hand-typed config string can name the same action twice.
|
|
31
|
+
*/
|
|
32
|
+
export function usableActionItems(
|
|
33
|
+
items: RegisteredAction[]
|
|
34
|
+
): RegisteredAction[] {
|
|
35
|
+
const seen = new Set<string>();
|
|
36
|
+
const result: RegisteredAction[] = [];
|
|
37
|
+
|
|
38
|
+
for (const item of items ?? []) {
|
|
39
|
+
const identifier = item?.identifier;
|
|
40
|
+
|
|
41
|
+
// A duplicate is expected - a config string may name the same action twice
|
|
42
|
+
// - and an action with no identifier cannot be named in a log anyway.
|
|
43
|
+
if (!identifier || seen.has(identifier)) {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (!isInvokableAction(item)) {
|
|
48
|
+
if (!reportedUnusable.has(identifier)) {
|
|
49
|
+
reportedUnusable.add(identifier);
|
|
50
|
+
|
|
51
|
+
log_warning(
|
|
52
|
+
`usableActionItems: dropping action "${identifier}" - its provider returned no invokeAction, so it cannot be shown`,
|
|
53
|
+
{ identifier }
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
reportedUnusable.delete(identifier);
|
|
61
|
+
seen.add(identifier);
|
|
62
|
+
result.push(item);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return result;
|
|
66
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import {
|
|
2
|
+
batchSaveOwnedValues,
|
|
3
|
+
batchRemoveOwnedValues,
|
|
4
|
+
} from "../localStorageHelper";
|
|
5
|
+
import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage";
|
|
6
|
+
|
|
7
|
+
// Mock localStorage
|
|
8
|
+
jest.mock(
|
|
9
|
+
"@applicaster/zapp-react-native-bridge/ZappStorage/LocalStorage",
|
|
10
|
+
() => ({
|
|
11
|
+
localStorage: {
|
|
12
|
+
getItem: jest.fn(),
|
|
13
|
+
setItem: jest.fn(),
|
|
14
|
+
removeItem: jest.fn(),
|
|
15
|
+
},
|
|
16
|
+
})
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
describe("localStorageHelper", () => {
|
|
20
|
+
const ownershipKey = "test_ownership_key";
|
|
21
|
+
const ownershipNamespace = "test_namespace";
|
|
22
|
+
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
jest.clearAllMocks();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe("addOwnedKeys via batchSaveOwnedValues", () => {
|
|
28
|
+
it("should add new keys to existing owned keys", async () => {
|
|
29
|
+
// Setup existing keys in storage
|
|
30
|
+
const existingKeys = {
|
|
31
|
+
namespace1: ["key1"],
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
(localStorage.getItem as jest.Mock).mockResolvedValue(
|
|
35
|
+
JSON.stringify(existingKeys)
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
const newValues = {
|
|
39
|
+
namespace1: { key2: "value2" },
|
|
40
|
+
namespace2: { key3: "value3" },
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
await batchSaveOwnedValues({
|
|
44
|
+
storageValues: newValues,
|
|
45
|
+
ownershipKey,
|
|
46
|
+
ownershipNamespace,
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Verify localStorage.setItem was called with correct updated keys
|
|
50
|
+
// Note: order of keys in array might vary depending on Set implementation, but usually insertion order
|
|
51
|
+
// However, to be safe, we can parse the argument and check contents
|
|
52
|
+
|
|
53
|
+
const lastCall = (localStorage.setItem as jest.Mock).mock.calls.find(
|
|
54
|
+
(call) => call[0] === ownershipKey
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
expect(lastCall).toBeDefined();
|
|
58
|
+
const savedData = JSON.parse(lastCall[1]);
|
|
59
|
+
|
|
60
|
+
expect(savedData.namespace1).toContain("key1");
|
|
61
|
+
expect(savedData.namespace1).toContain("key2");
|
|
62
|
+
expect(savedData.namespace2).toContain("key3");
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it("should handle empty existing keys", async () => {
|
|
66
|
+
(localStorage.getItem as jest.Mock).mockResolvedValue(null);
|
|
67
|
+
|
|
68
|
+
const newValues = {
|
|
69
|
+
namespace1: { key1: "value1" },
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
await batchSaveOwnedValues({
|
|
73
|
+
storageValues: newValues,
|
|
74
|
+
ownershipKey,
|
|
75
|
+
ownershipNamespace,
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
const lastCall = (localStorage.setItem as jest.Mock).mock.calls.find(
|
|
79
|
+
(call) => call[0] === ownershipKey
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
expect(lastCall).toBeDefined();
|
|
83
|
+
const savedData = JSON.parse(lastCall[1]);
|
|
84
|
+
|
|
85
|
+
expect(savedData.namespace1).toEqual(["key1"]);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
describe("removeOwnedKeys via batchRemoveOwnedValues", () => {
|
|
90
|
+
it("should remove keys from owned keys", async () => {
|
|
91
|
+
const existingKeys = {
|
|
92
|
+
namespace1: ["key1", "key2"],
|
|
93
|
+
namespace2: ["key3"],
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
(localStorage.getItem as jest.Mock).mockResolvedValue(
|
|
97
|
+
JSON.stringify(existingKeys)
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
const keysToRemove = {
|
|
101
|
+
namespace1: ["key1"],
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
await batchRemoveOwnedValues({
|
|
105
|
+
storageValues: keysToRemove,
|
|
106
|
+
ownershipKey,
|
|
107
|
+
ownershipNamespace,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
const lastCall = (localStorage.setItem as jest.Mock).mock.calls.find(
|
|
111
|
+
(call) => call[0] === ownershipKey
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
expect(lastCall).toBeDefined();
|
|
115
|
+
const savedData = JSON.parse(lastCall[1]);
|
|
116
|
+
|
|
117
|
+
expect(savedData.namespace1).toEqual(["key2"]);
|
|
118
|
+
expect(savedData.namespace2).toEqual(["key3"]);
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it("should remove namespace if all keys removed", async () => {
|
|
122
|
+
const existingKeys = {
|
|
123
|
+
namespace1: ["key1"],
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
(localStorage.getItem as jest.Mock).mockResolvedValue(
|
|
127
|
+
JSON.stringify(existingKeys)
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
const keysToRemove = {
|
|
131
|
+
namespace1: ["key1"],
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
await batchRemoveOwnedValues({
|
|
135
|
+
storageValues: keysToRemove,
|
|
136
|
+
ownershipKey,
|
|
137
|
+
ownershipNamespace,
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
expect(localStorage.removeItem).toHaveBeenCalledWith(
|
|
141
|
+
ownershipKey,
|
|
142
|
+
ownershipNamespace
|
|
143
|
+
);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
});
|
|
@@ -2,10 +2,10 @@ import { localStorage } from "@applicaster/zapp-react-native-bridge/ZappStorage/
|
|
|
2
2
|
import { isNilOrEmpty } from "../reactUtils/helpers";
|
|
3
3
|
import { parseJsonIfNeeded } from "@applicaster/zapp-react-native-utils/functionUtils";
|
|
4
4
|
import {
|
|
5
|
-
StorageOwnedValues,
|
|
6
5
|
NamespaceValues,
|
|
7
|
-
|
|
6
|
+
StorageOwnedValues,
|
|
8
7
|
StorageValuesToAdd,
|
|
8
|
+
StorageValuesToRemove,
|
|
9
9
|
} from "./types";
|
|
10
10
|
import { Storage } from "@applicaster/zapp-react-native-bridge/ZappStorage/Storage";
|
|
11
11
|
|
|
@@ -43,10 +43,10 @@ function mapOwnedKeysToAdd(
|
|
|
43
43
|
): StorageOwnedValues {
|
|
44
44
|
const mappedData = {};
|
|
45
45
|
|
|
46
|
-
Object.keys(storageValues)
|
|
46
|
+
for (const namespace of Object.keys(storageValues)) {
|
|
47
47
|
const data = storageValues[namespace];
|
|
48
48
|
mappedData[namespace] = Object.keys(data);
|
|
49
|
-
}
|
|
49
|
+
}
|
|
50
50
|
|
|
51
51
|
return mappedData;
|
|
52
52
|
}
|
|
@@ -59,6 +59,8 @@ export async function batchSave(
|
|
|
59
59
|
return false;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
const promises = [];
|
|
63
|
+
|
|
62
64
|
for (const namespace of Object.keys(storageValues)) {
|
|
63
65
|
const namespaceData = storageValues[namespace];
|
|
64
66
|
|
|
@@ -66,10 +68,12 @@ export async function batchSave(
|
|
|
66
68
|
const value = namespaceData[key];
|
|
67
69
|
|
|
68
70
|
if (!isNilOrEmpty(value)) {
|
|
69
|
-
|
|
71
|
+
promises.push(storage.setItem(key, value, namespace));
|
|
70
72
|
}
|
|
71
73
|
}
|
|
72
74
|
}
|
|
75
|
+
|
|
76
|
+
await Promise.all(promises);
|
|
73
77
|
}
|
|
74
78
|
|
|
75
79
|
export async function batchSaveToLocalStorage(
|
|
@@ -82,13 +86,17 @@ export async function batchRemoveFromStorage(
|
|
|
82
86
|
storageValues: StorageValuesToRemove,
|
|
83
87
|
storage: Storage = localStorage
|
|
84
88
|
) {
|
|
89
|
+
const promises = [];
|
|
90
|
+
|
|
85
91
|
for (const namespace of Object.keys(storageValues)) {
|
|
86
92
|
const namespaceData = storageValues[namespace];
|
|
87
93
|
|
|
88
94
|
for (const key of namespaceData) {
|
|
89
|
-
|
|
95
|
+
promises.push(storage.removeItem(key, namespace));
|
|
90
96
|
}
|
|
91
97
|
}
|
|
98
|
+
|
|
99
|
+
await Promise.all(promises);
|
|
92
100
|
}
|
|
93
101
|
|
|
94
102
|
export async function batchRemoveFromLocalStorage(
|
|
@@ -111,12 +119,12 @@ async function addOwnedKeys({
|
|
|
111
119
|
ownershipNamespace
|
|
112
120
|
);
|
|
113
121
|
|
|
114
|
-
Object.keys(newKeys)
|
|
122
|
+
for (const namespace of Object.keys(newKeys)) {
|
|
115
123
|
const newOwnedKeys: string[] = newKeys[namespace];
|
|
116
124
|
const currentKeys = allStoragedOwnedKeys[namespace] || [];
|
|
117
125
|
const combinedSet = new Set([...currentKeys, ...newOwnedKeys]);
|
|
118
126
|
allStoragedOwnedKeys[namespace] = Array.from(combinedSet);
|
|
119
|
-
}
|
|
127
|
+
}
|
|
120
128
|
|
|
121
129
|
const data = JSON.stringify(allStoragedOwnedKeys);
|
|
122
130
|
await localStorage.setItem(ownershipKey, data, ownershipNamespace);
|
|
@@ -136,18 +144,14 @@ async function removeOwnedKeys({
|
|
|
136
144
|
ownershipNamespace
|
|
137
145
|
);
|
|
138
146
|
|
|
139
|
-
Object.keys(toRemoveKeys)
|
|
147
|
+
for (const namespace of Object.keys(toRemoveKeys)) {
|
|
140
148
|
const keysToRemove: string[] = toRemoveKeys[namespace] || [];
|
|
141
149
|
const currentKeys: string[] = currentKeysList[namespace] || [];
|
|
142
150
|
|
|
143
151
|
const storageOwnedSet = new Set(currentKeys);
|
|
144
152
|
const keysToRemoveSet = new Set(keysToRemove);
|
|
145
153
|
|
|
146
|
-
|
|
147
|
-
toBeRemovedSet.forEach(Set.prototype.delete, originalSet);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
removeAll(storageOwnedSet, keysToRemoveSet);
|
|
154
|
+
keysToRemoveSet.forEach((key) => storageOwnedSet.delete(key));
|
|
151
155
|
const newLoginKeys = Array.from(storageOwnedSet);
|
|
152
156
|
|
|
153
157
|
if (isNilOrEmpty(newLoginKeys)) {
|
|
@@ -155,7 +159,7 @@ async function removeOwnedKeys({
|
|
|
155
159
|
} else {
|
|
156
160
|
currentKeysList[namespace] = newLoginKeys;
|
|
157
161
|
}
|
|
158
|
-
}
|
|
162
|
+
}
|
|
159
163
|
|
|
160
164
|
if (isNilOrEmpty(currentKeysList)) {
|
|
161
165
|
await localStorage.removeItem(ownershipKey, ownershipNamespace);
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState } from "react";
|
|
2
|
-
import { OverlaysObserver } from "./OverlayObserver/OverlaysObserver";
|
|
3
|
-
import { useFeedLoader } from "../../reactHooks";
|
|
4
|
-
import { usePlayer } from "./usePlayer";
|
|
5
|
-
|
|
6
|
-
const getLiveUrl = (url: string) => {
|
|
7
|
-
// Use the replace method with a regular expression to replace all instances of subClass with livePage
|
|
8
|
-
return url.replace(new RegExp("subClass", "g"), "livePage");
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
export const useTitleSummaryOverlay = (
|
|
12
|
-
entry,
|
|
13
|
-
isLive = false,
|
|
14
|
-
interval: number
|
|
15
|
-
) => {
|
|
16
|
-
// TODO: Have generic place for live url from configuration. Currently its hardcoded for client.
|
|
17
|
-
const feedUrl = getLiveUrl(entry?.extensions?.live?.channel_src ?? "");
|
|
18
|
-
const player = usePlayer();
|
|
19
|
-
const [title, setTitle] = useState<string | number>(entry?.title || "");
|
|
20
|
-
const [summary, setSummary] = useState<string | number>(entry?.summary || "");
|
|
21
|
-
|
|
22
|
-
// Hook to load feed data
|
|
23
|
-
const { data: feedData, reloadData } = useFeedLoader({ feedUrl });
|
|
24
|
-
|
|
25
|
-
useEffect(() => {
|
|
26
|
-
if (player && feedUrl && isLive) {
|
|
27
|
-
const observer = new OverlaysObserver({ player });
|
|
28
|
-
|
|
29
|
-
observer.setFeedDataHandlers(feedUrl, reloadData, interval, (entry) => {
|
|
30
|
-
setTitle(entry?.title || "");
|
|
31
|
-
setSummary(entry?.summary || "");
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
const subscription = observer
|
|
35
|
-
.getTitleSummaryObservable()
|
|
36
|
-
.subscribe(({ title, summary }) => {
|
|
37
|
-
setTitle(title);
|
|
38
|
-
setSummary(summary);
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
return () => {
|
|
42
|
-
subscription.unsubscribe();
|
|
43
|
-
observer.clearFeedDataInterval();
|
|
44
|
-
};
|
|
45
|
-
}
|
|
46
|
-
}, [player, feedUrl, reloadData, isLive]);
|
|
47
|
-
|
|
48
|
-
useEffect(() => {
|
|
49
|
-
if (isLive && feedData?.entry?.[0]) {
|
|
50
|
-
setTitle(feedData.entry[0].title || "");
|
|
51
|
-
setSummary(feedData.entry[0].summary || "");
|
|
52
|
-
}
|
|
53
|
-
}, [feedData]);
|
|
54
|
-
|
|
55
|
-
return { title, summary };
|
|
56
|
-
};
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { getPlayerActionButtons } from "../getPlayerActionButtons";
|
|
2
|
-
import { selectActionButtons } from "../../conf/player/selectors";
|
|
3
|
-
|
|
4
|
-
jest.mock("../../conf/player/selectors", () => ({
|
|
5
|
-
selectActionButtons: jest.fn(),
|
|
6
|
-
}));
|
|
7
|
-
|
|
8
|
-
describe("getPlayerActionButtons", () => {
|
|
9
|
-
afterEach(() => {
|
|
10
|
-
jest.clearAllMocks();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it("returns an empty array if selectActionButtons returns undefined", () => {
|
|
14
|
-
(selectActionButtons as jest.Mock).mockReturnValue(undefined);
|
|
15
|
-
const result = getPlayerActionButtons({});
|
|
16
|
-
expect(result).toEqual([]);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it("returns an empty array if selectActionButtons returns null", () => {
|
|
20
|
-
(selectActionButtons as jest.Mock).mockReturnValue(null);
|
|
21
|
-
const result = getPlayerActionButtons({});
|
|
22
|
-
expect(result).toEqual([]);
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it("returns an empty array if selectActionButtons returns empty string", () => {
|
|
26
|
-
(selectActionButtons as jest.Mock).mockReturnValue("");
|
|
27
|
-
const result = getPlayerActionButtons({});
|
|
28
|
-
expect(result).toEqual([]);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it("returns the first two trimmed action buttons", () => {
|
|
32
|
-
(selectActionButtons as jest.Mock).mockReturnValue(" play , pause , stop ");
|
|
33
|
-
const result = getPlayerActionButtons({});
|
|
34
|
-
expect(result).toEqual(["play", "pause"]);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it("returns only one button if only one is present", () => {
|
|
38
|
-
(selectActionButtons as jest.Mock).mockReturnValue(" play ");
|
|
39
|
-
const result = getPlayerActionButtons({});
|
|
40
|
-
expect(result).toEqual(["play"]);
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
it("trims whitespace from button names", () => {
|
|
44
|
-
(selectActionButtons as jest.Mock).mockReturnValue(" play , pause ");
|
|
45
|
-
const result = getPlayerActionButtons({});
|
|
46
|
-
expect(result).toEqual(["play", "pause"]);
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
it("returns an empty array if selectActionButtons returns only commas", () => {
|
|
50
|
-
(selectActionButtons as jest.Mock).mockReturnValue(" , , ");
|
|
51
|
-
const result = getPlayerActionButtons({});
|
|
52
|
-
expect(result).toEqual(["", ""]);
|
|
53
|
-
});
|
|
54
|
-
});
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { map, take, trim } from "../utils";
|
|
2
|
-
import { selectActionButtons } from "../conf/player/selectors";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Returns the first two action buttons from the configuration.
|
|
6
|
-
* @param {Object} configuration - The player configuration object.
|
|
7
|
-
* @returns {Array} An array containing the first two action buttons.
|
|
8
|
-
*/
|
|
9
|
-
export const getPlayerActionButtons = (configuration: any) => {
|
|
10
|
-
const buttonsString = selectActionButtons(configuration);
|
|
11
|
-
|
|
12
|
-
if (!buttonsString) {
|
|
13
|
-
return [];
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
return take(2, map(buttonsString.split(","), trim));
|
|
17
|
-
};
|
|
File without changes
|