Merge pull request #3567 from grafixeyehero/Convert-HomePage-to-react

This commit is contained in:
Bill Thornton 2022-09-02 17:47:23 -04:00 committed by GitHub
commit 0c8c1684b7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 186 additions and 204 deletions

View File

@ -8,7 +8,8 @@ type PageProps = {
isBackButtonEnabled?: boolean,
isMenuButtonEnabled?: boolean,
isNowPlayingBarEnabled?: boolean,
isThemeMediaSupported?: boolean
isThemeMediaSupported?: boolean,
backDropType?: string
};
/**
@ -23,7 +24,8 @@ const Page: FunctionComponent<PageProps & HTMLAttributes<HTMLDivElement>> = ({
isBackButtonEnabled = true,
isMenuButtonEnabled = false,
isNowPlayingBarEnabled = true,
isThemeMediaSupported = false
isThemeMediaSupported = false,
backDropType
}) => {
const element = useRef<HTMLDivElement>(null);
@ -61,8 +63,9 @@ const Page: FunctionComponent<PageProps & HTMLAttributes<HTMLDivElement>> = ({
data-role='page'
className={`page ${className}`}
data-title={title}
data-backbutton={`${isBackButtonEnabled}`}
data-menubutton={`${isMenuButtonEnabled}`}
data-backbutton={isBackButtonEnabled}
data-menubutton={isMenuButtonEnabled}
data-backdroptype={backDropType}
>
{children}
</div>

View File

@ -1,114 +0,0 @@
import { clearBackdrop } from '../backdrop/backdrop';
import * as mainTabsManager from '../maintabsmanager';
import layoutManager from '../layoutManager';
import '../../elements/emby-tabs/emby-tabs';
import LibraryMenu from '../../scripts/libraryMenu';
function onViewDestroy() {
const tabControllers = this.tabControllers;
if (tabControllers) {
tabControllers.forEach(function (t) {
if (t.destroy) {
t.destroy();
}
});
this.tabControllers = null;
}
this.view = null;
this.params = null;
this.currentTabController = null;
this.initialTabIndex = null;
}
class TabbedView {
constructor(view, params) {
this.tabControllers = [];
this.view = view;
this.params = params;
const self = this;
let currentTabIndex = parseInt(params.tab || this.getDefaultTabIndex(params.parentId));
this.initialTabIndex = currentTabIndex;
function validateTabLoad(index) {
return self.validateTabLoad ? self.validateTabLoad(index) : Promise.resolve();
}
function loadTab(index, previousIndex) {
validateTabLoad(index).then(function () {
self.getTabController(index).then(function (controller) {
const refresh = !controller.refreshed;
controller.onResume({
autoFocus: previousIndex == null && layoutManager.tv,
refresh: refresh
});
controller.refreshed = true;
currentTabIndex = index;
self.currentTabController = controller;
});
});
}
function getTabContainers() {
return view.querySelectorAll('.tabContent');
}
function onTabChange(e) {
const newIndex = parseInt(e.detail.selectedTabIndex);
const previousIndex = e.detail.previousIndex;
const previousTabController = previousIndex == null ? null : self.tabControllers[previousIndex];
if (previousTabController && previousTabController.onPause) {
previousTabController.onPause();
}
loadTab(newIndex, previousIndex);
}
view.addEventListener('viewbeforehide', this.onPause.bind(this));
view.addEventListener('viewbeforeshow', function () {
mainTabsManager.setTabs(view, currentTabIndex, self.getTabs, getTabContainers, null, onTabChange, false);
});
view.addEventListener('viewshow', function (e) {
self.onResume(e.detail);
});
view.addEventListener('viewdestroy', onViewDestroy.bind(this));
}
onResume() {
this.setTitle();
clearBackdrop();
const currentTabController = this.currentTabController;
if (!currentTabController) {
mainTabsManager.selectedTabIndex(this.initialTabIndex);
} else if (currentTabController && currentTabController.onResume) {
currentTabController.onResume({});
}
}
onPause() {
const currentTabController = this.currentTabController;
if (currentTabController && currentTabController.onPause) {
currentTabController.onPause();
}
}
setTitle() {
LibraryMenu.setTitle('');
}
}
export default TabbedView;

View File

@ -1,9 +0,0 @@
<div id="indexPage" style="outline: none;" data-role="page" data-dom-cache="true" class="page homePage libraryPage allLibraryPage backdropPage pageWithAbsoluteTabs withTabs" data-backdroptype="movie,series,book">
<div class="tabContent pageTabContent" id="homeTab" data-index="0">
<div class="sections"></div>
</div>
<div class="tabContent pageTabContent" id="favoritesTab" data-index="1">
<div class="sections"></div>
</div>
</div>

View File

@ -1,69 +0,0 @@
import TabbedView from '../components/tabbedview/tabbedview';
import globalize from '../scripts/globalize';
import '../elements/emby-tabs/emby-tabs';
import '../elements/emby-button/emby-button';
import '../elements/emby-scroller/emby-scroller';
import LibraryMenu from '../scripts/libraryMenu';
class HomeView extends TabbedView {
constructor(view, params) {
super(view, params);
}
setTitle() {
LibraryMenu.setTitle(null);
}
onPause() {
super.onPause(this);
document.querySelector('.skinHeader').classList.remove('noHomeButtonHeader');
}
onResume(options) {
super.onResume(this, options);
document.querySelector('.skinHeader').classList.add('noHomeButtonHeader');
}
getDefaultTabIndex() {
return 0;
}
getTabs() {
return [{
name: globalize.translate('Home')
}, {
name: globalize.translate('Favorites')
}];
}
getTabController(index) {
if (index == null) {
throw new Error('index cannot be null');
}
let depends = '';
switch (index) {
case 0:
depends = 'hometab';
break;
case 1:
depends = 'favorites';
}
const instance = this;
return import(/* webpackChunkName: "[request]" */ `../controllers/${depends}`).then(({ default: controllerFactory }) => {
let controller = instance.tabControllers[index];
if (!controller) {
controller = new controllerFactory(instance.view.querySelector(".tabContent[data-index='" + index + "']"), instance.params);
instance.tabControllers[index] = controller;
}
return controller;
});
}
}
export default HomeView;

177
src/routes/home.tsx Normal file
View File

@ -0,0 +1,177 @@
import React, { FunctionComponent, useCallback, useEffect, useMemo, useRef } from 'react';
import globalize from '../scripts/globalize';
import LibraryMenu from '../scripts/libraryMenu';
import { clearBackdrop } from '../components/backdrop/backdrop';
import layoutManager from '../components/layoutManager';
import * as mainTabsManager from '../components/maintabsmanager';
import '../elements/emby-tabs/emby-tabs';
import '../elements/emby-button/emby-button';
import '../elements/emby-scroller/emby-scroller';
import Page from '../components/Page';
type IProps = {
tab?: string;
}
type OnResumeOptions = {
autoFocus?: boolean;
refresh?: boolean
}
type ControllerProps = {
onResume: (
options: OnResumeOptions
) => void;
refreshed: boolean;
onPause: () => void;
destroy: () => void;
}
const Home: FunctionComponent<IProps> = (props: IProps) => {
const getDefaultTabIndex = () => {
return 0;
};
const tabController = useRef<ControllerProps | null>();
const currentTabIndex = useRef(parseInt(props.tab || getDefaultTabIndex().toString()));
const tabControllers = useMemo<ControllerProps[]>(() => [], []);
const initialTabIndex = useRef<number | null>(currentTabIndex.current);
const element = useRef<HTMLDivElement>(null);
const setTitle = () => {
LibraryMenu.setTitle(null);
};
const getTabs = () => {
return [{
name: globalize.translate('Home')
}, {
name: globalize.translate('Favorites')
}];
};
const getTabContainers = () => {
return element.current?.querySelectorAll('.tabContent');
};
const getTabController = useCallback((index: number) => {
if (index == null) {
throw new Error('index cannot be null');
}
let depends = '';
switch (index) {
case 0:
depends = 'hometab';
break;
case 1:
depends = 'favorites';
}
return import(/* webpackChunkName: "[request]" */ `../controllers/${depends}`).then(({ default: controllerFactory }) => {
let controller = tabControllers[index];
if (!controller) {
const tabContent = element.current?.querySelector(".tabContent[data-index='" + index + "']");
controller = new controllerFactory(tabContent, props);
tabControllers[index] = controller;
}
return controller;
});
}, [props, tabControllers]);
const onViewDestroy = useCallback(() => {
if (tabControllers) {
tabControllers.forEach(function (t) {
if (t.destroy) {
t.destroy();
}
});
}
tabController.current = null;
initialTabIndex.current = null;
}, [tabControllers]);
const loadTab = useCallback((index: number, previousIndex: number | null) => {
getTabController(index).then((controller) => {
const refresh = !controller.refreshed;
controller.onResume({
autoFocus: previousIndex == null && layoutManager.tv,
refresh: refresh
});
controller.refreshed = true;
currentTabIndex.current = index;
tabController.current = controller;
});
}, [getTabController]);
const onTabChange = useCallback((e: { detail: { selectedTabIndex: string; previousIndex: number | null }; }) => {
const newIndex = parseInt(e.detail.selectedTabIndex);
const previousIndex = e.detail.previousIndex;
const previousTabController = previousIndex == null ? null : tabControllers[previousIndex];
if (previousTabController && previousTabController.onPause) {
previousTabController.onPause();
}
loadTab(newIndex, previousIndex);
}, [loadTab, tabControllers]);
const onResume = useCallback(() => {
setTitle();
clearBackdrop();
const currentTabController = tabController.current;
if (!currentTabController) {
mainTabsManager.selectedTabIndex(initialTabIndex.current);
} else if (currentTabController && currentTabController.onResume) {
currentTabController.onResume({});
}
(document.querySelector('.skinHeader') as HTMLDivElement).classList.add('noHomeButtonHeader');
}, []);
const onPause = useCallback(() => {
const currentTabController = tabController.current;
if (currentTabController && currentTabController.onPause) {
currentTabController.onPause();
}
(document.querySelector('.skinHeader') as HTMLDivElement).classList.remove('noHomeButtonHeader');
}, []);
useEffect(() => {
mainTabsManager.setTabs(element.current, currentTabIndex.current, getTabs, getTabContainers, null, onTabChange, false);
onResume();
return () => {
onPause();
onViewDestroy();
};
}, [onPause, onResume, onTabChange, onViewDestroy]);
return (
<div ref={element}>
<Page
id='indexPage'
className='mainAnimatedPage homePage libraryPage allLibraryPage backdropPage pageWithAbsoluteTabs withTabs'
isBackButtonEnabled={false}
backDropType='movie,series,book'
>
<div className='tabContent pageTabContent' id='homeTab' data-index='0'>
<div className='sections'></div>
</div>
<div className='tabContent pageTabContent' id='favoritesTab' data-index='1'>
<div className='sections'></div>
</div>
</Page>
</div>
);
};
export default Home;

View File

@ -10,6 +10,7 @@ import UserParentalControl from './user/userparentalcontrol';
import UserPassword from './user/userpassword';
import UserProfile from './user/userprofile';
import UserProfiles from './user/userprofiles';
import Home from './home';
const AppRoutes = () => (
<Routes>
@ -18,6 +19,7 @@ const AppRoutes = () => (
<Route path='/' element={<ConnectionRequired />}>
<Route path='search.html' element={<Search />} />
<Route path='userprofile.html' element={<UserProfile />} />
<Route path='home.html' element={<Home />} />
</Route>
{/* Admin routes */}

View File

@ -293,14 +293,6 @@ import { appRouter } from '../components/appRouter';
controller: 'dashboard/plugins/repositories/index'
});
defineRoute({
alias: '/home.html',
path: 'home.html',
autoFocus: false,
controller: 'home',
type: 'home'
});
defineRoute({
alias: '/list.html',
path: 'list.html',