feat: Playtube Stream Dock Plugin 1.0.0 (Ajazz AKP153E) mit Icon-Pack
This commit is contained in:
@@ -0,0 +1,246 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Playtube</title>
|
||||
<style>
|
||||
html, body { margin: 0; background: #2a2a2a; color: #e6e6e6;
|
||||
font: 13px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Arial, sans-serif; }
|
||||
body { padding: 12px 14px; }
|
||||
.row { margin-bottom: 12px; }
|
||||
.row[hidden] { display: none; }
|
||||
label { display: block; margin-bottom: 4px; color: #b5b5b5; }
|
||||
select, input[type=number], input[type=text] { width: 100%; box-sizing: border-box; padding: 6px 8px;
|
||||
background: #3a3a3a; color: #fff; border: 1px solid #4a4a4a; border-radius: 4px; }
|
||||
input[type=checkbox] { vertical-align: middle; margin-right: 6px; }
|
||||
.check label { display: inline; color: #e6e6e6; }
|
||||
button { padding: 6px 10px; background: #3a3a3a; color: #fff; border: 1px solid #4a4a4a; border-radius: 4px; cursor: pointer; }
|
||||
button:hover { background: #4a4a4a; }
|
||||
.hint { margin-top: 4px; color: #9a9a9a; font-size: 12px; }
|
||||
.hint.error { color: #ff8a8a; }
|
||||
.inline { display: flex; gap: 8px; }
|
||||
.inline select { flex: 1; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="row" data-for="target">
|
||||
<label id="l-target" for="target"></label>
|
||||
<select id="target">
|
||||
<option value="auto" id="o-auto"></option>
|
||||
<option value="youtube">YouTube</option>
|
||||
<option value="music">YouTube Music</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="row" data-for="step" hidden>
|
||||
<label id="l-step" for="step"></label>
|
||||
<input type="number" id="step" min="1" max="25" />
|
||||
</div>
|
||||
|
||||
<div class="row" data-for="volume" hidden>
|
||||
<label id="l-volume" for="volume"></label>
|
||||
<input type="number" id="volume" min="0" max="100" />
|
||||
</div>
|
||||
|
||||
<div class="row" data-for="seconds" hidden>
|
||||
<label id="l-seconds" for="seconds"></label>
|
||||
<input type="number" id="seconds" min="1" max="300" />
|
||||
</div>
|
||||
|
||||
<div class="row" data-for="tab" hidden>
|
||||
<label id="l-tab" for="tab"></label>
|
||||
<select id="tab">
|
||||
<option value="toggle" id="o-toggle"></option>
|
||||
<option value="youtube">YouTube</option>
|
||||
<option value="music">YouTube Music</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="row" data-for="playlist" hidden>
|
||||
<label id="l-playlist" for="playlistSelect"></label>
|
||||
<div class="inline">
|
||||
<select id="playlistSelect"></select>
|
||||
<button id="reload"></button>
|
||||
</div>
|
||||
<div class="hint" id="playlistHint"></div>
|
||||
</div>
|
||||
|
||||
<div class="row" data-for="playlist" hidden>
|
||||
<label id="l-playlistId" for="playlistId"></label>
|
||||
<input type="text" id="playlistId" spellcheck="false" placeholder="PL..." />
|
||||
</div>
|
||||
|
||||
<div class="row check" data-for="showTitle" hidden>
|
||||
<input type="checkbox" id="showTitle" />
|
||||
<label id="l-showTitle" for="showTitle"></label>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
var PREFIX = 'com.fojadrachi.playtube.';
|
||||
var TEXT = {
|
||||
en: {
|
||||
target: 'Target tab', auto: 'Automatic (active tab)', step: 'Step (%)', volume: 'Volume (%)',
|
||||
seconds: 'Seconds', tab: 'Switch to', toggle: 'Toggle YouTube / Music', playlist: 'Playlist',
|
||||
playlistId: 'Playlist ID (manual)', showTitle: 'Show title on the key', reload: 'Reload',
|
||||
choose: '- choose a playlist -', loading: 'Loading playlists ...',
|
||||
offline: 'Playtube is not running or too old (needs the newer version with Stream Dock support).',
|
||||
failed: 'Playlists could not be read. Is YouTube Music loaded in Playtube?', count: 'playlists found'
|
||||
},
|
||||
de: {
|
||||
target: 'Ziel-Tab', auto: 'Automatisch (aktiver Tab)', step: 'Schrittweite (%)', volume: 'Lautstärke (%)',
|
||||
seconds: 'Sekunden', tab: 'Wechseln zu', toggle: 'YouTube / Musik umschalten', playlist: 'Playlist',
|
||||
playlistId: 'Playlist-ID (manuell)', showTitle: 'Titel auf der Taste anzeigen', reload: 'Neu laden',
|
||||
choose: '- Playlist wählen -', loading: 'Playlists werden geladen ...',
|
||||
offline: 'Playtube läuft nicht oder ist zu alt (benötigt die neuere Version mit Stream-Dock-Unterstützung).',
|
||||
failed: 'Playlists konnten nicht gelesen werden. Ist YouTube Musik in Playtube geladen?', count: 'Playlists gefunden'
|
||||
}
|
||||
};
|
||||
// Welche Felder eine Aktion zeigt; alle anderen Aktionen zeigen nur den Ziel-Tab.
|
||||
var FIELDS = {
|
||||
volumeup: ['target', 'step'], volumedown: ['target', 'step'], volumeset: ['target', 'volume'],
|
||||
seekback: ['target', 'seconds'], seekforward: ['target', 'seconds'],
|
||||
playpause: ['target', 'showTitle'], nowplaying: ['target', 'showTitle'],
|
||||
playlist: ['playlist'], switchtab: ['tab'], show: []
|
||||
};
|
||||
var DEFAULT_FIELDS = ['target'];
|
||||
|
||||
var websocket = null, uuid = null, actionUuid = null, settings = {}, t = TEXT.en;
|
||||
var saveTimer = null;
|
||||
|
||||
function $(id) { return document.getElementById(id); }
|
||||
function send(message) { if (websocket && websocket.readyState === 1) websocket.send(JSON.stringify(message)); }
|
||||
function actionId() { return actionUuid.indexOf(PREFIX) === 0 ? actionUuid.slice(PREFIX.length) : ''; }
|
||||
|
||||
function connectElgatoStreamDeckSocket(port, inUuid, registerEvent, info, actionInfo) {
|
||||
uuid = inUuid;
|
||||
var lang = 'en';
|
||||
try { lang = (JSON.parse(info).application.language || 'en').slice(0, 2); } catch (e) { lang = 'en'; }
|
||||
t = TEXT[lang] || TEXT.en;
|
||||
var action = {};
|
||||
try { action = JSON.parse(actionInfo); } catch (e) { action = {}; }
|
||||
actionUuid = action.action || '';
|
||||
settings = (action.payload && action.payload.settings) || {};
|
||||
|
||||
applyTexts();
|
||||
showFields();
|
||||
loadValues();
|
||||
|
||||
websocket = new WebSocket('ws://127.0.0.1:' + port);
|
||||
websocket.onopen = function () {
|
||||
send({ event: registerEvent, uuid: inUuid });
|
||||
if (actionId() === 'playlist') requestPlaylists();
|
||||
};
|
||||
websocket.onmessage = function (event) {
|
||||
var message = JSON.parse(event.data);
|
||||
if (message.event === 'sendToPropertyInspector' && message.payload && message.payload.command === 'playlists') {
|
||||
showPlaylists(message.payload);
|
||||
} else if (message.event === 'didReceiveSettings') {
|
||||
settings = (message.payload && message.payload.settings) || settings;
|
||||
loadValues();
|
||||
}
|
||||
};
|
||||
}
|
||||
window.connectElgatoStreamDeckSocket = connectElgatoStreamDeckSocket;
|
||||
|
||||
function applyTexts() {
|
||||
['target', 'step', 'volume', 'seconds', 'tab', 'playlist', 'playlistId', 'showTitle'].forEach(function (key) {
|
||||
$('l-' + key).textContent = t[key];
|
||||
});
|
||||
$('o-auto').textContent = t.auto;
|
||||
$('o-toggle').textContent = t.toggle;
|
||||
$('reload').textContent = t.reload;
|
||||
}
|
||||
|
||||
function showFields() {
|
||||
var visible = FIELDS[actionId()] || DEFAULT_FIELDS;
|
||||
Array.prototype.forEach.call(document.querySelectorAll('[data-for]'), function (row) {
|
||||
row.hidden = visible.indexOf(row.getAttribute('data-for')) < 0;
|
||||
});
|
||||
}
|
||||
|
||||
function loadValues() {
|
||||
$('target').value = settings.target || 'auto';
|
||||
$('step').value = settings.step || 5;
|
||||
$('volume').value = settings.volume === undefined ? 30 : settings.volume;
|
||||
$('seconds').value = settings.seconds || 10;
|
||||
$('tab').value = settings.tab || 'toggle';
|
||||
$('playlistId').value = settings.playlistId || '';
|
||||
var defaultShow = actionId() === 'nowplaying';
|
||||
$('showTitle').checked = settings.showTitle === undefined
|
||||
? defaultShow : settings.showTitle === true || settings.showTitle === 'true';
|
||||
selectPlaylist(settings.playlistId || '');
|
||||
}
|
||||
|
||||
function save(extra) {
|
||||
settings = Object.assign({}, settings, extra || {}, {
|
||||
target: $('target').value,
|
||||
step: Number($('step').value) || 5,
|
||||
volume: Number($('volume').value),
|
||||
seconds: Number($('seconds').value) || 10,
|
||||
tab: $('tab').value,
|
||||
playlistId: $('playlistId').value.trim(),
|
||||
showTitle: $('showTitle').checked
|
||||
});
|
||||
clearTimeout(saveTimer);
|
||||
saveTimer = setTimeout(function () { send({ event: 'setSettings', context: uuid, payload: settings }); }, 150);
|
||||
}
|
||||
|
||||
// ---- Playlists
|
||||
|
||||
function requestPlaylists() {
|
||||
$('playlistHint').className = 'hint';
|
||||
$('playlistHint').textContent = t.loading;
|
||||
send({ event: 'sendToPlugin', action: actionUuid, context: uuid, payload: { command: 'requestPlaylists' } });
|
||||
}
|
||||
|
||||
function showPlaylists(payload) {
|
||||
var select = $('playlistSelect');
|
||||
var hint = $('playlistHint');
|
||||
while (select.firstChild) select.removeChild(select.firstChild);
|
||||
var placeholder = document.createElement('option');
|
||||
placeholder.value = '';
|
||||
placeholder.textContent = t.choose;
|
||||
select.appendChild(placeholder);
|
||||
if (!payload.ok) {
|
||||
hint.className = 'hint error';
|
||||
hint.textContent = payload.error === 'offline' || payload.error === 'remote' ? t.offline : t.failed;
|
||||
selectPlaylist(settings.playlistId || '');
|
||||
return;
|
||||
}
|
||||
payload.playlists.forEach(function (playlist) {
|
||||
var option = document.createElement('option');
|
||||
option.value = playlist.id;
|
||||
option.textContent = playlist.title;
|
||||
select.appendChild(option);
|
||||
});
|
||||
hint.className = 'hint';
|
||||
hint.textContent = payload.playlists.length + ' ' + t.count;
|
||||
selectPlaylist(settings.playlistId || '');
|
||||
}
|
||||
|
||||
function selectPlaylist(id) {
|
||||
var select = $('playlistSelect');
|
||||
var known = Array.prototype.some.call(select.options, function (option) { return option.value === id; });
|
||||
select.value = known ? id : '';
|
||||
}
|
||||
|
||||
$('playlistSelect').addEventListener('change', function () {
|
||||
var select = $('playlistSelect');
|
||||
if (!select.value) return;
|
||||
$('playlistId').value = select.value;
|
||||
save({ playlistTitle: select.options[select.selectedIndex].textContent });
|
||||
});
|
||||
$('playlistId').addEventListener('input', function () {
|
||||
// Manuell eingegebene ID: den Titel nur behalten, wenn die ID in der Liste vorkommt.
|
||||
selectPlaylist($('playlistId').value.trim());
|
||||
var select = $('playlistSelect');
|
||||
save({ playlistTitle: select.value ? select.options[select.selectedIndex].textContent : '' });
|
||||
});
|
||||
$('reload').addEventListener('click', requestPlaylists);
|
||||
['target', 'step', 'volume', 'seconds', 'tab', 'showTitle'].forEach(function (id) {
|
||||
$(id).addEventListener('input', function () { save(); });
|
||||
$(id).addEventListener('change', function () { save(); });
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user