Merge branch 'development' of github.com:Stremio/stremio-web into core-async-api

This commit is contained in:
nklhrstv 2022-09-12 20:00:06 +03:00
commit 418782e596
4 changed files with 154 additions and 3 deletions

View file

@ -4,7 +4,10 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-title" content="Stremio">
<link rel="icon" type="image/png" sizes="96x96" href="<%= htmlWebpackPlugin.options.faviconsPath %>/icon-96.png">
<link rel="apple-touch-icon" href="<%= htmlWebpackPlugin.options.faviconsPath %>/icon-96.png" />
<title>Stremio - All you can watch!</title>
<%= htmlWebpackPlugin.tags.headTags %>
</head>

View file

@ -18,7 +18,7 @@ const useSettings = require('./useSettings');
const styles = require('./styles');
const Player = ({ urlParams, queryParams }) => {
const { chromecast } = useServices();
const { chromecast, shell } = useServices();
const [forceTranscoding, maxAudioChannels] = React.useMemo(() => {
return [
queryParams.has('forceTranscoding'),
@ -258,6 +258,7 @@ const Player = ({ urlParams, queryParams }) => {
}
}, {
chromecastTransport: chromecast.active ? chromecast.transport : null,
shellTransport: shell.active ? shell.transport : null,
});
}
}, [streamingServer.baseUrl, player.selected, player.metaItem, forceTranscoding, maxAudioChannels, casting]);

View file

@ -1,14 +1,31 @@
// Copyright (C) 2017-2022 Smart code 203358507
const EventEmitter = require('eventemitter3');
const ShellTransport = require('./ShellTransport');
function Shell() {
let active = false;
let error = null;
let starting = false;
let transport = null;
const events = new EventEmitter();
function onTransportInit() {
active = true;
error = null;
starting = false;
onStateChanged();
}
function onTransportInitError(err) {
console.error(err);
active = false;
error = new Error(err);
starting = false;
onStateChanged();
transport = null;
}
function onStateChanged() {
events.emit('stateChanged');
}
@ -34,6 +51,13 @@ function Shell() {
get: function() {
return starting;
}
},
transport: {
configurable: false,
enumerable: true,
get: function() {
return transport;
}
}
});
@ -43,8 +67,10 @@ function Shell() {
}
active = false;
error = new Error('Stremio Shell API not available');
starting = false;
starting = true;
transport = new ShellTransport();
transport.on('init', onTransportInit);
transport.on('init-error', onTransportInitError);
onStateChanged();
};
this.stop = function() {

View file

@ -0,0 +1,121 @@
// Copyright (C) 2017-2022 Smart code 203358507
const EventEmitter = require('eventemitter3');
let shellAvailable = false;
const shellEvents = new EventEmitter();
const QtMsgTypes = {
signal: 1,
propertyUpdate: 2,
init: 3,
idle: 4,
debug: 5,
invokeMethod: 6,
connectToSignal: 7,
disconnectFromSignal: 8,
setProperty: 9,
response: 10,
};
const QtObjId = 'transport'; // the ID of our transport object
window.initShellComm = function () {
delete window.initShellComm;
shellEvents.emit('availabilityChanged');
};
const initialize = () => {
if(!window.qt) return Promise.reject('Qt API not found');
return new Promise((resolve) => {
function onShellAvailabilityChanged() {
shellEvents.off('availabilityChanged', onShellAvailabilityChanged);
shellAvailable = true;
resolve();
}
if (shellAvailable) {
onShellAvailabilityChanged();
} else {
shellEvents.on('availabilityChanged', onShellAvailabilityChanged);
}
});
};
function ShellTransport() {
const events = new EventEmitter();
this.props = {};
const shell = this;
initialize()
.then(() => {
const transport = window.qt && window.qt.webChannelTransport;
if (!transport) throw 'no viable transport found (qt.webChannelTransport)';
let id = 0;
function send(msg) {
msg.id = id++;
transport.send(JSON.stringify(msg));
}
transport.onmessage = function (message) {
const msg = JSON.parse(message.data);
if (msg.id === 0) {
const obj = msg.data[QtObjId];
obj.properties.slice(1).forEach(function (prop) {
shell.props[prop[1]] = prop[3];
});
if (typeof shell.props.shellVersion === 'string') {
shell.shellVersionArr = (
shell.props.shellVersion.match(/(\d+)\.(\d+)\.(\d+)/) || []
)
.slice(1, 4)
.map(Number);
}
events.emit('received-props', shell.props);
obj.signals.forEach(function (sig) {
send({
type: QtMsgTypes.connectToSignal,
object: QtObjId,
signal: sig[1],
});
});
const onEvent = obj.methods.filter(function (x) {
return x[0] === 'onEvent';
})[0];
shell.send = function (ev, args) {
send({
type: QtMsgTypes.invokeMethod,
object: QtObjId,
method: onEvent[1],
args: [ev, args || {}],
});
};
shell.send('app-ready', {}); // signal that we're ready to take events
}
if (msg.object === QtObjId && msg.type === QtMsgTypes.signal)
events.emit(msg.args[0], msg.args[1]);
events.emit('init');
};
send({ type: QtMsgTypes.init });
}) .catch((error) => {
events.emit('init-error', error);
});
this.on = function(name, listener) {
events.on(name, listener);
};
this.off = function(name, listener) {
events.off(name, listener);
};
this.removeAllListeners = function() {
events.removeAllListeners();
};
}
module.exports = ShellTransport;