You've already forked joplin
mirror of
https://github.com/laurent22/joplin.git
synced 2025-08-10 22:11:50 +02:00
Chore: Desktop: Update components for compatibility with React 19 (#12184)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
const React = require('react');
|
||||
import * as React from 'react';
|
||||
import EncryptionService from '@joplin/lib/services/e2ee/EncryptionService';
|
||||
import { themeStyle } from '@joplin/lib/theme';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
|
@@ -1,9 +1,9 @@
|
||||
const { connect } = require('react-redux');
|
||||
import * as React from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { AppState } from '../app.reducer';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import { clipboard } from 'electron';
|
||||
import Button from './Button/Button';
|
||||
import { Fragment } from 'react';
|
||||
import { accountTypeToString } from '@joplin/lib/utils/joplinCloud/types';
|
||||
import bridge from '../services/bridge';
|
||||
|
||||
@@ -47,10 +47,10 @@ const JoplinCloudConfigScreen = (props: JoplinCloudConfigScreenProps) => {
|
||||
<h2>{_('Email to note')}</h2>
|
||||
<p>{_('Any email sent to this address will be converted into a note and added to your collection. The note will be saved into the Inbox notebook')}</p>
|
||||
{
|
||||
isEmailToNoteAvailableInAccount ? <Fragment>
|
||||
isEmailToNoteAvailableInAccount ? <>
|
||||
<p className='inbox-email-value'>{props.inboxEmail}</p>
|
||||
<Button onClick={copyToClipboard} title={_('Copy to clipboard')} />
|
||||
</Fragment>
|
||||
</>
|
||||
: <div className='alert-warn'>
|
||||
<p>{_('Your account doesn\'t have access to this feature')}</p>
|
||||
</div>
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import { Fragment, useEffect, useMemo, useReducer, useState } from 'react';
|
||||
import * as React from 'react';
|
||||
import { useEffect, useMemo, useReducer, useState } from 'react';
|
||||
import ButtonBar from './ConfigScreen/ButtonBar';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import { clipboard } from 'electron';
|
||||
@@ -81,7 +82,7 @@ const JoplinCloudScreenComponent = (props: Props) => {
|
||||
<div className="login-page">
|
||||
<div className="page-container">
|
||||
{state.active !== 'COMPLETED' ? (
|
||||
<Fragment>
|
||||
<>
|
||||
<p className="text">{_('To allow Joplin to synchronise with Joplin Cloud, please login using this URL:')}</p>
|
||||
<div className="buttons-container">
|
||||
<Button
|
||||
@@ -98,7 +99,7 @@ const JoplinCloudScreenComponent = (props: Props) => {
|
||||
/>
|
||||
|
||||
</div>
|
||||
</Fragment>
|
||||
</>
|
||||
) : null}
|
||||
<p className={state.className}>{state.message()}
|
||||
{state.active === 'ERROR' ? (
|
||||
|
@@ -1,6 +1,4 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, import/prefer-default-export -- Old code before rule was applied
|
||||
export function cursorPositionToTextOffset(cursorPos: any, body: string) {
|
||||
if (!body) return 0;
|
||||
|
||||
@@ -20,12 +18,3 @@ export function cursorPositionToTextOffset(cursorPos: any, body: string) {
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
export function usePrevious(value: any): any {
|
||||
const ref = useRef();
|
||||
useEffect(() => {
|
||||
ref.current = value;
|
||||
});
|
||||
return ref.current;
|
||||
}
|
||||
|
@@ -26,7 +26,7 @@ interface Props extends EditorProps {
|
||||
}
|
||||
|
||||
const Editor = (props: Props, ref: ForwardedRef<CodeMirrorControl>) => {
|
||||
const editorContainerRef = useRef<HTMLDivElement>();
|
||||
const editorContainerRef = useRef<HTMLDivElement|null>(null);
|
||||
const [editor, setEditor] = useState<CodeMirrorControl|null>(null);
|
||||
|
||||
// The editor will only be created once, so callbacks that could
|
||||
|
@@ -7,7 +7,7 @@ import { useEffect, useCallback, useRef, forwardRef, useImperativeHandle } from
|
||||
import { NoteBodyEditorProps, NoteBodyEditorRef } from '../../utils/types';
|
||||
|
||||
const PlainEditor = (props: NoteBodyEditorProps, ref: ForwardedRef<NoteBodyEditorRef>) => {
|
||||
const editorRef = useRef<HTMLTextAreaElement>();
|
||||
const editorRef = useRef<HTMLTextAreaElement|null>(null);
|
||||
|
||||
useImperativeHandle(ref, () => {
|
||||
return {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import { useState, useEffect, useCallback, useRef, forwardRef, useImperativeHandle, useMemo } from 'react';
|
||||
import { ScrollOptions, ScrollOptionTypes, EditorCommand, NoteBodyEditorProps, ResourceInfos, HtmlToMarkdownHandler, ScrollToTextValue } from '../../utils/types';
|
||||
import { useState, useEffect, useCallback, useRef, forwardRef, useImperativeHandle, useMemo, Ref } from 'react';
|
||||
import { ScrollOptions, ScrollOptionTypes, EditorCommand, NoteBodyEditorProps, ResourceInfos, HtmlToMarkdownHandler, ScrollToTextValue, NoteBodyEditorRef } from '../../utils/types';
|
||||
import { resourcesStatus, commandAttachFileToBody, getResourcesFromPasteEvent, processPastedHtml } from '../../utils/resourceHandling';
|
||||
import attachedResources from '@joplin/lib/utils/attachedResources';
|
||||
import useScroll from './utils/useScroll';
|
||||
@@ -95,8 +95,7 @@ interface LastOnChangeEventInfo {
|
||||
let dispatchDidUpdateIID_: any = null;
|
||||
let changeId_ = 1;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
||||
const TinyMCE = (props: NoteBodyEditorProps, ref: Ref<NoteBodyEditorRef>) => {
|
||||
const [editorContainer, setEditorContainer] = useState<HTMLDivElement|null>(null);
|
||||
const editorContainerDom = useDocument(editorContainer);
|
||||
const [editor, setEditor] = useState<Editor|null>(null);
|
||||
@@ -1200,11 +1199,10 @@ const TinyMCE = (props: NoteBodyEditorProps, ref: any) => {
|
||||
// we call the current one from setTimeout.
|
||||
// https://github.com/facebook/react/issues/14010#issuecomment-433788147
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied
|
||||
const props_onChangeRef = useRef<Function>();
|
||||
const props_onChangeRef = useRef<Function>(null);
|
||||
props_onChangeRef.current = props.onChange;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied
|
||||
const prop_htmlToMarkdownRef = useRef<HtmlToMarkdownHandler>();
|
||||
const prop_htmlToMarkdownRef = useRef<HtmlToMarkdownHandler>(null);
|
||||
prop_htmlToMarkdownRef.current = props.htmlToMarkdown;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
|
@@ -14,7 +14,7 @@ import useFormNote, { OnLoadEvent, OnSetFormNote } from './utils/useFormNote';
|
||||
import useEffectiveNoteId from './utils/useEffectiveNoteId';
|
||||
import useFolder from './utils/useFolder';
|
||||
import styles_ from './styles';
|
||||
import { NoteEditorProps, FormNote, OnChangeEvent, NoteBodyEditorProps, AllAssetsOptions, NoteBodyEditorRef } from './utils/types';
|
||||
import { NoteEditorProps, FormNote, OnChangeEvent, AllAssetsOptions, NoteBodyEditorRef, NoteBodyEditorPropsAndRef } from './utils/types';
|
||||
import CommandService from '@joplin/lib/services/CommandService';
|
||||
import Button, { ButtonLevel } from '../Button/Button';
|
||||
import eventManager, { EventName } from '@joplin/lib/eventManager';
|
||||
@@ -75,8 +75,8 @@ function NoteEditorContent(props: NoteEditorProps) {
|
||||
const [titleHasBeenManuallyChanged, setTitleHasBeenManuallyChanged] = useState(false);
|
||||
const [isReadOnly, setIsReadOnly] = useState<boolean>(false);
|
||||
|
||||
const editorRef = useRef<NoteBodyEditorRef>();
|
||||
const titleInputRef = useRef<HTMLInputElement>();
|
||||
const editorRef = useRef<NoteBodyEditorRef|null>(null);
|
||||
const titleInputRef = useRef<HTMLInputElement|null>(null);
|
||||
const isMountedRef = useRef(true);
|
||||
const noteSearchBarRef = useRef(null);
|
||||
|
||||
@@ -91,7 +91,7 @@ function NoteEditorContent(props: NoteEditorProps) {
|
||||
return `editor-${editorIdCounter++}`;
|
||||
}, []);
|
||||
|
||||
const setFormNoteRef = useRef<OnSetFormNote>();
|
||||
const setFormNoteRef = useRef<OnSetFormNote>(null);
|
||||
const { saveNoteIfWillChange, scheduleSaveNote } = useScheduleSaveCallbacks({
|
||||
setFormNote: setFormNoteRef, dispatch: props.dispatch, editorRef, editorId,
|
||||
});
|
||||
@@ -130,7 +130,7 @@ function NoteEditorContent(props: NoteEditorProps) {
|
||||
editorId,
|
||||
});
|
||||
setFormNoteRef.current = setFormNote;
|
||||
const formNoteRef = useRef<FormNote>();
|
||||
const formNoteRef = useRef<FormNote>(formNote);
|
||||
formNoteRef.current = { ...formNote };
|
||||
|
||||
const formNoteFolder = useFolder({ folderId: formNote.parent_id });
|
||||
@@ -423,7 +423,7 @@ function NoteEditorContent(props: NoteEditorProps) {
|
||||
const searchMarkers = useSearchMarkers(showLocalSearch, localSearchMarkerOptions, props.searches, props.selectedSearchId, props.highlightedWords);
|
||||
|
||||
const markupLanguage = formNote.markup_language;
|
||||
const editorProps: NoteBodyEditorProps = {
|
||||
const editorProps: NoteBodyEditorPropsAndRef = {
|
||||
ref: editorRef,
|
||||
contentKey: formNote.id,
|
||||
style: styles.tinyMCE,
|
||||
|
@@ -85,8 +85,6 @@ export type HtmlToMarkdownHandler = (markupLanguage: number, html: string, origi
|
||||
export interface NoteBodyEditorProps {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
style: any;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied
|
||||
ref: any;
|
||||
themeId: number;
|
||||
|
||||
// When this is true it means the note must always be rendered using a white
|
||||
@@ -141,6 +139,10 @@ export interface NoteBodyEditorProps {
|
||||
watchedNoteFiles: string[];
|
||||
}
|
||||
|
||||
export interface NoteBodyEditorPropsAndRef extends NoteBodyEditorProps {
|
||||
ref: RefObject<NoteBodyEditorRef>;
|
||||
}
|
||||
|
||||
export interface FormNote {
|
||||
id: string;
|
||||
title: string;
|
||||
|
@@ -14,7 +14,7 @@ const useScrollWhenReadyOptions = ({ noteId, selectedNoteHash, lastEditorScrollP
|
||||
const [scrollWhenReady, setScrollWhenReady] = useState<ScrollOptions|null>(null);
|
||||
|
||||
const previousNoteId = usePrevious(noteId);
|
||||
const lastScrollPercentsRef = useRef<EditorScrollPercents>();
|
||||
const lastScrollPercentsRef = useRef<EditorScrollPercents>(null);
|
||||
lastScrollPercentsRef.current = lastEditorScrollPercents;
|
||||
|
||||
useEffect(() => {
|
||||
|
@@ -226,7 +226,7 @@ const NoteList = (props: Props) => {
|
||||
output.push(
|
||||
<NoteListItem
|
||||
key={note.id}
|
||||
ref={el => itemRefs.current[note.id] = el}
|
||||
ref={el => { itemRefs.current[note.id] = el; }}
|
||||
index={i}
|
||||
dragIndex={dragOverTargetNoteIndex}
|
||||
noteCount={props.notes.length}
|
||||
|
@@ -10,7 +10,7 @@ const useActiveDescendantId = (selectedFolderId: string, selectedNoteIds: string
|
||||
setActiveNoteId(selectedNoteIdsRef.current?.[0] ?? '');
|
||||
}, [selectedFolderId]);
|
||||
|
||||
const previousNoteIdsRef = useRef<string[]>();
|
||||
const previousNoteIdsRef = useRef<string[]>(null);
|
||||
previousNoteIdsRef.current = usePrevious(selectedNoteIds);
|
||||
|
||||
useEffect(() => {
|
||||
|
@@ -157,24 +157,24 @@ const NoteTextViewer = forwardRef((props: Props, ref: ForwardedRef<NoteViewerCon
|
||||
return result;
|
||||
}, [parentDoc]);
|
||||
|
||||
const webview_domReadyRef = useRef<EventListener>();
|
||||
const webview_domReadyRef = useRef<EventListener>(null);
|
||||
webview_domReadyRef.current = (event: Event) => {
|
||||
domReadyRef.current = true;
|
||||
if (props.onDomReady) props.onDomReady(event);
|
||||
};
|
||||
|
||||
const webview_ipcMessageRef = useRef<EventListener>();
|
||||
const webview_ipcMessageRef = useRef<EventListener>(null);
|
||||
webview_ipcMessageRef.current = (event: Event) => {
|
||||
if (props.onIpcMessage) props.onIpcMessage(event);
|
||||
};
|
||||
|
||||
const webview_loadRef = useRef<EventListener>();
|
||||
const webview_loadRef = useRef<EventListener>(null);
|
||||
webview_loadRef.current = (event: Event) => {
|
||||
webview_domReadyRef.current(event);
|
||||
};
|
||||
|
||||
type MessageEventListener = (event: MessageEvent)=> void;
|
||||
const webview_messageRef = useRef<MessageEventListener>();
|
||||
const webview_messageRef = useRef<MessageEventListener>(null);
|
||||
webview_messageRef.current = (event: MessageEvent) => {
|
||||
if (event.source !== webviewRef.current?.contentWindow) return;
|
||||
if (!event.data || event.data.target !== 'main') return;
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import * as React from 'react';
|
||||
import app from '../app';
|
||||
import { AppState, AppStateDialog } from '../app.reducer';
|
||||
import MainScreen from './MainScreen';
|
||||
@@ -10,7 +11,6 @@ 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');
|
||||
const { createRoot } = require('react-dom/client');
|
||||
const { connect, Provider } = require('react-redux');
|
||||
import Setting from '@joplin/lib/models/Setting';
|
||||
@@ -36,6 +36,7 @@ const { ThemeProvider, StyleSheetManager, createGlobalStyle } = require('styled-
|
||||
interface Props {
|
||||
themeId: number;
|
||||
appState: string;
|
||||
profileConfigCurrentProfileId: string;
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types -- Old code before rule was applied
|
||||
dispatch: Function;
|
||||
size: Size;
|
||||
|
@@ -1,3 +1,4 @@
|
||||
import * as React from 'react';
|
||||
import Dialog from '../Dialog';
|
||||
import DialogButtonRow, { ClickEvent, ButtonSpec } from '../DialogButtonRow';
|
||||
import DialogTitle from '../DialogTitle';
|
||||
|
@@ -62,7 +62,7 @@ const FolderAndTagList: React.FC<Props> = props => {
|
||||
collapsedFolderIds: props.collapsedFolderIds,
|
||||
});
|
||||
|
||||
const itemListRef = useRef<ItemList<ListItem>>();
|
||||
const itemListRef = useRef<ItemList<ListItem>|null>(null);
|
||||
const { focusSidebar } = useFocusHandler({ itemListRef, selectedIndex, listItems });
|
||||
|
||||
useSidebarCommandHandler({ focusSidebar });
|
||||
|
@@ -29,7 +29,7 @@ const onCancelClick = async (lastDeletion: StateLastDeletion) => {
|
||||
export default (props: Props) => {
|
||||
const popupManager = useContext(PopupNotificationContext);
|
||||
|
||||
const lastDeletionNotificationTimeRef = useRef<number>();
|
||||
const lastDeletionNotificationTimeRef = useRef<number>(props.lastDeletionNotificationTime);
|
||||
lastDeletionNotificationTimeRef.current = props.lastDeletionNotificationTime;
|
||||
|
||||
useEffect(() => {
|
||||
|
Reference in New Issue
Block a user