@oxymoron.13/tizentube-s95b 0.2.1 → 0.2.2

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.
Files changed (84) hide show
  1. package/README.md +42 -49
  2. package/S95B-CHANGES.txt +3 -9
  3. package/dist/userScript.js +2 -2
  4. package/package.json +5 -11
  5. package/UPSTREAM-README.md +0 -42
  6. package/mods/config.js +0 -117
  7. package/mods/domrect-polyfill.js +0 -104
  8. package/mods/features/adblock.js +0 -584
  9. package/mods/features/autoFrameRate.js +0 -42
  10. package/mods/features/enableFeatures.js +0 -19
  11. package/mods/features/moreSubtitles.js +0 -378
  12. package/mods/features/pictureInPicture.js +0 -198
  13. package/mods/features/preferredVideoQuality.js +0 -101
  14. package/mods/features/s95bCodec.js +0 -45
  15. package/mods/features/s95bI18n.js +0 -36
  16. package/mods/features/s95bMenu.js +0 -246
  17. package/mods/features/sponsorblock.js +0 -437
  18. package/mods/features/standaloneUserscript.js +0 -107
  19. package/mods/features/updater.js +0 -119
  20. package/mods/features/userAgentSpoofing.js +0 -73
  21. package/mods/features/videoQueuing.js +0 -64
  22. package/mods/package-lock.json +0 -2321
  23. package/mods/package.json +0 -33
  24. package/mods/resolveCommand.js +0 -376
  25. package/mods/rollup.config.js +0 -41
  26. package/mods/spatial-navigation-polyfill.js +0 -1756
  27. package/mods/tiny-sha256.js +0 -99
  28. package/mods/translations/i18nResources.js +0 -11
  29. package/mods/translations/index.js +0 -18
  30. package/mods/translations/language-names.js +0 -981
  31. package/mods/translations/resources/ar.json +0 -308
  32. package/mods/translations/resources/az.json +0 -308
  33. package/mods/translations/resources/bs.json +0 -308
  34. package/mods/translations/resources/cs.json +0 -308
  35. package/mods/translations/resources/de.json +0 -308
  36. package/mods/translations/resources/dk.json +0 -308
  37. package/mods/translations/resources/el.json +0 -308
  38. package/mods/translations/resources/en.json +0 -308
  39. package/mods/translations/resources/es-419.json +0 -308
  40. package/mods/translations/resources/es.json +0 -308
  41. package/mods/translations/resources/fi-FI.json +0 -308
  42. package/mods/translations/resources/fr.json +0 -311
  43. package/mods/translations/resources/hr.json +0 -308
  44. package/mods/translations/resources/hu.json +0 -308
  45. package/mods/translations/resources/id.json +0 -308
  46. package/mods/translations/resources/it.json +0 -308
  47. package/mods/translations/resources/ja.json +0 -308
  48. package/mods/translations/resources/lt.json +0 -308
  49. package/mods/translations/resources/lv.json +0 -308
  50. package/mods/translations/resources/pl.json +0 -308
  51. package/mods/translations/resources/pt-BR.json +0 -308
  52. package/mods/translations/resources/pt-PT.json +0 -308
  53. package/mods/translations/resources/ro.json +0 -310
  54. package/mods/translations/resources/ru.json +0 -308
  55. package/mods/translations/resources/sr-Cyrl.json +0 -308
  56. package/mods/translations/resources/sr-Latn.json +0 -308
  57. package/mods/translations/resources/tlh.json +0 -308
  58. package/mods/translations/resources/tr.json +0 -308
  59. package/mods/translations/resources/uk.json +0 -308
  60. package/mods/translations/resources/vi.json +0 -309
  61. package/mods/translations/resources/zh-CN.json +0 -308
  62. package/mods/translations/resources/zh-TW.json +0 -308
  63. package/mods/translations/update-translations.js +0 -55
  64. package/mods/ui/chapters.js +0 -137
  65. package/mods/ui/clock.js +0 -71
  66. package/mods/ui/customCommandExecution.js +0 -49
  67. package/mods/ui/customGuideAction.js +0 -119
  68. package/mods/ui/customUI.js +0 -192
  69. package/mods/ui/customYTSettings.js +0 -29
  70. package/mods/ui/disableWhosWatching.js +0 -48
  71. package/mods/ui/settings.js +0 -1024
  72. package/mods/ui/sidebarModification.js +0 -179
  73. package/mods/ui/speedUI.js +0 -119
  74. package/mods/ui/theme.js +0 -26
  75. package/mods/ui/ui.css +0 -157
  76. package/mods/ui/ui.js +0 -261
  77. package/mods/ui/ytUI.js +0 -510
  78. package/mods/userScript.js +0 -28
  79. package/mods/utils/ASTParser.js +0 -67
  80. package/mods/utils/innerTubeCalls.js +0 -138
  81. package/service/package-lock.json +0 -4193
  82. package/service/package.json +0 -29
  83. package/service/rollup.config.js +0 -47
  84. package/service/service.js +0 -118
@@ -1,137 +0,0 @@
1
- function parseTimestamps(input) {
2
- var lines = input.trim().split('\n');
3
- var result = [];
4
- var timestampRegex = /^\d+:\d{2}/;
5
-
6
- for (var i = 0; i < lines.length; i++) {
7
- var line = lines[i];
8
- var match = line.match(timestampRegex);
9
- if (match) {
10
- var timePart = match[0];
11
- var parts = line.split(' ');
12
- parts.shift();
13
- var timeParts = timePart.split(':');
14
- var minutes = parseInt(timeParts[0], 10);
15
- var seconds = parseInt(timeParts[1], 10);
16
- var milliseconds = (minutes * 60 + seconds) * 1000;
17
- var name = parts.join(' ');
18
- result.push({ time: milliseconds, name: name });
19
- }
20
- }
21
- return result;
22
- }
23
-
24
- function marker(title, start, duration, videoID, i) {
25
- return {
26
- title: {
27
- simpleText: title
28
- },
29
- startMillis: start,
30
- durationMillis: duration,
31
- thumbnailDetails: {
32
- thumbnails: [
33
- {
34
- url: `https://i.ytimg.com/vi/${videoID}/hqdefault.jpg`,
35
- width: 320,
36
- height: 180
37
- }
38
- ]
39
- },
40
- onActive: {
41
- innertubeCommand: {
42
- clickTrackingParams: null,
43
- entityUpdateCommand: {
44
- entityBatchUpdate: {
45
- mutations: [
46
- {
47
- entityKey: `${videoID}${start}${duration}`,
48
- type: 'ENTITY_MUTATION_TYPE_REPLACE',
49
- payload: {
50
- markersEngagementPanelSyncEntity: {
51
- key: `${videoID}${start}${duration}`,
52
- panelId: 'engagement-panel-macro-markers-description-chapters',
53
- activeItemIndex: i,
54
- syncEnabled: true
55
- }
56
- }
57
- }
58
- ]
59
- }
60
- }
61
- }
62
- }
63
- }
64
- }
65
-
66
- function markerEntity(videoID, markers) {
67
- return {
68
- entityKey: `${videoID}-key`,
69
- type: 'ENTITY_MUTATION_TYPE_REPLACE',
70
- payload: {
71
- macroMarkersListEntity: {
72
- key: `${videoID}-key`,
73
- externalVideoId: videoID,
74
- markersList: {
75
- markerType: 'MARKER_TYPE_CHAPTERS',
76
- markers: markers,
77
- headerTitle: {
78
- runs: [
79
- {
80
- text: 'Chapters'
81
- }
82
- ]
83
- },
84
- onTap: {
85
- innertubeCommand: {
86
- clickTrackingParams: null,
87
- changeEngagementPanelVisibilityAction: {
88
- targetId: 'engagement-panel-macro-markers-description-chapters',
89
- visibility: 'ENGAGEMENT_PANEL_VISIBILITY_EXPANDED'
90
- }
91
- }
92
- },
93
- markersEdu: {
94
- enterNudgeText: {
95
- runs: [
96
- {
97
- text: 'To view chapters, press the up arrow button'
98
- }
99
- ]
100
- },
101
- enterNudgeA11yText: 'To view chapters, press the up arrow button',
102
- navNudgeText: {
103
- runs: [
104
- {
105
- text: 'Navigate between chapters'
106
- }
107
- ]
108
- },
109
- navNudgeA11yText: 'Press the left or right arrow button to navigate between chapters'
110
- },
111
- loggingDirectives: {
112
- trackingParams: null,
113
- enableDisplayloggerExperiment: true
114
- }
115
- }
116
- }
117
- }
118
- }
119
- }
120
-
121
- export default function Chapters(video) {
122
- const videoID = video.contents.singleColumnWatchNextResults.results.results.contents[0].itemSectionRenderer.contents[0].videoMetadataRenderer.videoId;
123
- const videoDescription = video.contents.singleColumnWatchNextResults.results.results.contents[0].itemSectionRenderer.contents[0].videoMetadataRenderer.description.runs[0].text;
124
- const chapters = parseTimestamps(videoDescription);
125
- const videoDuration = document.getElementsByTagName('video')[0].duration * 1000;
126
- let markers = [];
127
-
128
- for (let i = 0; i < chapters.length; i++) {
129
- const chapter = chapters[i];
130
- const nextChapter = chapters[i + 1];
131
- const duration = nextChapter ? nextChapter.time - chapter.time : videoDuration - chapter.time;
132
- markers.push(marker(chapter.name, String(chapter.time), String(duration), videoID, i));
133
- }
134
-
135
- const markerEntityData = markerEntity(videoID, markers);
136
- return markerEntityData;
137
- }
package/mods/ui/clock.js DELETED
@@ -1,71 +0,0 @@
1
- import { configChangeEmitter, configRead } from '../config.js';
2
-
3
- configChangeEmitter.addEventListener('configChange', (e) => {
4
- if (e.detail.key === 'enableClock') {
5
- toggleClock(e.detail.value);
6
- }
7
- });
8
-
9
- let actualClock;
10
-
11
- function toggleClock(value) {
12
- const existingClock = document.getElementById('tizentube-clock');
13
- if (value && existingClock) return;
14
- if (!value && existingClock) {
15
- existingClock.remove();
16
- return;
17
- }
18
- if (!value && !existingClock) {
19
- return;
20
- } else {
21
- const clock = document.createElement('div');
22
-
23
- clock.id = 'tizentube-clock';
24
- clock.style.height = '45rem';
25
- clock.style.width = '80rem';
26
- clock.style.position = 'absolute';
27
- clock.style.top = '50%';
28
- clock.style.left = '50%';
29
- clock.style.marginTop = '-22.5rem';
30
- clock.style.marginLeft = '-40rem';
31
-
32
- actualClock = document.createElement('div');
33
-
34
- actualClock.style.position = 'absolute';
35
- actualClock.style.zIndex = '9999';
36
- actualClock.style.right = '5%';
37
- actualClock.style.top = '2%';
38
- actualClock.style.fontSize = '1.5em';
39
- clock.appendChild(actualClock);
40
- document.body.appendChild(clock);
41
-
42
- function updateClock() {
43
- const now = new Date();
44
- const is12HourFormat = configRead('isClock12HourFormat');
45
- const secondsEnabled = configRead('clockShowSeconds');
46
- const shouldHideWhenVideoPlaying = configRead('clockHideWhenVideoPlaying');
47
- const ytlrWatchDefault = document.querySelector('ytlr-watch-default');
48
-
49
- if (shouldHideWhenVideoPlaying) {
50
- if (ytlrWatchDefault && ytlrWatchDefault.getAttribute('hybridnavfocusable') === 'true')
51
- actualClock.style.display = 'none';
52
- else actualClock.style.display = 'block';
53
- }
54
-
55
- let hours = now.getHours();
56
- if (is12HourFormat) {
57
- hours = hours % 12 || 12;
58
- }
59
-
60
- hours = hours.toString().padStart(2, '0');
61
- const minutes = now.getMinutes().toString().padStart(2, '0');
62
- const seconds = now.getSeconds().toString().padStart(2, '0');
63
- actualClock.textContent = `${hours}:${minutes}${secondsEnabled ? `:${seconds}` : ''}${is12HourFormat ? (now.getHours() >= 12 ? ' PM' : ' AM') : ''}`;
64
- }
65
-
66
- updateClock();
67
- setInterval(updateClock, 1000);
68
- }
69
- }
70
-
71
- toggleClock(configRead('enableClock'));
@@ -1,49 +0,0 @@
1
- function getCommandExecutor() {
2
- let instance;
3
- let executeFunction;
4
-
5
- for (const key in window._yttv) {
6
- if (window._yttv[key] && window._yttv[key].getInstance) {
7
- if (window._yttv[key].toString().includes('ytlrActionRouter')) instance = window._yttv[key].getInstance();
8
- else {
9
- let isInstance = false;
10
- const tempInstance = window._yttv[key].getInstance();
11
- const keys = Object.getOwnPropertyNames(Object.getPrototypeOf(tempInstance));
12
- for (const key of keys) {
13
- if (typeof tempInstance[key] === 'function' && tempInstance[key].toString().includes('ytlrActionRouter')) {
14
- executeFunction = tempInstance[key];
15
- isInstance = true;
16
- }
17
- }
18
-
19
- if (isInstance) instance = window._yttv[key].getInstance();
20
- }
21
- }
22
- }
23
-
24
- if (!instance) return;
25
-
26
- if (!executeFunction) {
27
- const keys = Object.getOwnPropertyNames(Object.getPrototypeOf(instance));
28
- for (const key of keys) {
29
- if (typeof instance[key] === 'function' && instance[key].toString().includes('ytlrActionRouter')) {
30
- executeFunction = instance[key];
31
- }
32
- }
33
- }
34
-
35
- if (!executeFunction) return;
36
-
37
- let commandFunction;
38
- for (const key in window._yttv) {
39
- if (window._yttv[key] && typeof window._yttv[key] === 'function' && window._yttv[key].toString().includes('this.actionName')) {
40
- commandFunction = window._yttv[key];
41
- }
42
- }
43
- return {
44
- executeFunction: executeFunction.bind(instance),
45
- commandFunction
46
- }
47
- }
48
-
49
- export default getCommandExecutor;
@@ -1,119 +0,0 @@
1
- import { configChangeEmitter, configRead, configWrite } from "../config.js";
2
- import getCommandExecutor from "./customCommandExecution.js";
3
- import { GuideEntryRenderer } from "./ytUI.js";
4
-
5
- const origParse = JSON.parse;
6
- JSON.parse = function () {
7
- const r = origParse.apply(this, arguments);
8
- const guideSection = r.items?.[0]?.guideSectionRenderer;
9
- const order = configRead('sidebarContentsOrder');
10
- if (guideSection && Array.isArray(order)) {
11
- let orderChanged = false;
12
- for (const item of guideSection.items) {
13
- // Not every guide item is a guideEntryRenderer: a throw here would fail
14
- // the caller's JSON.parse and lose the whole guide response.
15
- const itemOrder = item.guideEntryRenderer?.navigationEndpoint?.browseEndpoint?.browseId
16
- || (item.guideEntryRenderer?.navigationEndpoint?.searchEndpoint && 'search');
17
- if (itemOrder && !order.some(orderItem =>
18
- (typeof orderItem === 'object' ? orderItem.browseId : orderItem) === itemOrder)) {
19
- order.push(itemOrder);
20
- orderChanged = true;
21
- }
22
- }
23
- if (orderChanged) configWrite('sidebarContentsOrder', order);
24
- }
25
- if (configRead('sidebarContentsOrder')?.length === 0) {
26
- // Add all of the items in the sidebar to the sidebarContentsOrder
27
- if (r.items && Array.isArray(r.items) && r.items[0].guideSectionRenderer) {
28
- const order = [];
29
- for (const item of r.items[0].guideSectionRenderer.items) {
30
- const browseId = item.guideEntryRenderer?.navigationEndpoint?.browseEndpoint?.browseId;
31
- if (browseId) {
32
- order.push(browseId);
33
- } else if (item.guideEntryRenderer?.navigationEndpoint?.searchEndpoint) {
34
- order.push('search');
35
- }
36
- }
37
- configWrite('sidebarContentsOrder', order);
38
- }
39
- } else {
40
- // Reorder the items based on the sidebarContentsOrder config key
41
-
42
- if (r.items && Array.isArray(r.items) && r.items[0].guideSectionRenderer) {
43
- const order = configRead('sidebarContentsOrder');
44
- const items = r.items[0].guideSectionRenderer.items;
45
- const copiedItems = JSON.parse(JSON.stringify(items));
46
-
47
- for (const orderItem of order) {
48
- if (typeof orderItem === 'object' && orderItem !== null) {
49
- const customItem = GuideEntryRenderer(
50
- orderItem.title,
51
- {
52
- browseEndpoint: {
53
- browseId: orderItem.browseId
54
- }
55
- },
56
- 'PERSON'
57
- );
58
- copiedItems.push(customItem);
59
- }
60
- }
61
-
62
- const orderedItems = [];
63
- const placed = new Set();
64
- for (const orderItem of order) {
65
- const browseId = typeof orderItem === 'object' ? orderItem.browseId : orderItem;
66
- const index = copiedItems.findIndex(item => {
67
- const itemBrowseId = item.guideEntryRenderer?.navigationEndpoint?.browseEndpoint?.browseId;
68
- return itemBrowseId === browseId || (browseId === 'search' && item.guideEntryRenderer?.navigationEndpoint?.searchEndpoint);
69
- });
70
- if (index !== -1) {
71
- orderedItems.push(copiedItems[index]);
72
- placed.add(index);
73
- }
74
- }
75
- // Entries the stored order knows nothing about must survive, after the
76
- // ordered ones. The order is not scoped to a profile: it is learned from
77
- // whichever profile loads first, and only from entries exposing a
78
- // browseEndpoint.browseId. A YouTube Kids profile's guide entries don't,
79
- // so they were neither learned above nor matched here — dropping them
80
- // emptied the whole left menu on that profile (#643, #648).
81
- copiedItems.forEach((item, index) => {
82
- if (!placed.has(index)) orderedItems.push(item);
83
- });
84
- r.items[0].guideSectionRenderer.items = orderedItems;
85
- }
86
- }
87
-
88
- const disabledSidebarContents = configRead('disabledSidebarContents');
89
- const disableChannelsOnSidebar = configRead('disableChannelsOnSidebar');
90
- if (r.items && Array.isArray(r.items) && r.items[0].guideSectionRenderer) {
91
- for (let i = 0; i < r.items.length; i++) {
92
- const section = r.items[i].guideSectionRenderer;
93
- section.originalItems = section.items.slice();
94
- for (let j = 0; j < section.items.length; j++) {
95
- const item = section.items[j].guideEntryRenderer;
96
- if (!item) continue;
97
- if ((disabledSidebarContents?.length &&
98
- disabledSidebarContents.includes(item.navigationEndpoint?.browseEndpoint ?
99
- item.navigationEndpoint.browseEndpoint.browseId :
100
- 'search'))
101
- || (disableChannelsOnSidebar && item?.thumbnail)) {
102
- section.items.splice(j, 1);
103
- j--;
104
- }
105
- }
106
- }
107
- }
108
-
109
- return r;
110
- }
111
-
112
- configChangeEmitter.addEventListener('configChange', (e) => {
113
- if (e.detail.key === 'disabledSidebarContents' || e.detail.key === 'disableChannelsOnSidebar' || e.detail.key === 'sidebarContentsOrder') {
114
- const commandExecutor = getCommandExecutor();
115
- if (commandExecutor) {
116
- commandExecutor.executeFunction(new commandExecutor.commandFunction('reloadGuideAction'));
117
- }
118
- }
119
- });
@@ -1,192 +0,0 @@
1
- // Custom UI for video player
2
-
3
- import { extractAssignedFunctions } from "../utils/ASTParser.js";
4
- import { configRead } from "../config.js";
5
- import { ButtonRenderer } from "./ytUI.js";
6
- import { t } from 'i18next';
7
-
8
- // S95B: result of the AST scan is constant for a given player class, so compute it once.
9
- let s95bFunctions = null;
10
- function applyPatches() {
11
- if (!window._yttv) return setTimeout(applyPatches, 250);
12
- if (!document.querySelector('video')) return setTimeout(applyPatches, 250);
13
- const methods = Object.keys(window._yttv).filter(key => {
14
- return typeof window._yttv[key] === 'function' && window._yttv[key].toString().includes('TRANSPORT_CONTROLS_BUTTON_TYPE_FEATURED_ACTION');
15
- });
16
-
17
- if (methods.length === 0) {
18
- setTimeout(applyPatches, 250);
19
- return;
20
- }
21
-
22
- const origMethod = window._yttv[methods[0]];
23
-
24
- function YtlrPlayerActionsContainer() {
25
- const args = Array.prototype.slice.call(arguments);
26
- const isClass = /^class\s/.test(origMethod.toString());
27
-
28
- function constructAsNew(ctor, argsList) {
29
- if (typeof Reflect !== 'undefined' && typeof Reflect.construct === 'function') {
30
- return Reflect.construct(ctor, argsList, YtlrPlayerActionsContainer);
31
- }
32
- return new origMethod(...argsList);
33
- }
34
-
35
- if (!(this instanceof YtlrPlayerActionsContainer)) {
36
- if (isClass) return constructAsNew(origMethod, args);
37
- return origMethod.apply(this, args);
38
- }
39
-
40
- let inst;
41
- if (isClass) {
42
- inst = constructAsNew(origMethod, args);
43
- } else {
44
- origMethod.apply(this, args);
45
- inst = this;
46
- }
47
-
48
- const functions = s95bFunctions || (s95bFunctions = extractAssignedFunctions(origMethod.toString()));
49
-
50
- const pipCommand = {
51
- "type": "TRANSPORT_CONTROLS_BUTTON_TYPE_PIP",
52
- "button": {
53
- "buttonRenderer": ButtonRenderer(
54
- false,
55
- configRead('enableSwapMPWithPIP') ? t('player.pictureInPicture') : t('player.miniPlayer'),
56
- 'CLEAR_COOKIES',
57
- {
58
- customAction: {
59
- action: configRead('enableSwapMPWithPIP') ? 'ENTER_PIP' : 'ENTER_MP',
60
- }
61
- }
62
- )
63
- }
64
- }
65
-
66
- const settingActionGroup = functions.find(func => {
67
- return func.rhs.includes('TRANSPORT_CONTROLS_BUTTON_TYPE_PLAYBACK_SETTINGS');
68
- }).left.split('.')[1];
69
-
70
- if (!settingActionGroup) return inst;
71
-
72
- const origSettingActionGroup = inst[settingActionGroup];
73
- if (configRead('enableMPButton')) {
74
- inst[settingActionGroup] = function () {
75
- const res = origSettingActionGroup.apply(this, arguments);
76
- const idx = res.findIndex(item => item.type === 'TRANSPORT_CONTROLS_BUTTON_TYPE_PLAYBACK_SETTINGS');
77
- res.find(item => item.type === 'TRANSPORT_CONTROLS_BUTTON_TYPE_PIP') || res.splice(idx, 0, pipCommand);
78
- return res;
79
- };
80
- }
81
-
82
- const previousButtonName = functions.find(func => {
83
- if (func.rhs.includes('skipNextButton')) {
84
- const skipNextButtonIndex = func.rhs.indexOf('skipNextButton');
85
- const skipPreviousButtonIndex = func.rhs.indexOf('skipPreviousButton');
86
- if (skipPreviousButtonIndex > skipNextButtonIndex) {
87
- return true;
88
- }
89
- }
90
- }).left.split('.')[1];
91
-
92
- const nextButtonName = functions.find(func => {
93
- if (func.rhs.includes('skipPreviousButton')) {
94
- const skipNextButtonIndex = func.rhs.indexOf('skipNextButton');
95
- const skipPreviousButtonIndex = func.rhs.indexOf('skipPreviousButton');
96
- if (skipNextButtonIndex > skipPreviousButtonIndex) {
97
- return true;
98
- }
99
- }
100
- }).left.split('.')[1];
101
-
102
- const engagementActionButton = functions.find(func => func.rhs.includes('props.data.engagementActions')).left.split('.')[1];
103
-
104
- if (engagementActionButton && configRead('enableSpeedControlsButton')) {
105
- const origEngagementActionButton = inst[engagementActionButton];
106
- inst[engagementActionButton] = function () {
107
- const res = origEngagementActionButton.apply(this, arguments);
108
- res.find(item => item.type === 'TRANSPORT_CONTROLS_BUTTON_TYPE_SPEED') || res.push({
109
- type: 'TRANSPORT_CONTROLS_BUTTON_TYPE_SPEED',
110
- button: {
111
- buttonRenderer: ButtonRenderer(
112
- false,
113
- t('player.playbackSpeed.button'),
114
- 'SLOW_MOTION_VIDEO',
115
- {
116
- customAction:
117
- {
118
- action: 'TT_SPEED_SETTINGS_SHOW',
119
- }
120
- }
121
- )
122
- }
123
- });
124
- return res;
125
- }
126
- }
127
-
128
- if (!configRead('enableSuperThanksButton')) {
129
- const origEngagementActionButton = inst[engagementActionButton];
130
- inst[engagementActionButton] = function () {
131
- const res = origEngagementActionButton.apply(this, arguments);
132
- const superThanksFiltered = res.filter(item => item.type !== 'TRANSPORT_CONTROLS_BUTTON_TYPE_SUPER_THANKS');
133
- const shoppingFiltered = superThanksFiltered.filter(item => item.type !== 'TRANSPORT_CONTROLS_BUTTON_TYPE_SHOPPING');
134
- return shoppingFiltered;
135
- }
136
- }
137
-
138
- if (!configRead('enableAIAskButton')) {
139
- const origEngagementActionButton = inst[engagementActionButton];
140
- inst[engagementActionButton] = function () {
141
- const res = origEngagementActionButton.apply(this, arguments);
142
- const superThanksFiltered = res.filter(item => item.type !== 'TRANSPORT_CONTROLS_BUTTON_TYPE_YOUCHAT_BUTTON');
143
- const shoppingFiltered = superThanksFiltered.filter(item => item.type !== 'TRANSPORT_CONTROLS_BUTTON_TYPE_YOUCHAT_BUTTON');
144
- return shoppingFiltered;
145
- }
146
- }
147
-
148
- if (configRead('enablePreviousNextButtons')) {
149
- if (!previousButtonName || !nextButtonName) return inst;
150
- inst[previousButtonName] = function () {
151
- return ButtonRenderer(
152
- false,
153
- t('player.previous'),
154
- 'SKIP_PREVIOUS',
155
- {
156
- signalAction: {
157
- signal: 'PLAYER_PLAY_PREVIOUS'
158
- }
159
- }
160
- )
161
- }
162
-
163
- inst[nextButtonName] = function () {
164
- return ButtonRenderer(
165
- false,
166
- t('player.next'),
167
- 'SKIP_NEXT',
168
- {
169
- signalAction: {
170
- signal: 'PLAYER_PLAY_NEXT'
171
- }
172
- }
173
- )
174
- }
175
-
176
- }
177
-
178
- return inst;
179
- }
180
-
181
- if (configRead('enablePatchingVideoPlayer')) {
182
- YtlrPlayerActionsContainer.prototype = origMethod.prototype;
183
- window._yttv[methods[0]] = YtlrPlayerActionsContainer;
184
- }
185
- }
186
-
187
-
188
- if (document.readyState === 'complete' || document.readyState === 'interactive') {
189
- applyPatches();
190
- } else {
191
- window.addEventListener('DOMContentLoaded', applyPatches);
192
- }
@@ -1,29 +0,0 @@
1
- import { SettingActionRenderer, SettingsCategory } from './ytUI.js';
2
- import { t } from 'i18next';
3
-
4
- function PatchSettings(settingsObject) {
5
- const tizentubeOpenAction = SettingActionRenderer(
6
- t('settings.ttSettings.title'),
7
- 'tizentube_open_action',
8
- {
9
- customAction: {
10
- action: 'TT_SETTINGS_SHOW',
11
- parameters: []
12
- }
13
- },
14
- t('settings.ttSettings.summary'),
15
- 'https://www.gstatic.com/ytlr/img/parent_code.png'
16
- )
17
-
18
- const tizenTubeCategory = SettingsCategory(
19
- 'tizentube_category',
20
- [tizentubeOpenAction]
21
- );
22
- // Add it as the first item in the settings object
23
- settingsObject.items.unshift(tizenTubeCategory);
24
-
25
- }
26
-
27
- export {
28
- PatchSettings
29
- }
@@ -1,48 +0,0 @@
1
- import { configChangeEmitter, configRead } from '../config.js';
2
-
3
- configChangeEmitter.addEventListener('configChange', (event) => {
4
- const { key, value } = event.detail;
5
- if (key === 'enableWhoIsWatchingMenu') {
6
- disableWhosWatching(value);
7
- }
8
- });
9
-
10
- let interval;
11
-
12
- function disableWhosWatching(value) {
13
- const LeanbackRecurringActions = JSON.parse(localStorage['yt.leanback.default::recurring_actions']);
14
- const shouldPermanentlyEnable = configRead('permanentlyEnableWhoIsWatchingMenu');
15
- const date = new Date();
16
- if (!value) {
17
- // Setting it after 7 days should be enough, as it'll get executed every time the app launches.
18
- date.setDate(date.getDate() + 7);
19
- LeanbackRecurringActions.data.data["startup-screen-account-selector-with-guest"] &&
20
- (LeanbackRecurringActions.data.data["startup-screen-account-selector-with-guest"].lastFired = date.getTime());
21
- LeanbackRecurringActions.data.data.whos_watching_fullscreen_zero_accounts.lastFired = date.getTime();
22
- LeanbackRecurringActions.data.data["startup-screen-signed-out-welcome-back"] &&
23
- (LeanbackRecurringActions.data.data["startup-screen-signed-out-welcome-back"].lastFired = date.getTime());
24
- localStorage['yt.leanback.default::recurring_actions'] = JSON.stringify(LeanbackRecurringActions);
25
- } else {
26
- // Do nothing if the last fired action is less than 2 hours ago.
27
- if (date.getTime() - LeanbackRecurringActions.data.data["startup-screen-account-selector-with-guest"]?.lastFired > 0 && date.getTime() - LeanbackRecurringActions.data.data["startup-screen-account-selector-with-guest"]?.lastFired < 2 * 60 * 60 * 1000
28
- && !shouldPermanentlyEnable) {
29
- return;
30
- }
31
- function setActions() {
32
- LeanbackRecurringActions.data.data["startup-screen-account-selector-with-guest"] &&
33
- (LeanbackRecurringActions.data.data["startup-screen-account-selector-with-guest"].lastFired = date.getTime());
34
- LeanbackRecurringActions.data.data.whos_watching_fullscreen_zero_accounts.lastFired = date.getTime();
35
- LeanbackRecurringActions.data.data["startup-screen-signed-out-welcome-back"] &&
36
- (LeanbackRecurringActions.data.data["startup-screen-signed-out-welcome-back"].lastFired = date.getTime());
37
- localStorage['yt.leanback.default::recurring_actions'] = JSON.stringify(LeanbackRecurringActions);
38
- }
39
- setActions();
40
- if (shouldPermanentlyEnable) {
41
- date.setDate(date.getDate() - 7);
42
- setActions();
43
- interval = setInterval(setActions, 60 * 1000);
44
- } else if (interval) clearInterval(interval);
45
- }
46
- }
47
-
48
- disableWhosWatching(configRead('enableWhoIsWatchingMenu'));