1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-24 10:27:10 +02:00
joplin/packages/app-desktop/gui/Root.tsx

276 lines
8.6 KiB
TypeScript
Raw Normal View History

import app from '../app';
import { AppState, AppStateDialog } from '../app.reducer';
import MainScreen from './MainScreen/MainScreen';
import ConfigScreen from './ConfigScreen/ConfigScreen';
import StatusScreen from './StatusScreen/StatusScreen';
import OneDriveLoginScreen from './OneDriveLoginScreen';
import DropboxLoginScreen from './DropboxLoginScreen';
import ErrorBoundary from './ErrorBoundary';
import { themeStyle } from '@joplin/lib/theme';
import { Size } from './ResizableLayout/utils/types';
import MenuBar from './MenuBar';
import { _ } from '@joplin/lib/locale';
const React = require('react');
2022-11-15 11:09:43 +02:00
const { createRoot } = require('react-dom/client');
2017-11-04 18:40:34 +02:00
const { connect, Provider } = require('react-redux');
import Setting from '@joplin/lib/models/Setting';
import shim from '@joplin/lib/shim';
import ClipperServer from '@joplin/lib/ClipperServer';
import DialogTitle from './DialogTitle';
import DialogButtonRow, { ButtonSpec, ClickEvent, ClickEventHandler } from './DialogButtonRow';
import Dialog from './Dialog';
2021-08-16 16:20:14 +02:00
import SyncWizardDialog from './SyncWizard/Dialog';
import MasterPasswordDialog from './MasterPasswordDialog/Dialog';
import EditFolderDialog from './EditFolderDialog/Dialog';
import PdfViewer from './PdfViewer';
import StyleSheetContainer from './StyleSheets/StyleSheetContainer';
import ImportScreen from './ImportScreen';
const { ResourceScreen } = require('./ResourceScreen.js');
import Navigator from './Navigator';
import WelcomeUtils from '@joplin/lib/WelcomeUtils';
import JoplinCloudLoginScreen from './JoplinCloudLoginScreen';
2020-09-15 15:01:07 +02:00
const { ThemeProvider, StyleSheetManager, createGlobalStyle } = require('styled-components');
const bridge = require('@electron/remote').require('./bridge').default;
interface Props {
themeId: number;
appState: string;
// eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied
dispatch: Function;
size: Size;
zoomFactor: number;
needApiAuth: boolean;
dialogs: AppStateDialog[];
}
interface ModalDialogProps {
themeId: number;
message: string;
buttonSpecs: ButtonSpec[];
onClick: ClickEventHandler;
}
2021-08-16 16:20:14 +02:00
interface RegisteredDialogProps {
themeId: number;
key: string;
// eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied
2021-08-16 16:20:14 +02:00
dispatch: Function;
}
interface RegisteredDialog {
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
render: (props: RegisteredDialogProps, customProps: any)=> any;
2021-08-16 16:20:14 +02:00
}
const registeredDialogs: Record<string, RegisteredDialog> = {
syncWizard: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
render: (props: RegisteredDialogProps, customProps: any) => {
return <SyncWizardDialog key={props.key} dispatch={props.dispatch} themeId={props.themeId} {...customProps}/>;
2021-08-16 16:20:14 +02:00
},
},
masterPassword: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
render: (props: RegisteredDialogProps, customProps: any) => {
return <MasterPasswordDialog key={props.key} dispatch={props.dispatch} themeId={props.themeId} {...customProps}/>;
},
},
editFolder: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
render: (props: RegisteredDialogProps, customProps: any) => {
return <EditFolderDialog key={props.key} dispatch={props.dispatch} themeId={props.themeId} {...customProps}/>;
},
},
pdfViewer: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
render: (props: RegisteredDialogProps, customProps: any) => {
return <PdfViewer key={props.key} dispatch={props.dispatch} themeId={props.themeId} {...customProps}/>;
},
},
2021-08-16 16:20:14 +02:00
};
2020-09-15 15:01:07 +02:00
const GlobalStyle = createGlobalStyle`
* {
box-sizing: border-box;
}
2020-09-15 15:01:07 +02:00
`;
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
let wcsTimeoutId_: any = null;
2017-11-12 01:13:14 +02:00
async function initialize() {
bridge().window().on('resize', () => {
if (wcsTimeoutId_) shim.clearTimeout(wcsTimeoutId_);
wcsTimeoutId_ = shim.setTimeout(() => {
store.dispatch({
type: 'WINDOW_CONTENT_SIZE_SET',
size: bridge().windowContentSize(),
});
wcsTimeoutId_ = null;
}, 10);
});
// Need to dispatch this to make sure the components are
// displayed at the right size. The windowContentSize is
// also set in the store default state, but at that point
// the window might not be at its final size.
store.dispatch({
type: 'WINDOW_CONTENT_SIZE_SET',
size: bridge().windowContentSize(),
});
store.dispatch({
type: 'NOTE_VISIBLE_PANES_SET',
panes: Setting.value('noteVisiblePanes'),
});
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
class RootComponent extends React.Component<Props, any> {
public async componentDidMount() {
2022-07-23 11:33:12 +02:00
if (this.props.appState === 'starting') {
this.props.dispatch({
2017-11-08 23:22:24 +02:00
type: 'APP_STATE_SET',
state: 'initializing',
});
await initialize();
this.props.dispatch({
2017-11-08 23:22:24 +02:00
type: 'APP_STATE_SET',
state: 'ready',
});
}
await WelcomeUtils.install(Setting.value('locale'), this.props.dispatch);
}
private renderModalMessage(props: ModalDialogProps) {
if (!props) return null;
const renderContent = () => {
return (
<div>
<DialogTitle title={_('Confirmation')}/>
<p>{props.message}</p>
<DialogButtonRow
themeId={props.themeId}
onClick={props.onClick}
okButtonShow={false}
cancelButtonShow={false}
customButtons={props.buttonSpecs}
/>
</div>
);
};
return <Dialog>{renderContent()}</Dialog>;
}
private modalDialogProps(): ModalDialogProps {
if (!this.props.needApiAuth) return null;
let message = '';
const buttonSpecs: ButtonSpec[] = [];
let onClick: ClickEventHandler = null;
if (this.props.needApiAuth) {
message = _('The Web Clipper needs your authorisation to access your data.');
buttonSpecs.push({ name: 'ok', label: _('Grant authorisation') });
buttonSpecs.push({ name: 'cancel', label: _('Reject') });
onClick = (event: ClickEvent) => {
ClipperServer.instance().api.acceptAuthToken(event.buttonName === 'ok');
};
} else {
return null;
}
return {
themeId: this.props.themeId,
buttonSpecs,
message,
onClick,
};
}
2021-08-16 16:20:14 +02:00
private renderDialogs() {
const props: Props = this.props;
if (!props.dialogs.length) return null;
2021-08-16 16:20:14 +02:00
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
2021-08-16 16:20:14 +02:00
const output: any[] = [];
for (const dialog of props.dialogs) {
2021-08-16 16:20:14 +02:00
const md = registeredDialogs[dialog.name];
if (!md) throw new Error(`Unknown dialog: ${dialog.name}`);
output.push(md.render({
key: dialog.name,
themeId: props.themeId,
dispatch: props.dispatch,
}, dialog.props));
2021-08-16 16:20:14 +02:00
}
return output;
}
public render() {
const navigatorStyle = {
Desktop: Resolves #2162: Added zoom controls to the application menu commit 2285000a6ac09eed12d4215d71b4f88f1660411a Author: Laurent Cozic <laurent@cozic.net> Date: Tue Feb 11 22:25:12 2020 +0000 Deprecate style.zoom commit 3a6da4ffee280dd93eee1f4ae8891a72ecaea8e3 Author: Laurent Cozic <laurent@cozic.net> Date: Tue Feb 11 22:13:01 2020 +0000 Fix zoom branch commit c46c080a069d213e4f75c261a12cbed47ed8de8f Author: Elizabeth Schafer <elizabeth.schafer.wenk@gmail.com> Date: Sun Dec 15 10:37:10 2019 -0500 Using componentDidUpdate rather than deprecated componentWillRecieveProps https://github.com/laurent22/joplin/pull/2165#discussion_r357441917 commit 069444fd02e18f6542e6483d9fffae8a941ab59c Author: Elizabeth Schafer <elizabeth.schafer.wenk@gmail.com> Date: Sun Dec 15 10:33:23 2019 -0500 Zoom factor is saved to private setting https://github.com/laurent22/joplin/pull/2165#issuecomment-565258704 commit 34a1b2dc3e65f6a5b72a59608f4dddd9bad4bd08 Author: Elizabeth Schafer <elizabeth.schafer.wenk@gmail.com> Date: Sun Dec 15 10:30:29 2019 -0500 Basing new zoom value off redux state https://github.com/laurent22/joplin/pull/2165#discussion_r357441406 https://github.com/laurent22/joplin/pull/2165#discussion_r357441512 commit 7ec15ff4c4b334fd96003aaf04c119e013bb748c Author: Elizabeth Schafer <elizabeth.schafer.wenk@gmail.com> Date: Fri Dec 13 12:50:11 2019 -0500 Reducer shouldn't have any side effects https://github.com/laurent22/joplin/pull/2165#discussion_r357440767 commit 9e676ece1369e60496ba72cd953ba141b93afd6a Author: Elizabeth Schafer <elizabeth.schafer.wenk@gmail.com> Date: Sun Dec 8 11:11:28 2019 -0500 Added zoom options to the view menu
2020-02-12 14:41:32 +02:00
width: this.props.size.width / this.props.zoomFactor,
height: this.props.size.height / this.props.zoomFactor,
};
2020-09-15 15:01:07 +02:00
const theme = themeStyle(this.props.themeId);
const screens = {
Main: { screen: MainScreen },
OneDriveLogin: { screen: OneDriveLoginScreen, title: () => _('OneDrive Login') },
2018-03-26 19:33:55 +02:00
DropboxLogin: { screen: DropboxLoginScreen, title: () => _('Dropbox Login') },
JoplinCloudLogin: { screen: JoplinCloudLoginScreen, title: () => _('Joplin Cloud Login') },
Import: { screen: ImportScreen, title: () => _('Import') },
2017-11-30 20:36:26 +02:00
Config: { screen: ConfigScreen, title: () => _('Options') },
Resources: { screen: ResourceScreen, title: () => _('Note attachments') },
2017-12-05 20:56:39 +02:00
Status: { screen: StatusScreen, title: () => _('Synchronisation Status') },
};
2020-09-15 15:01:07 +02:00
return (
<StyleSheetManager disableVendorPrefixes>
<ThemeProvider theme={theme}>
<StyleSheetContainer themeId={this.props.themeId}></StyleSheetContainer>
<MenuBar/>
2020-09-15 15:01:07 +02:00
<GlobalStyle/>
<Navigator style={navigatorStyle} screens={screens} className={`profile-${this.props.profileConfigCurrentProfileId}`} />
{this.renderModalMessage(this.modalDialogProps())}
2021-08-16 16:20:14 +02:00
{this.renderDialogs()}
2020-09-15 15:01:07 +02:00
</ThemeProvider>
</StyleSheetManager>
);
}
}
2021-08-16 16:20:14 +02:00
const mapStateToProps = (state: AppState) => {
return {
size: state.windowContentSize,
Desktop: Resolves #2162: Added zoom controls to the application menu commit 2285000a6ac09eed12d4215d71b4f88f1660411a Author: Laurent Cozic <laurent@cozic.net> Date: Tue Feb 11 22:25:12 2020 +0000 Deprecate style.zoom commit 3a6da4ffee280dd93eee1f4ae8891a72ecaea8e3 Author: Laurent Cozic <laurent@cozic.net> Date: Tue Feb 11 22:13:01 2020 +0000 Fix zoom branch commit c46c080a069d213e4f75c261a12cbed47ed8de8f Author: Elizabeth Schafer <elizabeth.schafer.wenk@gmail.com> Date: Sun Dec 15 10:37:10 2019 -0500 Using componentDidUpdate rather than deprecated componentWillRecieveProps https://github.com/laurent22/joplin/pull/2165#discussion_r357441917 commit 069444fd02e18f6542e6483d9fffae8a941ab59c Author: Elizabeth Schafer <elizabeth.schafer.wenk@gmail.com> Date: Sun Dec 15 10:33:23 2019 -0500 Zoom factor is saved to private setting https://github.com/laurent22/joplin/pull/2165#issuecomment-565258704 commit 34a1b2dc3e65f6a5b72a59608f4dddd9bad4bd08 Author: Elizabeth Schafer <elizabeth.schafer.wenk@gmail.com> Date: Sun Dec 15 10:30:29 2019 -0500 Basing new zoom value off redux state https://github.com/laurent22/joplin/pull/2165#discussion_r357441406 https://github.com/laurent22/joplin/pull/2165#discussion_r357441512 commit 7ec15ff4c4b334fd96003aaf04c119e013bb748c Author: Elizabeth Schafer <elizabeth.schafer.wenk@gmail.com> Date: Fri Dec 13 12:50:11 2019 -0500 Reducer shouldn't have any side effects https://github.com/laurent22/joplin/pull/2165#discussion_r357440767 commit 9e676ece1369e60496ba72cd953ba141b93afd6a Author: Elizabeth Schafer <elizabeth.schafer.wenk@gmail.com> Date: Sun Dec 8 11:11:28 2019 -0500 Added zoom options to the view menu
2020-02-12 14:41:32 +02:00
zoomFactor: state.settings.windowContentZoomFactor / 100,
appState: state.appState,
2020-09-15 15:01:07 +02:00
themeId: state.settings.theme,
needApiAuth: state.needApiAuth,
2021-08-16 16:20:14 +02:00
dialogs: state.dialogs,
profileConfigCurrentProfileId: state.profileConfig.currentProfileId,
};
2017-11-04 18:40:34 +02:00
};
const Root = connect(mapStateToProps)(RootComponent);
2017-11-04 18:40:34 +02:00
const store = app().store();
2022-11-15 11:09:43 +02:00
const root = createRoot(document.getElementById('react-root'));
root.render(
<Provider store={store}>
<ErrorBoundary>
<Root />
</ErrorBoundary>
</Provider>,
);