mirror of
https://github.com/Stremio/stremio-web.git
synced 2026-05-11 20:40:54 +00:00
Merge pull request #1261 from Stremio/refactor/file-drop-logic
Some checks are pending
Build / build (push) Waiting to run
Some checks are pending
Build / build (push) Waiting to run
Dev: Move file drop logic to provider
This commit is contained in:
commit
5f0ecd2a3e
15 changed files with 110 additions and 198 deletions
|
|
@ -5,9 +5,9 @@ const React = require('react');
|
||||||
const { useTranslation } = require('react-i18next');
|
const { useTranslation } = require('react-i18next');
|
||||||
const { useCore } = require('stremio/core');
|
const { useCore } = require('stremio/core');
|
||||||
const { Router } = require('stremio-router');
|
const { Router } = require('stremio-router');
|
||||||
const { Shell, Chromecast, DragAndDrop, KeyboardShortcuts, ServicesProvider, GamepadProvider } = require('stremio/services');
|
const { Shell, Chromecast, KeyboardShortcuts, ServicesProvider, GamepadProvider } = require('stremio/services');
|
||||||
const { NotFound } = require('stremio/routes');
|
const { NotFound } = require('stremio/routes');
|
||||||
const { FileDropProvider, FullscreenProvider, PlatformProvider, ToastProvider, TooltipProvider, ShortcutsProvider, CONSTANTS, useShell, useBinaryState, useProfile, withCoreSuspender } = require('stremio/common');
|
const { FullscreenProvider, PlatformProvider, ToastProvider, TooltipProvider, ShortcutsProvider, CONSTANTS, useShell, useBinaryState, useProfile, withCoreSuspender, onFileDrop } = require('stremio/common');
|
||||||
const ServicesToaster = require('./ServicesToaster');
|
const ServicesToaster = require('./ServicesToaster');
|
||||||
const DeepLinkHandler = require('./DeepLinkHandler');
|
const DeepLinkHandler = require('./DeepLinkHandler');
|
||||||
const SearchParamsHandler = require('./SearchParamsHandler');
|
const SearchParamsHandler = require('./SearchParamsHandler');
|
||||||
|
|
@ -34,7 +34,6 @@ const App = () => {
|
||||||
shell: new Shell(),
|
shell: new Shell(),
|
||||||
chromecast: new Chromecast(),
|
chromecast: new Chromecast(),
|
||||||
keyboardShortcuts: new KeyboardShortcuts(),
|
keyboardShortcuts: new KeyboardShortcuts(),
|
||||||
dragAndDrop: new DragAndDrop({ core })
|
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
const [shortcutModalOpen,, closeShortcutsModal, toggleShortcutModal] = useBinaryState(false);
|
const [shortcutModalOpen,, closeShortcutsModal, toggleShortcutModal] = useBinaryState(false);
|
||||||
|
|
@ -51,6 +50,16 @@ const App = () => {
|
||||||
}
|
}
|
||||||
}, [toggleShortcutModal, toggleGamepadModal]);
|
}, [toggleShortcutModal, toggleGamepadModal]);
|
||||||
|
|
||||||
|
onFileDrop(['application/x-bittorrent'], (file, buffer) => {
|
||||||
|
core.transport.dispatch({
|
||||||
|
action: 'StreamingServer',
|
||||||
|
args: {
|
||||||
|
action: 'CreateTorrent',
|
||||||
|
args: Array.from(new Uint8Array(buffer))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
let prevPath = window.location.hash.slice(1);
|
let prevPath = window.location.hash.slice(1);
|
||||||
const onLocationHashChange = () => {
|
const onLocationHashChange = () => {
|
||||||
|
|
@ -82,13 +91,11 @@ const App = () => {
|
||||||
services.shell.start();
|
services.shell.start();
|
||||||
services.chromecast.start();
|
services.chromecast.start();
|
||||||
services.keyboardShortcuts.start();
|
services.keyboardShortcuts.start();
|
||||||
services.dragAndDrop.start();
|
|
||||||
window.services = services;
|
window.services = services;
|
||||||
return () => {
|
return () => {
|
||||||
services.shell.stop();
|
services.shell.stop();
|
||||||
services.chromecast.stop();
|
services.chromecast.stop();
|
||||||
services.keyboardShortcuts.stop();
|
services.keyboardShortcuts.stop();
|
||||||
services.dragAndDrop.stop();
|
|
||||||
services.chromecast.off('stateChanged', onChromecastStateChange);
|
services.chromecast.off('stateChanged', onChromecastStateChange);
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
@ -174,29 +181,27 @@ const App = () => {
|
||||||
<PlatformProvider>
|
<PlatformProvider>
|
||||||
<ToastProvider className={styles['toasts-container']}>
|
<ToastProvider className={styles['toasts-container']}>
|
||||||
<TooltipProvider className={styles['tooltip-container']}>
|
<TooltipProvider className={styles['tooltip-container']}>
|
||||||
<FileDropProvider className={styles['file-drop-container']}>
|
<GamepadProvider enabled={gamepadSupportEnabled} onGuide={toggleGamepadModal}>
|
||||||
<GamepadProvider enabled={gamepadSupportEnabled} onGuide={toggleGamepadModal}>
|
<ShortcutsProvider onShortcut={onShortcut}>
|
||||||
<ShortcutsProvider onShortcut={onShortcut}>
|
<FullscreenProvider>
|
||||||
<FullscreenProvider>
|
{
|
||||||
{
|
shortcutModalOpen && <ShortcutsModal onClose={closeShortcutsModal}/>
|
||||||
shortcutModalOpen && <ShortcutsModal onClose={closeShortcutsModal}/>
|
}
|
||||||
}
|
{
|
||||||
{
|
gamepadModalOpen && <GamepadModal onClose={closeGamepadModal}/>
|
||||||
gamepadModalOpen && <GamepadModal onClose={closeGamepadModal}/>
|
}
|
||||||
}
|
<ServicesToaster />
|
||||||
<ServicesToaster />
|
<DeepLinkHandler />
|
||||||
<DeepLinkHandler />
|
<SearchParamsHandler />
|
||||||
<SearchParamsHandler />
|
<UpdaterBanner className={styles['updater-banner-container']} />
|
||||||
<UpdaterBanner className={styles['updater-banner-container']} />
|
<RouterWithProtectedRoutes
|
||||||
<RouterWithProtectedRoutes
|
className={styles['router']}
|
||||||
className={styles['router']}
|
viewsConfig={routerViewsConfig}
|
||||||
viewsConfig={routerViewsConfig}
|
onPathNotMatch={onPathNotMatch}
|
||||||
onPathNotMatch={onPathNotMatch}
|
/>
|
||||||
/>
|
</FullscreenProvider>
|
||||||
</FullscreenProvider>
|
</ShortcutsProvider>
|
||||||
</ShortcutsProvider>
|
</GamepadProvider>
|
||||||
</GamepadProvider>
|
|
||||||
</FileDropProvider>
|
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
</ToastProvider>
|
</ToastProvider>
|
||||||
</PlatformProvider>
|
</PlatformProvider>
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
// Copyright (C) 2017-2023 Smart code 203358507
|
// Copyright (C) 2017-2023 Smart code 203358507
|
||||||
|
|
||||||
const React = require('react');
|
const React = require('react');
|
||||||
const { useServices } = require('stremio/services');
|
|
||||||
const { useCore } = require('stremio/core');
|
const { useCore } = require('stremio/core');
|
||||||
const { useToast } = require('stremio/common');
|
const { useToast, useFileDrop } = require('stremio/common');
|
||||||
|
|
||||||
const ServicesToaster = () => {
|
const ServicesToaster = () => {
|
||||||
const { dragAndDrop } = useServices();
|
|
||||||
const core = useCore();
|
const core = useCore();
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
|
const filedrop = useFileDrop();
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const onCoreEvent = (name, data) => {
|
const onCoreEvent = (name, data) => {
|
||||||
switch (name) {
|
switch (name) {
|
||||||
|
|
@ -53,21 +53,23 @@ const ServicesToaster = () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const onDragAndDropError = (error) => {
|
const onFileDrop = (file, buffer, supported) => {
|
||||||
toast.show({
|
if (!supported) {
|
||||||
type: 'error',
|
toast.show({
|
||||||
title: error.message,
|
type: 'error',
|
||||||
message: error.file?.name,
|
title: 'Unsupported file',
|
||||||
timeout: 4000
|
message: file.name,
|
||||||
});
|
timeout: 4000
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
core.on('event', onCoreEvent);
|
core.on('event', onCoreEvent);
|
||||||
core.on('error', onCoreError);
|
core.on('error', onCoreError);
|
||||||
dragAndDrop.on('error', onDragAndDropError);
|
filedrop.on('*', onFileDrop);
|
||||||
return () => {
|
return () => {
|
||||||
core.off('event', onCoreEvent);
|
core.off('event', onCoreEvent);
|
||||||
core.off('error', onCoreError);
|
core.off('error', onCoreError);
|
||||||
dragAndDrop.off('error', onDragAndDropError);
|
filedrop.off('*', onFileDrop);
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -213,22 +213,6 @@ html {
|
||||||
transition: opacity 0.1s ease-out;
|
transition: opacity 0.1s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-drop-container {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
border-radius: 1rem;
|
|
||||||
border: 0.5rem dashed transparent;
|
|
||||||
pointer-events: none;
|
|
||||||
transition: border-color 0.25s ease-out;
|
|
||||||
|
|
||||||
&:global(.active) {
|
|
||||||
border-color: var(--primary-accent-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.updater-banner-container {
|
.updater-banner-container {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ const ICON_FOR_TYPE = new Map([
|
||||||
const MIME_SIGNATURES = {
|
const MIME_SIGNATURES = {
|
||||||
'application/x-subrip': ['310D0A', '310A'],
|
'application/x-subrip': ['310D0A', '310A'],
|
||||||
'text/vtt': ['574542565454'],
|
'text/vtt': ['574542565454'],
|
||||||
|
'application/x-bittorrent': ['64'],
|
||||||
};
|
};
|
||||||
|
|
||||||
const SUPPORTED_LOCAL_SUBTITLES = [
|
const SUPPORTED_LOCAL_SUBTITLES = [
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
import React, { createContext, useCallback, useContext, useEffect, useState } from 'react';
|
import React, { createContext, useContext, useEffect, useRef, useState } from 'react';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { isFileType } from './utils';
|
import { isFileType, isFileTypeSupported } from './utils';
|
||||||
|
import styles from './styles.less';
|
||||||
|
|
||||||
export type FileType = string;
|
export type FileType = string;
|
||||||
export type FileDropListener = (filename: string, buffer: ArrayBuffer) => void;
|
export type FileDropListener = (file: File, buffer: ArrayBuffer, supported: boolean) => void;
|
||||||
|
|
||||||
type FileDropContext = {
|
type FileDropContext = {
|
||||||
on: (type: FileType, listener: FileDropListener) => void,
|
on: (type: FileType, listener: FileDropListener) => void,
|
||||||
|
|
@ -13,12 +14,11 @@ type FileDropContext = {
|
||||||
const FileDropContext = createContext({} as FileDropContext);
|
const FileDropContext = createContext({} as FileDropContext);
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
className: string,
|
children: React.ReactNode,
|
||||||
children: JSX.Element,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const FileDropProvider = ({ className, children }: Props) => {
|
const FileDropProvider = ({ children }: Props) => {
|
||||||
const [listeners, setListeners] = useState<[FileType, FileDropListener][]>([]);
|
const listeners = useRef<[FileType, FileDropListener][]>([]);
|
||||||
const [active, setActive] = useState(false);
|
const [active, setActive] = useState(false);
|
||||||
|
|
||||||
const onDragOver = (event: DragEvent) => {
|
const onDragOver = (event: DragEvent) => {
|
||||||
|
|
@ -30,38 +30,38 @@ const FileDropProvider = ({ className, children }: Props) => {
|
||||||
setActive(false);
|
setActive(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onDrop = useCallback((event: DragEvent) => {
|
|
||||||
event.preventDefault();
|
|
||||||
const { dataTransfer } = event;
|
|
||||||
|
|
||||||
if (dataTransfer && dataTransfer?.files.length > 0) {
|
|
||||||
const file = dataTransfer.files[0];
|
|
||||||
|
|
||||||
file
|
|
||||||
.arrayBuffer()
|
|
||||||
.then((buffer) => {
|
|
||||||
listeners
|
|
||||||
.filter(([type]) => file.type ? type === file.type : isFileType(buffer, type))
|
|
||||||
.forEach(([, listener]) => listener(file.name, buffer));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setActive(false);
|
|
||||||
}, [listeners]);
|
|
||||||
|
|
||||||
const on = (type: FileType, listener: FileDropListener) => {
|
const on = (type: FileType, listener: FileDropListener) => {
|
||||||
setListeners((listeners) => {
|
listeners.current = [...listeners.current, [type, listener]];
|
||||||
return [...listeners, [type, listener]];
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const off = (type: FileType, listener: FileDropListener) => {
|
const off = (type: FileType, listener: FileDropListener) => {
|
||||||
setListeners((listeners) => {
|
listeners.current = listeners.current.filter(([key, value]) => key !== type && value !== listener);
|
||||||
return listeners.filter(([key, value]) => key !== type && value !== listener);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
const onDrop = (event: DragEvent) => {
|
||||||
|
event.preventDefault();
|
||||||
|
const { dataTransfer } = event;
|
||||||
|
|
||||||
|
if (dataTransfer && dataTransfer?.files.length > 0) {
|
||||||
|
const file = dataTransfer.files[0];
|
||||||
|
|
||||||
|
file
|
||||||
|
.arrayBuffer()
|
||||||
|
.then((buffer) => {
|
||||||
|
listeners.current
|
||||||
|
.filter(([type]) => type === '*')
|
||||||
|
.forEach(([, listener]) => listener(file, buffer, isFileTypeSupported(buffer)));
|
||||||
|
listeners.current
|
||||||
|
.filter(([type]) => type !== '*' && (file.type ? type === file.type : isFileType(buffer, type)))
|
||||||
|
.forEach(([, listener]) => listener(file, buffer, true));
|
||||||
|
})
|
||||||
|
.catch(console.error);
|
||||||
|
}
|
||||||
|
|
||||||
|
setActive(false);
|
||||||
|
};
|
||||||
|
|
||||||
window.addEventListener('dragover', onDragOver);
|
window.addEventListener('dragover', onDragOver);
|
||||||
window.addEventListener('dragleave', onDragLeave);
|
window.addEventListener('dragleave', onDragLeave);
|
||||||
window.addEventListener('drop', onDrop);
|
window.addEventListener('drop', onDrop);
|
||||||
|
|
@ -71,12 +71,12 @@ const FileDropProvider = ({ className, children }: Props) => {
|
||||||
window.removeEventListener('dragleave', onDragLeave);
|
window.removeEventListener('dragleave', onDragLeave);
|
||||||
window.removeEventListener('drop', onDrop);
|
window.removeEventListener('drop', onDrop);
|
||||||
};
|
};
|
||||||
}, [onDrop]);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FileDropContext.Provider value={{ on, off }}>
|
<FileDropContext.Provider value={{ on, off }}>
|
||||||
{ children }
|
{ children }
|
||||||
<div className={classNames(className, { 'active': active })} />
|
<div className={classNames(styles['file-drop-container'], { 'active': active })} />
|
||||||
</FileDropContext.Provider>
|
</FileDropContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ const onFileDrop = (types: FileType[], listener: FileDropListener) => {
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
types.forEach((type) => on(type, listener));
|
types.forEach((type) => on(type, listener));
|
||||||
|
|
||||||
return () => types.forEach((type) => off(type, listener));
|
return () => types.forEach((type) => off(type, listener));
|
||||||
}, []);
|
}, []);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
15
src/common/FileDrop/styles.less
Normal file
15
src/common/FileDrop/styles.less
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
.file-drop-container {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
border-radius: 1rem;
|
||||||
|
border: 0.5rem dashed transparent;
|
||||||
|
pointer-events: none;
|
||||||
|
transition: border-color 0.25s ease-out;
|
||||||
|
|
||||||
|
&:global(.active) {
|
||||||
|
border-color: var(--primary-accent-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -14,6 +14,11 @@ const isFileType = (buffer: ArrayBuffer, type: string) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isFileTypeSupported = (buffer: ArrayBuffer) => {
|
||||||
|
return Object.keys(SIGNATURES).some((type) => isFileType(buffer, type));
|
||||||
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
isFileType,
|
isFileType,
|
||||||
|
isFileTypeSupported,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// Copyright (C) 2017-2023 Smart code 203358507
|
// Copyright (C) 2017-2023 Smart code 203358507
|
||||||
|
|
||||||
const { FileDropProvider, onFileDrop } = require('./FileDrop');
|
const { FileDropProvider, useFileDrop, onFileDrop } = require('./FileDrop');
|
||||||
const { FullscreenProvider, useFullscreen } = require('./Fullscreen');
|
const { FullscreenProvider, useFullscreen } = require('./Fullscreen');
|
||||||
const { PlatformProvider, usePlatform } = require('./Platform');
|
const { PlatformProvider, usePlatform } = require('./Platform');
|
||||||
const { ToastProvider, useToast } = require('./Toast');
|
const { ToastProvider, useToast } = require('./Toast');
|
||||||
|
|
@ -33,6 +33,7 @@ const { default: useLanguageSorting } = require('./useLanguageSorting');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
FileDropProvider,
|
FileDropProvider,
|
||||||
|
useFileDrop,
|
||||||
onFileDrop,
|
onFileDrop,
|
||||||
FullscreenProvider,
|
FullscreenProvider,
|
||||||
PlatformProvider,
|
PlatformProvider,
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ const { initReactI18next } = require('react-i18next');
|
||||||
const stremioTranslations = require('stremio-translations');
|
const stremioTranslations = require('stremio-translations');
|
||||||
const App = require('./App');
|
const App = require('./App');
|
||||||
const { CoreProvider } = require('./core');
|
const { CoreProvider } = require('./core');
|
||||||
|
const { FileDropProvider } = require('./common');
|
||||||
|
|
||||||
const translations = Object.fromEntries(Object.entries(stremioTranslations()).map(([key, value]) => [key, {
|
const translations = Object.fromEntries(Object.entries(stremioTranslations()).map(([key, value]) => [key, {
|
||||||
translation: value
|
translation: value
|
||||||
|
|
@ -42,7 +43,9 @@ const appInfo = {
|
||||||
const root = ReactDOM.createRoot(document.getElementById('app'));
|
const root = ReactDOM.createRoot(document.getElementById('app'));
|
||||||
root.render(
|
root.render(
|
||||||
<CoreProvider appInfo={appInfo}>
|
<CoreProvider appInfo={appInfo}>
|
||||||
<App />
|
<FileDropProvider>
|
||||||
|
<App />
|
||||||
|
</FileDropProvider>
|
||||||
</CoreProvider>
|
</CoreProvider>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -151,8 +151,8 @@ const useSubtitles = ({
|
||||||
streamStateChanged({ subtitleOffset: offset });
|
streamStateChanged({ subtitleOffset: offset });
|
||||||
}, [streamStateChanged, video]);
|
}, [streamStateChanged, video]);
|
||||||
|
|
||||||
onFileDrop(CONSTANTS.SUPPORTED_LOCAL_SUBTITLES, (filename: string, buffer: ArrayBuffer) => {
|
onFileDrop(CONSTANTS.SUPPORTED_LOCAL_SUBTITLES, (file: File, buffer: ArrayBuffer) => {
|
||||||
videoRef.current.addLocalSubtitles(filename, buffer);
|
videoRef.current.addLocalSubtitles(file.name, buffer);
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
||||||
|
|
@ -1,95 +0,0 @@
|
||||||
// Copyright (C) 2017-2023 Smart code 203358507
|
|
||||||
|
|
||||||
const EventEmitter = require('eventemitter3');
|
|
||||||
|
|
||||||
function DragAndDrop({ core }) {
|
|
||||||
let active = false;
|
|
||||||
|
|
||||||
const events = new EventEmitter();
|
|
||||||
|
|
||||||
function onDragOver(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
}
|
|
||||||
async function onDrop(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
if (event.dataTransfer.files instanceof FileList && event.dataTransfer.files.length > 0) {
|
|
||||||
const file = event.dataTransfer.files[0];
|
|
||||||
switch (file.type) {
|
|
||||||
case 'application/x-bittorrent': {
|
|
||||||
try {
|
|
||||||
const torrent = await file.arrayBuffer();
|
|
||||||
core.transport.dispatch({
|
|
||||||
action: 'StreamingServer',
|
|
||||||
args: {
|
|
||||||
action: 'CreateTorrent',
|
|
||||||
args: Array.from(new Uint8Array(torrent))
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (_error) {
|
|
||||||
events.emit('error', {
|
|
||||||
message: 'Failed to process file',
|
|
||||||
file: {
|
|
||||||
name: file.name,
|
|
||||||
type: file.type
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'application/x-subrip':
|
|
||||||
break;
|
|
||||||
case 'text/vtt':
|
|
||||||
break;
|
|
||||||
case '':
|
|
||||||
break;
|
|
||||||
default: {
|
|
||||||
events.emit('error', {
|
|
||||||
message: 'Unsupported file',
|
|
||||||
file: {
|
|
||||||
name: file.name,
|
|
||||||
type: file.type
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function onStateChanged() {
|
|
||||||
events.emit('stateChanged');
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.defineProperties(this, {
|
|
||||||
active: {
|
|
||||||
configurable: false,
|
|
||||||
enumerable: true,
|
|
||||||
get: function() {
|
|
||||||
return active;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
this.start = function() {
|
|
||||||
if (active) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
window.addEventListener('dragover', onDragOver);
|
|
||||||
window.addEventListener('drop', onDrop);
|
|
||||||
active = true;
|
|
||||||
onStateChanged();
|
|
||||||
};
|
|
||||||
this.stop = function() {
|
|
||||||
window.removeEventListener('dragover', onDragOver);
|
|
||||||
window.removeEventListener('drop', onDrop);
|
|
||||||
active = false;
|
|
||||||
onStateChanged();
|
|
||||||
};
|
|
||||||
this.on = function(name, listener) {
|
|
||||||
events.on(name, listener);
|
|
||||||
};
|
|
||||||
this.off = function(name, listener) {
|
|
||||||
events.off(name, listener);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = DragAndDrop;
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
// Copyright (C) 2017-2023 Smart code 203358507
|
|
||||||
|
|
||||||
const DragAndDrop = require('./DragAndDrop');
|
|
||||||
|
|
||||||
module.exports = DragAndDrop;
|
|
||||||
1
src/services/ServicesContext/types.d.ts
vendored
1
src/services/ServicesContext/types.d.ts
vendored
|
|
@ -2,5 +2,4 @@ type ServicesContext = {
|
||||||
shell: any,
|
shell: any,
|
||||||
chromecast: any,
|
chromecast: any,
|
||||||
keyboardShortcuts: any,
|
keyboardShortcuts: any,
|
||||||
dragAndDrop: any,
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
// Copyright (C) 2017-2023 Smart code 203358507
|
// Copyright (C) 2017-2023 Smart code 203358507
|
||||||
|
|
||||||
const Chromecast = require('./Chromecast');
|
const Chromecast = require('./Chromecast');
|
||||||
const DragAndDrop = require('./DragAndDrop');
|
|
||||||
const KeyboardShortcuts = require('./KeyboardShortcuts');
|
const KeyboardShortcuts = require('./KeyboardShortcuts');
|
||||||
const { ServicesProvider, useServices } = require('./ServicesContext');
|
const { ServicesProvider, useServices } = require('./ServicesContext');
|
||||||
const { GamepadProvider, useGamepad } = require('./GamepadContext');
|
const { GamepadProvider, useGamepad } = require('./GamepadContext');
|
||||||
|
|
@ -9,7 +8,6 @@ const Shell = require('./Shell');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
Chromecast,
|
Chromecast,
|
||||||
DragAndDrop,
|
|
||||||
KeyboardShortcuts,
|
KeyboardShortcuts,
|
||||||
ServicesProvider,
|
ServicesProvider,
|
||||||
useServices,
|
useServices,
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue