@oxymoron.13/tizentube-s95b 0.3.0 → 0.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.
@@ -1,6 +1,7 @@
1
1
  // Picture in Picture Mode for TizenTube
2
2
 
3
3
  import resolveCommand from "../resolveCommand.js";
4
+ import { s95bMiniLayout, s95bMiniEntered } from './s95bMiniPlayer.js';
4
5
 
5
6
  window.isPipPlaying = false;
6
7
  let PlayerService = null;
@@ -51,14 +52,10 @@ function enablePip() {
51
52
 
52
53
  function onPipEnter() {
53
54
  videoElement.style.removeProperty('inset');
54
- const pipWidth = window.innerWidth / 3.5;
55
- const pipHeight = window.innerHeight / 3.5;
56
- videoElement.style.width = `${pipWidth}px`;
57
- videoElement.style.height = `${pipHeight}px`;
58
- videoElement.style.top = '68vh';
59
- videoElement.style.left = '68vw';
55
+ s95bMiniLayout(videoElement);
60
56
 
61
57
  window.isPipPlaying = true;
58
+ s95bMiniEntered(videoElement);
62
59
  videoElement.removeEventListener('play', onPipEnter);
63
60
  }
64
61
 
@@ -10,6 +10,14 @@ export const STRINGS = Object.freeze({
10
10
  statVideo: 'Video', statFrames: 'Verlorene Bilder', statCodec: 'Codec-Wunsch',
11
11
  statUnavailable: 'nicht verfügbar', statWait: 'wartet auf Video',
12
12
  languageDE: 'Deutsch', languageEN: 'English',
13
+ mini: 'Mini-Player',
14
+ miniHint: 'TizenTubes Mini-Player (Eintrag „MiniPlayer“ im Video-Menü). Änderungen gelten beim nächsten Start des Mini-Players. Ein neu gestartetes Video öffnet im Vollbild und ersetzt den Mini-Player.',
15
+ miniOn: 'Mini-Player anbieten',
16
+ miniOnHint: 'Eintrag im Video-Menü und Schaltfläche in der Player-Leiste (die Leiste ändert sich eventuell erst nach einem Neustart von YouTube).',
17
+ miniPos: 'Position', posBR: 'Unten rechts', posBL: 'Unten links', posTR: 'Oben rechts', posTL: 'Oben links',
18
+ miniSize: 'Größe', sizeSmall: 'Klein', sizeMedium: 'Mittel (wie bisher)', sizeLarge: 'Groß',
19
+ miniBrowse: 'Beim Stöbern', browsePlay: 'Weiterlaufen', browsePause: 'Pausieren',
20
+ miniBrowseHint: 'Pausieren: Das Video hält im kleinen Fenster an (der Anfang ist kurz hörbar) und läuft im Vollbild an derselben Stelle weiter.',
13
21
  }),
14
22
  en: Object.freeze({
15
23
  title: 'S95B · Performance', language: 'Language', codec: 'Video codec', quality: 'Default quality (all videos)',
@@ -21,6 +29,14 @@ export const STRINGS = Object.freeze({
21
29
  statVideo: 'Video', statFrames: 'Dropped frames', statCodec: 'Codec preference',
22
30
  statUnavailable: 'not available', statWait: 'waiting for video',
23
31
  languageDE: 'Deutsch', languageEN: 'English',
32
+ mini: 'Mini player',
33
+ miniHint: 'TizenTube’s mini player (“MiniPlayer” row in the video menu). Changes apply the next time the mini player starts. A newly started video opens full screen and replaces the mini player.',
34
+ miniOn: 'Offer mini player',
35
+ miniOnHint: 'Row in the video menu and button in the player bar (the bar may only change after restarting YouTube).',
36
+ miniPos: 'Position', posBR: 'Bottom right', posBL: 'Bottom left', posTR: 'Top right', posTL: 'Top left',
37
+ miniSize: 'Size', sizeSmall: 'Small', sizeMedium: 'Medium (as before)', sizeLarge: 'Large',
38
+ miniBrowse: 'While browsing', browsePlay: 'Keep playing', browsePause: 'Pause',
39
+ miniBrowseHint: 'Pause: the video stops in the small window (its start is briefly audible) and continues full screen from the same position.',
24
40
  })
25
41
  });
26
42
  export function translate(lang, key) {
@@ -7,6 +7,7 @@ import { configRead, configWrite, configChangeEmitter } from '../config.js';
7
7
  import { optionShow } from '../ui/settings.js';
8
8
  import { translate } from './s95bI18n.js';
9
9
  import { codecMenu, qualityMenu, codecLabel, currentCodec } from './s95bOptions.js';
10
+ import { MINI_POSITIONS, MINI_SIZES, MINI_BROWSE } from './s95bMiniPlayer.js';
10
11
 
11
12
  const STATE_KEY = 's95b-perf-edition-v1';
12
13
  const EDITED = ['enablePreviews', 'enableDeArrow', 'enableDeArrowThumbnails'];
@@ -80,6 +81,28 @@ function statsLine() {
80
81
  ' | ' + t('statCodec') + ': ' + codecLabel(t, currentCodec());
81
82
  }
82
83
 
84
+ const MINI_DEFAULTS = { s95bMiniPos: 'br', s95bMiniSize: 'medium', s95bMiniBrowse: 'play' };
85
+ const MINI_VALUES = { s95bMiniPos: MINI_POSITIONS, s95bMiniSize: MINI_SIZES, s95bMiniBrowse: MINI_BROWSE };
86
+ const MINI_LABELS = { br: 'posBR', bl: 'posBL', tr: 'posTR', tl: 'posTL', small: 'sizeSmall', medium: 'sizeMedium',
87
+ large: 'sizeLarge', play: 'browsePlay', pause: 'browsePause' };
88
+
89
+ function miniChoice(title, key, hint) {
90
+ return { name: t(title), value: null, menuId: 's95b-' + key,
91
+ menuHeader: { title: t(title), subtitle: hint ? t(hint) : t('miniHint') },
92
+ options: MINI_VALUES[key].map(value => ({ name: t(MINI_LABELS[value]), key, value })) };
93
+ }
94
+ function miniMenu() {
95
+ return { name: t('mini'), icon: 'CLEAR_COOKIES', value: null, menuId: 's95b-mini',
96
+ menuHeader: { title: t('mini'), subtitle: t('miniHint') },
97
+ options: [
98
+ // TizenTube's own switch; the fork extends it to the "MiniPlayer" row in the video menu.
99
+ { name: t('miniOn'), subtitle: t('miniOnHint'), value: 'enableMPButton' },
100
+ miniChoice('miniPos', 's95bMiniPos'),
101
+ miniChoice('miniSize', 's95bMiniSize'),
102
+ miniChoice('miniBrowse', 's95bMiniBrowse', 'miniBrowseHint')
103
+ ] };
104
+ }
105
+
83
106
  function buildOptions() {
84
107
  return [
85
108
  { name: t('language'), value: null, menuId: 's95b-language',
@@ -90,6 +113,7 @@ function buildOptions() {
90
113
  ] },
91
114
  codecMenu(t),
92
115
  qualityMenu(t),
116
+ miniMenu(),
93
117
  { name: t('light'), subtitle: t('lightHint'), value: 's95bLowOverhead' }
94
118
  ];
95
119
  }
@@ -126,6 +150,9 @@ function init() {
126
150
  // Menu entries read their current value from the TizenTube config, so mirror our stored state into it first.
127
151
  if (configRead('s95bLowOverhead') !== state.light) configWrite('s95bLowOverhead', state.light);
128
152
  if (configRead('s95bLanguage') !== state.lang) configWrite('s95bLanguage', state.lang);
153
+ Object.keys(MINI_DEFAULTS).forEach(key => {
154
+ if (MINI_VALUES[key].indexOf(configRead(key)) < 0) configWrite(key, MINI_DEFAULTS[key]);
155
+ });
129
156
  configChangeEmitter.addEventListener('configChange', onConfigChange);
130
157
  // Capture phase on window: only the yellow key is consumed.
131
158
  window.addEventListener('keydown', onKeys, true);
@@ -0,0 +1,36 @@
1
+ /* S95B Performance Edition – GPL-3.0-only
2
+ * Settings for TizenTube's own mini player (features/pictureInPicture.js): position, size and
3
+ * whether the video keeps playing while browsing. Called from the two patched lines in pictureInPicture.js.
4
+ * Defaults reproduce upstream exactly: 1/3.5 of the screen at 68vh / 68vw (bottom right), keeps playing.
5
+ */
6
+ import { configRead } from '../config.js';
7
+
8
+ export const MINI_POSITIONS = ['br', 'bl', 'tr', 'tl'];
9
+ export const MINI_SIZES = ['small', 'medium', 'large'];
10
+ export const MINI_BROWSE = ['play', 'pause'];
11
+ const DIVISOR = { small: 4.5, medium: 3.5, large: 2.5 };
12
+ // Upstream's gap between the mini player and the right/bottom screen edge, in vw/vh (100 - 68 - 100/3.5).
13
+ const GAP = 100 - 68 - 100 / 3.5;
14
+ const round = value => Math.round(value * 100) / 100;
15
+
16
+ export function s95bMiniLayout(videoElement) {
17
+ const position = MINI_POSITIONS.indexOf(configRead('s95bMiniPos')) >= 0 ? configRead('s95bMiniPos') : 'br';
18
+ const divisor = DIVISOR[configRead('s95bMiniSize')] || DIVISOR.medium;
19
+ const far = round(100 - 100 / divisor - GAP);
20
+ const near = round(GAP);
21
+ videoElement.style.width = `${window.innerWidth / divisor}px`;
22
+ videoElement.style.height = `${window.innerHeight / divisor}px`;
23
+ videoElement.style.top = (position[0] === 'b' ? far : near) + 'vh';
24
+ videoElement.style.left = (position[1] === 'r' ? far : near) + 'vw';
25
+ }
26
+
27
+ // "Pause while browsing": pause once the reloaded video has really started, so YouTube's own play() call
28
+ // is not interrupted. Going back to full screen starts the video again from this position (upstream behavior).
29
+ export function s95bMiniEntered(videoElement) {
30
+ if (configRead('s95bMiniBrowse') !== 'pause') return;
31
+ const pauseOnce = () => {
32
+ videoElement.removeEventListener('playing', pauseOnce);
33
+ if (window.isPipPlaying) videoElement.pause();
34
+ };
35
+ videoElement.addEventListener('playing', pauseOnce);
36
+ }
@@ -97,7 +97,7 @@ export function patchResolveCommand() {
97
97
  }
98
98
  }
99
99
 
100
- cmd.openPopupAction.popup.overlaySectionRenderer.overlay.overlayTwoPanelRenderer.actionPanel.overlayPanelRenderer.content.overlayPanelItemListRenderer.items.splice(2, 0,
100
+ if (configRead('enableMPButton')) cmd.openPopupAction.popup.overlaySectionRenderer.overlay.overlayTwoPanelRenderer.actionPanel.overlayPanelRenderer.content.overlayPanelItemListRenderer.items.splice(2, 0,
101
101
  buttonItem(
102
102
  { title: t('player.miniPlayer') },
103
103
  { icon: 'CLEAR_COOKIES' }, [
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@oxymoron.13/tizentube-s95b",
3
3
  "appName": "TizenTube S95B Performance (Fork)",
4
- "version": "0.3.0",
4
+ "version": "0.3.1",
5
5
  "description": "Unofficial fork of TizenTube (@foxreis/tizentube) for TizenBrew: reversible performance profile, German/English settings, smaller bundle.",
6
6
  "packageType": "mods",
7
7
  "websiteURL": "https://youtube.com/tv?additionalDataUrl=http%3A%2F%2Flocalhost%3A8085%2Fdial%2Fapps%2FYouTube",