1
0
Fork 0
mirror of https://github.com/jellyfin/jellyfin-web synced 2025-03-30 19:56:21 +00:00

Update SyncPlay references to use plugin

This commit is contained in:
Bill Thornton 2023-03-08 17:47:40 -05:00
parent 641a7c0915
commit 732ef8fdad
9 changed files with 106 additions and 64 deletions

View file

@ -4,7 +4,8 @@ import Events from '../../utils/events.ts';
import layoutManager from '../layoutManager'; import layoutManager from '../layoutManager';
import { playbackManager } from '../playback/playbackmanager'; import { playbackManager } from '../playback/playbackmanager';
import playMethodHelper from '../playback/playmethodhelper'; import playMethodHelper from '../playback/playmethodhelper';
import SyncPlay from '../../plugins/syncPlay/core'; import { pluginManager } from '../pluginManager';
import { PluginType } from '../../types/plugin.ts';
import './playerstats.scss'; import './playerstats.scss';
import ServerConnections from '../ServerConnections'; import ServerConnections from '../ServerConnections';
@ -325,6 +326,12 @@ import ServerConnections from '../ServerConnections';
} }
function getSyncPlayStats() { function getSyncPlayStats() {
const SyncPlay = pluginManager.firstOfType(PluginType.SyncPlay)?.instance;
if (!SyncPlay?.Manager.isSyncPlayEnabled()) {
return [];
}
const syncStats = []; const syncStats = [];
const stats = SyncPlay.Manager.getStats(); const stats = SyncPlay.Manager.getStats();
@ -422,10 +429,10 @@ import ServerConnections from '../ServerConnections';
name: globalize.translate('LabelOriginalMediaInfo') name: globalize.translate('LabelOriginalMediaInfo')
}); });
const apiClient = ServerConnections.getApiClient(playbackManager.currentItem(player).ServerId); const syncPlayStats = getSyncPlayStats();
if (SyncPlay.Manager.isSyncPlayEnabled() && apiClient.isMinServerVersion('10.6.0')) { if (syncPlayStats.length > 0) {
categories.push({ categories.push({
stats: getSyncPlayStats(), stats: syncPlayStats,
name: globalize.translate('LabelSyncPlayInfo') name: globalize.translate('LabelSyncPlayInfo')
}); });
} }

View file

@ -4,10 +4,12 @@ import dialogHelper from '../dialogHelper/dialogHelper';
import loading from '../loading/loading'; import loading from '../loading/loading';
import layoutManager from '../layoutManager'; import layoutManager from '../layoutManager';
import { playbackManager } from '../playback/playbackmanager'; import { playbackManager } from '../playback/playbackmanager';
import SyncPlay from '../../plugins/syncPlay/core'; import { pluginManager } from '../pluginManager';
import * as userSettings from '../../scripts/settings/userSettings'; import * as userSettings from '../../scripts/settings/userSettings';
import { appRouter } from '../appRouter'; import { appRouter } from '../appRouter';
import globalize from '../../scripts/globalize'; import globalize from '../../scripts/globalize';
import { PluginType } from '../../types/plugin.ts';
import '../../elements/emby-button/emby-button'; import '../../elements/emby-button/emby-button';
import '../../elements/emby-input/emby-input'; import '../../elements/emby-input/emby-input';
import '../../elements/emby-button/paper-icon-button-light'; import '../../elements/emby-button/paper-icon-button-light';
@ -117,10 +119,12 @@ import ServerConnections from '../ServerConnections';
}; };
const apiClient = ServerConnections.getApiClient(currentServerId); const apiClient = ServerConnections.getApiClient(currentServerId);
const SyncPlay = pluginManager.firstOfType(PluginType.SyncPlay)?.instance;
apiClient.getItems(apiClient.getCurrentUserId(), options).then(result => { apiClient.getItems(apiClient.getCurrentUserId(), options).then(result => {
let html = ''; let html = '';
if ((editorOptions.enableAddToPlayQueue !== false && playbackManager.isPlaying()) || SyncPlay.Manager.isSyncPlayEnabled()) { if ((editorOptions.enableAddToPlayQueue !== false && playbackManager.isPlaying()) || SyncPlay?.Manager.isSyncPlayEnabled()) {
html += `<option value="queue">${globalize.translate('AddToPlayQueue')}</option>`; html += `<option value="queue">${globalize.translate('AddToPlayQueue')}</option>`;
} }

View file

@ -119,9 +119,14 @@ class PluginManager {
} }
ofType(type) { ofType(type) {
return this.pluginsList.filter((o) => { return this.pluginsList.filter(plugin => plugin.type === type);
return o.type === type; }
});
firstOfType(type) {
// Get all plugins of the specified type
return this.ofType(type)
// Return the plugin with the "highest" (lowest numeric value) priority
.sort((p1, p2) => (p1.priority || 0) - (p2.priority || 0))[0];
} }
#mapRoute(plugin, route) { #mapRoute(plugin, route) {

View file

@ -1,6 +1,5 @@
import escapeHtml from 'escape-html'; import escapeHtml from 'escape-html';
import { playbackManager } from '../../../components/playback/playbackmanager'; import { playbackManager } from '../../../components/playback/playbackmanager';
import SyncPlay from '../../../plugins/syncPlay/core';
import browser from '../../../scripts/browser'; import browser from '../../../scripts/browser';
import dom from '../../../scripts/dom'; import dom from '../../../scripts/dom';
import inputManager from '../../../scripts/inputManager'; import inputManager from '../../../scripts/inputManager';
@ -25,6 +24,8 @@ import SubtitleSync from '../../../components/subtitlesync/subtitlesync';
import { appRouter } from '../../../components/appRouter'; import { appRouter } from '../../../components/appRouter';
import LibraryMenu from '../../../scripts/libraryMenu'; import LibraryMenu from '../../../scripts/libraryMenu';
import { setBackdropTransparency, TRANSPARENCY_LEVEL } from '../../../components/backdrop/backdrop'; import { setBackdropTransparency, TRANSPARENCY_LEVEL } from '../../../components/backdrop/backdrop';
import { pluginManager } from '../../../components/pluginManager';
import { PluginType } from '../../../types/plugin.ts';
/* eslint-disable indent */ /* eslint-disable indent */
const TICKS_PER_MINUTE = 600000000; const TICKS_PER_MINUTE = 600000000;
@ -1774,20 +1775,20 @@ import { setBackdropTransparency, TRANSPARENCY_LEVEL } from '../../../components
}, iconVisibilityTime); }, iconVisibilityTime);
}; };
Events.on(SyncPlay.Manager, 'enabled', (event, enabled) => { const SyncPlay = pluginManager.firstOfType(PluginType.SyncPlay)?.instance;
if (enabled) { if (SyncPlay) {
// SyncPlay enabled Events.on(SyncPlay.Manager, 'enabled', (_event, enabled) => {
} else { if (!enabled) {
const syncPlayIcon = view.querySelector('#syncPlayIcon'); const syncPlayIcon = view.querySelector('#syncPlayIcon');
syncPlayIcon.style.visibility = 'hidden'; syncPlayIcon.style.visibility = 'hidden';
} }
}); });
Events.on(SyncPlay.Manager, 'notify-osd', (event, action) => { Events.on(SyncPlay.Manager, 'notify-osd', (_event, action) => {
showIcon(action); showIcon(action);
}); });
Events.on(SyncPlay.Manager, 'group-state-update', (event, state, reason) => { Events.on(SyncPlay.Manager, 'group-state-update', (_event, state, reason) => {
if (state === 'Playing' && reason === 'Unpause') { if (state === 'Playing' && reason === 'Unpause') {
showIcon('schedule-play'); showIcon('schedule-play');
} else if (state === 'Playing' && reason === 'Ready') { } else if (state === 'Playing' && reason === 'Ready') {
@ -1807,5 +1808,6 @@ import { setBackdropTransparency, TRANSPARENCY_LEVEL } from '../../../components
} }
}); });
} }
}
/* eslint-enable indent */ /* eslint-enable indent */

View file

@ -12,6 +12,7 @@ class SyncPlayPlugin implements Plugin {
id: string; id: string;
type: string; type: string;
priority: number; priority: number;
instance: typeof SyncPlay;
constructor() { constructor() {
this.name = 'SyncPlay Plugin'; this.name = 'SyncPlay Plugin';
@ -21,6 +22,8 @@ class SyncPlayPlugin implements Plugin {
this.type = PluginType.SyncPlay; this.type = PluginType.SyncPlay;
this.priority = 1; this.priority = 1;
this.instance = SyncPlay;
this.init(); this.init();
} }

View file

@ -1,11 +1,12 @@
import SyncPlay from '../core';
import SyncPlaySettingsEditor from './settings/SettingsEditor'; import SyncPlaySettingsEditor from './settings/SettingsEditor';
import loading from '../../../components/loading/loading'; import loading from '../../../components/loading/loading';
import toast from '../../../components/toast/toast'; import toast from '../../../components/toast/toast';
import actionsheet from '../../../components/actionSheet/actionSheet'; import actionsheet from '../../../components/actionSheet/actionSheet';
import globalize from '../../../scripts/globalize'; import globalize from '../../../scripts/globalize';
import playbackPermissionManager from './playbackPermissionManager'; import playbackPermissionManager from './playbackPermissionManager';
import { pluginManager } from '../../../components/pluginManager';
import ServerConnections from '../../../components/ServerConnections'; import ServerConnections from '../../../components/ServerConnections';
import { PluginType } from '../../../types/plugin.ts';
import Events from '../../../utils/events.ts'; import Events from '../../../utils/events.ts';
import './groupSelectionMenu.scss'; import './groupSelectionMenu.scss';
@ -17,11 +18,25 @@ class GroupSelectionMenu {
constructor() { constructor() {
// Register to SyncPlay events. // Register to SyncPlay events.
this.syncPlayEnabled = false; this.syncPlayEnabled = false;
Events.on(SyncPlay.Manager, 'enabled', (e, enabled) => { this.SyncPlay = pluginManager.firstOfType(PluginType.SyncPlay)?.instance;
if (this.SyncPlay) {
Events.on(this.SyncPlay.Manager, 'enabled', (_event, enabled) => {
this.syncPlayEnabled = enabled; this.syncPlayEnabled = enabled;
}); });
} }
Events.on(pluginManager, 'registered', (_event0, plugin) => {
if (plugin.type === PluginType.SyncPlay) {
this.SyncPlay = plugin.instance;
Events.on(plugin.instance.Manager, 'enabled', (_event1, enabled) => {
this.syncPlayEnabled = enabled;
});
}
});
}
/** /**
* Used when user needs to join a group. * Used when user needs to join a group.
* @param {HTMLElement} button - Element where to place the menu. * @param {HTMLElement} button - Element where to place the menu.
@ -103,10 +118,11 @@ class GroupSelectionMenu {
* @param {Object} apiClient - ApiClient. * @param {Object} apiClient - ApiClient.
*/ */
showLeaveGroupSelection(button, user, apiClient) { showLeaveGroupSelection(button, user, apiClient) {
const groupInfo = SyncPlay.Manager.getGroupInfo(); const groupInfo = this.SyncPlay?.Manager.getGroupInfo();
const menuItems = []; const menuItems = [];
if (!SyncPlay.Manager.isPlaylistEmpty() && !SyncPlay.Manager.isPlaybackActive()) { if (!this.SyncPlay?.Manager.isPlaylistEmpty()
&& !this.SyncPlay?.Manager.isPlaybackActive()) {
menuItems.push({ menuItems.push({
name: globalize.translate('LabelSyncPlayResumePlayback'), name: globalize.translate('LabelSyncPlayResumePlayback'),
icon: 'play_circle_filled', icon: 'play_circle_filled',
@ -114,7 +130,7 @@ class GroupSelectionMenu {
selected: false, selected: false,
secondaryText: globalize.translate('LabelSyncPlayResumePlaybackDescription') secondaryText: globalize.translate('LabelSyncPlayResumePlaybackDescription')
}); });
} else if (SyncPlay.Manager.isPlaybackActive()) { } else if (this.SyncPlay?.Manager.isPlaybackActive()) {
menuItems.push({ menuItems.push({
name: globalize.translate('LabelSyncPlayHaltPlayback'), name: globalize.translate('LabelSyncPlayHaltPlayback'),
icon: 'pause_circle_filled', icon: 'pause_circle_filled',
@ -149,15 +165,15 @@ class GroupSelectionMenu {
border: true border: true
}; };
actionsheet.show(menuOptions).then(function (id) { actionsheet.show(menuOptions).then((id) => {
if (id == 'resume-playback') { if (id == 'resume-playback') {
SyncPlay.Manager.resumeGroupPlayback(apiClient); this.SyncPlay?.Manager.resumeGroupPlayback(apiClient);
} else if (id == 'halt-playback') { } else if (id == 'halt-playback') {
SyncPlay.Manager.haltGroupPlayback(apiClient); this.SyncPlay?.Manager.haltGroupPlayback(apiClient);
} else if (id == 'leave-group') { } else if (id == 'leave-group') {
apiClient.leaveSyncPlayGroup(); apiClient.leaveSyncPlayGroup();
} else if (id == 'settings') { } else if (id == 'settings') {
new SyncPlaySettingsEditor(apiClient, SyncPlay.Manager.getTimeSyncCore(), { groupInfo: groupInfo }) new SyncPlaySettingsEditor(apiClient, this.SyncPlay?.Manager.getTimeSyncCore(), { groupInfo: groupInfo })
.embed() .embed()
.catch(error => { .catch(error => {
if (error) { if (error) {

View file

@ -3,13 +3,14 @@
* @module components/syncPlay/settings/SettingsEditor * @module components/syncPlay/settings/SettingsEditor
*/ */
import SyncPlay from '../../core';
import { setSetting } from '../../core/Settings'; import { setSetting } from '../../core/Settings';
import dialogHelper from '../../../../components/dialogHelper/dialogHelper'; import dialogHelper from '../../../../components/dialogHelper/dialogHelper';
import layoutManager from '../../../../components/layoutManager'; import layoutManager from '../../../../components/layoutManager';
import { pluginManager } from '../../../../components/pluginManager';
import loading from '../../../../components/loading/loading'; import loading from '../../../../components/loading/loading';
import toast from '../../../../components/toast/toast'; import toast from '../../../../components/toast/toast';
import globalize from '../../../../scripts/globalize'; import globalize from '../../../../scripts/globalize';
import { PluginType } from '../../../../types/plugin.ts';
import Events from '../../../../utils/events.ts'; import Events from '../../../../utils/events.ts';
import 'material-design-icons-iconfont'; import 'material-design-icons-iconfont';
@ -36,6 +37,7 @@ class SettingsEditor {
this.apiClient = apiClient; this.apiClient = apiClient;
this.timeSyncCore = timeSyncCore; this.timeSyncCore = timeSyncCore;
this.options = options; this.options = options;
this.SyncPlay = pluginManager.firstOfType(PluginType.SyncPlay)?.instance;
} }
async embed() { async embed() {
@ -95,14 +97,14 @@ class SettingsEditor {
async initEditor() { async initEditor() {
const { context } = this; const { context } = this;
context.querySelector('#txtExtraTimeOffset').value = SyncPlay.Manager.timeSyncCore.extraTimeOffset; context.querySelector('#txtExtraTimeOffset').value = this.SyncPlay?.Manager.timeSyncCore.extraTimeOffset;
context.querySelector('#chkSyncCorrection').checked = SyncPlay.Manager.playbackCore.enableSyncCorrection; context.querySelector('#chkSyncCorrection').checked = this.SyncPlay?.Manager.playbackCore.enableSyncCorrection;
context.querySelector('#txtMinDelaySpeedToSync').value = SyncPlay.Manager.playbackCore.minDelaySpeedToSync; context.querySelector('#txtMinDelaySpeedToSync').value = this.SyncPlay?.Manager.playbackCore.minDelaySpeedToSync;
context.querySelector('#txtMaxDelaySpeedToSync').value = SyncPlay.Manager.playbackCore.maxDelaySpeedToSync; context.querySelector('#txtMaxDelaySpeedToSync').value = this.SyncPlay?.Manager.playbackCore.maxDelaySpeedToSync;
context.querySelector('#txtSpeedToSyncDuration').value = SyncPlay.Manager.playbackCore.speedToSyncDuration; context.querySelector('#txtSpeedToSyncDuration').value = this.SyncPlay?.Manager.playbackCore.speedToSyncDuration;
context.querySelector('#txtMinDelaySkipToSync').value = SyncPlay.Manager.playbackCore.minDelaySkipToSync; context.querySelector('#txtMinDelaySkipToSync').value = this.SyncPlay?.Manager.playbackCore.minDelaySkipToSync;
context.querySelector('#chkSpeedToSync').checked = SyncPlay.Manager.playbackCore.useSpeedToSync; context.querySelector('#chkSpeedToSync').checked = this.SyncPlay?.Manager.playbackCore.useSpeedToSync;
context.querySelector('#chkSkipToSync').checked = SyncPlay.Manager.playbackCore.useSkipToSync; context.querySelector('#chkSkipToSync').checked = this.SyncPlay?.Manager.playbackCore.useSkipToSync;
} }
onSubmit() { onSubmit() {
@ -139,7 +141,7 @@ class SettingsEditor {
setSetting('useSpeedToSync', useSpeedToSync); setSetting('useSpeedToSync', useSpeedToSync);
setSetting('useSkipToSync', useSkipToSync); setSetting('useSkipToSync', useSkipToSync);
Events.trigger(SyncPlay.Manager, 'settings-update'); Events.trigger(this.SyncPlay?.Manager, 'settings-update');
} }
} }

View file

@ -1,5 +1,5 @@
import { playbackManager } from '../components/playback/playbackmanager'; import { playbackManager } from '../components/playback/playbackmanager';
import SyncPlay from '../plugins/syncPlay/core'; import { pluginManager } from '../components/pluginManager';
import inputManager from '../scripts/inputManager'; import inputManager from '../scripts/inputManager';
import focusManager from '../components/focusManager'; import focusManager from '../components/focusManager';
import { appRouter } from '../components/appRouter'; import { appRouter } from '../components/appRouter';
@ -7,6 +7,7 @@ import ServerConnections from '../components/ServerConnections';
import toast from '../components/toast/toast'; import toast from '../components/toast/toast';
import alert from '../components/alert'; import alert from '../components/alert';
import Events from '../utils/events.ts'; import Events from '../utils/events.ts';
import { PluginType } from '../types/plugin.ts';
const serverNotifications = {}; const serverNotifications = {};
@ -140,6 +141,8 @@ function processGeneralCommand(cmd, apiClient) {
function onMessageReceived(e, msg) { function onMessageReceived(e, msg) {
const apiClient = this; const apiClient = this;
const SyncPlay = pluginManager.firstOfType(PluginType.SyncPlay)?.instance;
if (msg.MessageType === 'Play') { if (msg.MessageType === 'Play') {
notifyApp(); notifyApp();
const serverId = apiClient.serverInfo().Id; const serverId = apiClient.serverInfo().Id;
@ -186,9 +189,9 @@ function onMessageReceived(e, msg) {
} }
} }
} else if (msg.MessageType === 'SyncPlayCommand') { } else if (msg.MessageType === 'SyncPlayCommand') {
SyncPlay.Manager.processCommand(msg.Data, apiClient); SyncPlay?.Manager.processCommand(msg.Data, apiClient);
} else if (msg.MessageType === 'SyncPlayGroupUpdate') { } else if (msg.MessageType === 'SyncPlayGroupUpdate') {
SyncPlay.Manager.processGroupUpdate(msg.Data, apiClient); SyncPlay?.Manager.processGroupUpdate(msg.Data, apiClient);
} else { } else {
Events.trigger(serverNotifications, msg.MessageType, [apiClient, msg.Data]); Events.trigger(serverNotifications, msg.MessageType, [apiClient, msg.Data]);
} }

View file

@ -9,5 +9,5 @@ export interface Plugin {
name: string name: string
id: string id: string
type: PluginType | string type: PluginType | string
priority: number priority?: number
} }