1
0
mirror of https://github.com/laurent22/joplin.git synced 2025-08-10 22:11:50 +02:00

Desktop: Fixes #12214: Change how the main content size is determined (#12388)

This commit is contained in:
Henry Heino
2025-06-06 02:30:17 -07:00
committed by GitHub
parent 8e8ab3bd80
commit ab17625ed8
8 changed files with 33 additions and 66 deletions

View File

@@ -4,7 +4,7 @@ import appReducer, { createAppDefaultState } from './app.reducer';
describe('app.reducer', () => {
it('should handle DIALOG_OPEN', async () => {
const state: AppState = createAppDefaultState({}, {});
const state: AppState = createAppDefaultState({});
let newState = appReducer(state, {
type: 'DIALOG_OPEN',
@@ -49,7 +49,7 @@ describe('app.reducer', () => {
it('showing a dialog in one window should hide dialogs with the same ID in background windows', () => {
const state: AppState = {
...createAppDefaultState({}, {}),
...createAppDefaultState({}),
backgroundWindows: {
testWindow: {
...createAppDefaultWindowState(),

View File

@@ -54,8 +54,6 @@ export interface AppState extends State, AppWindowState {
route: AppStateRoute;
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
navHistory: any[];
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
windowContentSize: any;
watchedNoteFiles: string[];
lastEditorScrollPercents: EditorScrollPercents;
focusedField: string;
@@ -81,7 +79,7 @@ export const createAppDefaultWindowState = (): AppWindowState => {
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
export function createAppDefaultState(windowContentSize: any, resourceEditWatcherDefaultState: any): AppState {
export function createAppDefaultState(resourceEditWatcherDefaultState: any): AppState {
return {
...defaultState,
...createAppDefaultWindowState(),
@@ -91,7 +89,6 @@ export function createAppDefaultState(windowContentSize: any, resourceEditWatche
props: {},
},
navHistory: [],
windowContentSize, // bridge().windowContentSize(),
watchedNoteFiles: [],
lastEditorScrollPercents: {},
visibleDialogs: {}, // empty object if no dialog is visible. Otherwise contains the list of visible dialogs.
@@ -166,12 +163,6 @@ export default function(state: AppState, action: any) {
}
break;
case 'WINDOW_CONTENT_SIZE_SET':
newState = { ...state };
newState.windowContentSize = action.size;
break;
case 'NOTE_VISIBLE_PANES_TOGGLE':
{

View File

@@ -65,10 +65,7 @@ const pluginClasses = [
require('./plugins/GotoAnything').default,
];
const appDefaultState = createAppDefaultState(
bridge().windowContentSize(),
resourceEditWatcherDefaultState,
);
const appDefaultState = createAppDefaultState(resourceEditWatcherDefaultState);
class Application extends BaseApplication {

View File

@@ -313,13 +313,6 @@ export class Bridge {
return new BrowserWindow(options);
}
// Note: This provides the size of the main window. Prefer CSS where possible.
public windowContentSize() {
if (!this.mainWindow()) return { width: 0, height: 0 };
const s = this.mainWindow().getContentSize();
return { width: s[0], height: s[1] };
}
public windowSetSize(width: number, height: number) {
if (!this.mainWindow()) return;
return this.mainWindow().setSize(width, height);

View File

@@ -38,7 +38,7 @@ describe('exportDeletionLog', () => {
let state: AppState = undefined;
beforeAll(() => {
state = createAppDefaultState({}, {});
state = createAppDefaultState({});
jest.useFakeTimers();
jest.setSystemTime(new Date('2024-09-18T12:00:00Z').getTime());
});

View File

@@ -3,7 +3,7 @@ import { connect } from 'react-redux';
import Setting from '@joplin/lib/models/Setting';
import { AppState, AppStateRoute } from '../app.reducer';
import bridge from '../services/bridge';
import { useContext, useEffect, useMemo, useRef } from 'react';
import { useContext, useEffect, useMemo, useRef, useState } from 'react';
import { WindowIdContext } from './NewWindowOrIFrame';
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Partial refactor of code from before rule was applied
@@ -55,26 +55,44 @@ const useWindowRefocusManager = (route: AppStateRoute) => {
}, [routeName, windowId]);
};
const useContainerSize = (container: HTMLElement|null) => {
const [size, setSize] = useState({ width: container?.clientWidth, height: container?.clientHeight });
useEffect(() => {
if (!container) return () => {};
const observer = new ResizeObserver(() => {
setSize({
width: container.clientWidth,
height: container.clientHeight,
});
});
observer.observe(container);
return () => {
observer.disconnect();
};
}, [container]);
return size;
};
const NavigatorComponent: React.FC<Props> = props => {
const route = props.route;
const screenInfo = props.screens[route?.routeName];
const [container, setContainer] = useState<HTMLElement|null>(null);
useWindowTitleManager(screenInfo);
useWindowRefocusManager(route);
const size = useContainerSize(container);
if (!route) throw new Error('Route must not be null');
const screenProps = route.props ? route.props : {};
const Screen = screenInfo.screen;
const screenStyle = {
width: props.style.width,
height: props.style.height,
};
return (
<div style={props.style} className={props.className}>
<Screen style={screenStyle} {...screenProps} />
<div ref={setContainer} style={props.style} className={props.className}>
<Screen style={size} {...screenProps} />
</div>
);
};

View File

@@ -8,13 +8,11 @@ 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 { createRoot } = require('react-dom/client');
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';
@@ -28,7 +26,6 @@ import JoplinCloudLoginScreen from './JoplinCloudLoginScreen';
import InteropService from '@joplin/lib/services/interop/InteropService';
import WindowCommandsAndDialogs from './WindowCommandsAndDialogs/WindowCommandsAndDialogs';
import { defaultWindowId, stateUtils, WindowState } from '@joplin/lib/reducer';
import bridge from '../services/bridge';
import EditorWindow from './NoteEditor/EditorWindow';
import SsoLoginScreen from './SsoLoginScreen/SsoLoginScreen';
import SamlShared from '@joplin/lib/components/shared/SamlShared';
@@ -41,7 +38,6 @@ interface Props {
profileConfigCurrentProfileId: 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[];
@@ -62,31 +58,9 @@ const GlobalStyle = createGlobalStyle`
}
`;
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
let wcsTimeoutId_: any = null;
const navigatorStyle = { width: '100vw', height: '100vh' };
async function initialize() {
bridge().activeWindow().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: 'EDITOR_CODE_VIEW_CHANGE',
value: Setting.value('editor.codeView'),
@@ -180,11 +154,6 @@ class RootComponent extends React.Component<Props, any> {
}
public render() {
const navigatorStyle = {
width: this.props.size.width / this.props.zoomFactor,
height: this.props.size.height / this.props.zoomFactor,
};
const theme = themeStyle(this.props.themeId);
const screens = {
@@ -219,7 +188,6 @@ class RootComponent extends React.Component<Props, any> {
const mapStateToProps = (state: AppState) => {
return {
size: state.windowContentSize,
zoomFactor: state.settings.windowContentZoomFactor / 100,
appState: state.appState,
themeId: state.settings.theme,

View File

@@ -39,7 +39,7 @@ describe('PerFolderSortOrderService', () => {
beforeEach(() => {
PerFolderSortOrderService.initialize();
Setting.setValue('notes.perFolderSortOrderEnabled', true);
updateAppState(createAppDefaultState({}, {}));
updateAppState(createAppDefaultState({}));
switchToFolder(folderId1);
});
afterEach(() => {