Desktop: Resolves #11664: Double click to open a note in a new window

pull/11674/head^2
Laurent Cozic 2025-01-17 11:52:52 +00:00
parent 0bd1e202a2
commit c6956df1c9
7 changed files with 42 additions and 8 deletions

View File

@ -312,6 +312,7 @@ packages/app-desktop/gui/NoteList/utils/useItemCss.js
packages/app-desktop/gui/NoteList/utils/useMoveNote.js packages/app-desktop/gui/NoteList/utils/useMoveNote.js
packages/app-desktop/gui/NoteList/utils/useOnKeyDown.js packages/app-desktop/gui/NoteList/utils/useOnKeyDown.js
packages/app-desktop/gui/NoteList/utils/useOnNoteClick.js packages/app-desktop/gui/NoteList/utils/useOnNoteClick.js
packages/app-desktop/gui/NoteList/utils/useOnNoteDoubleClick.js
packages/app-desktop/gui/NoteList/utils/useScroll.js packages/app-desktop/gui/NoteList/utils/useScroll.js
packages/app-desktop/gui/NoteList/utils/useVisibleRange.test.js packages/app-desktop/gui/NoteList/utils/useVisibleRange.test.js
packages/app-desktop/gui/NoteList/utils/useVisibleRange.js packages/app-desktop/gui/NoteList/utils/useVisibleRange.js

1
.gitignore vendored
View File

@ -287,6 +287,7 @@ packages/app-desktop/gui/NoteList/utils/useItemCss.js
packages/app-desktop/gui/NoteList/utils/useMoveNote.js packages/app-desktop/gui/NoteList/utils/useMoveNote.js
packages/app-desktop/gui/NoteList/utils/useOnKeyDown.js packages/app-desktop/gui/NoteList/utils/useOnKeyDown.js
packages/app-desktop/gui/NoteList/utils/useOnNoteClick.js packages/app-desktop/gui/NoteList/utils/useOnNoteClick.js
packages/app-desktop/gui/NoteList/utils/useOnNoteDoubleClick.js
packages/app-desktop/gui/NoteList/utils/useScroll.js packages/app-desktop/gui/NoteList/utils/useScroll.js
packages/app-desktop/gui/NoteList/utils/useVisibleRange.test.js packages/app-desktop/gui/NoteList/utils/useVisibleRange.test.js
packages/app-desktop/gui/NoteList/utils/useVisibleRange.js packages/app-desktop/gui/NoteList/utils/useVisibleRange.js

View File

@ -32,6 +32,14 @@ function styles_(props: MultiNoteActionsProps) {
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
}, },
divider: {
borderTopWidth: 1,
borderTopStyle: 'solid',
borderTopColor: theme.dividerColor,
width: '100%',
height: 1,
marginBottom: 10,
},
button: { button: {
...theme.buttonStyle, ...theme.buttonStyle,
marginBottom: 10, marginBottom: 10,
@ -68,11 +76,17 @@ export default function MultiNoteActions(props: MultiNoteActionsProps) {
const item = menuItems[i]; const item = menuItems[i];
if (!item.enabled) continue; if (!item.enabled) continue;
itemComps.push( if (item.type === 'separator') {
<button key={item.label} style={styles.button} onClick={() => multiNotesButton_click(item)}> itemComps.push(
{item.label} <div key={`divider${i}`} style={styles.divider}/>,
</button>, );
); } else {
itemComps.push(
<button key={item.label} style={styles.button} onClick={() => multiNotesButton_click(item)}>
{item.label}
</button>,
);
}
} }
return ( return (

View File

@ -29,6 +29,7 @@ import getNoteElementIdFromJoplinId from '../NoteListItem/utils/getNoteElementId
import useFocusVisible from './utils/useFocusVisible'; import useFocusVisible from './utils/useFocusVisible';
import { stateUtils } from '@joplin/lib/reducer'; import { stateUtils } from '@joplin/lib/reducer';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import useOnNoteDoubleClick from './utils/useOnNoteDoubleClick';
const commands = { const commands = {
focusElementNoteList, focusElementNoteList,
@ -103,6 +104,8 @@ const NoteList = (props: Props) => {
const onNoteClick = useOnNoteClick(props.dispatch, focusNote); const onNoteClick = useOnNoteClick(props.dispatch, focusNote);
const onNoteDoubleClick = useOnNoteDoubleClick();
const onKeyDown = useOnKeyDown( const onKeyDown = useOnKeyDown(
activeNoteId, activeNoteId,
props.selectedNoteIds, props.selectedNoteIds,
@ -226,6 +229,7 @@ const NoteList = (props: Props) => {
itemSize={itemSize} itemSize={itemSize}
onChange={listRenderer.onChange} onChange={listRenderer.onChange}
onClick={onNoteClick} onClick={onNoteClick}
onDoubleClick={onNoteDoubleClick}
onContextMenu={onItemContextMenu} onContextMenu={onItemContextMenu}
onDragStart={onDragStart} onDragStart={onDragStart}
onDragOver={onDragOver} onDragOver={onDragOver}

View File

@ -0,0 +1,10 @@
import * as React from 'react';
import { useCallback } from 'react';
import CommandService from '@joplin/lib/services/CommandService';
export default () => {
return useCallback((event: React.MouseEvent<HTMLDivElement>) => {
const noteId = event.currentTarget.getAttribute('data-id');
void CommandService.instance().execute('openNoteInNewWindow', noteId);
}, []);
};

View File

@ -22,6 +22,7 @@ interface NoteItemProps {
noteCount: number; noteCount: number;
onChange: OnChangeHandler; onChange: OnChangeHandler;
onClick: MouseEventHandler<HTMLDivElement>; onClick: MouseEventHandler<HTMLDivElement>;
onDoubleClick: MouseEventHandler<HTMLDivElement>;
onContextMenu: MouseEventHandler; onContextMenu: MouseEventHandler;
onDragOver: DragEventHandler; onDragOver: DragEventHandler;
onDragStart: DragEventHandler; onDragStart: DragEventHandler;
@ -79,6 +80,7 @@ const NoteListItem = (props: NoteItemProps, ref: LegacyRef<HTMLDivElement>) => {
props.style, props.style,
props.itemSize, props.itemSize,
props.onClick, props.onClick,
props.onDoubleClick,
props.flow, props.flow,
); );

View File

@ -4,7 +4,7 @@ import { useEffect, useState } from 'react';
import { ItemFlow } from '@joplin/lib/services/plugins/api/noteListType'; import { ItemFlow } from '@joplin/lib/services/plugins/api/noteListType';
const useItemElement = ( const useItemElement = (
rootElement: HTMLDivElement, noteId: string, noteHtml: string, focusVisible: boolean, style: React.CSSProperties, itemSize: Size, onClick: React.MouseEventHandler<HTMLDivElement>, flow: ItemFlow, rootElement: HTMLDivElement, noteId: string, noteHtml: string, focusVisible: boolean, style: React.CSSProperties, itemSize: Size, onClick: React.MouseEventHandler<HTMLDivElement>, onDoubleClick: React.MouseEventHandler<HTMLDivElement>, flow: ItemFlow,
) => { ) => {
const [itemElement, setItemElement] = useState<HTMLDivElement>(null); const [itemElement, setItemElement] = useState<HTMLDivElement>(null);
@ -21,8 +21,10 @@ const useItemElement = (
if (flow === ItemFlow.LeftToRight) element.style.width = `${itemSize.width}px`; if (flow === ItemFlow.LeftToRight) element.style.width = `${itemSize.width}px`;
element.style.height = `${itemSize.height}px`; element.style.height = `${itemSize.height}px`;
element.innerHTML = noteHtml; element.innerHTML = noteHtml;
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Old code before rule was applied // eslint-disable-next-line @typescript-eslint/no-explicit-any -- we're mixing React synthetic events with DOM events which ideally should not be done but it is fine in this particular case
element.addEventListener('click', onClick as any); element.addEventListener('click', onClick as any);
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- we're mixing React synthetic events with DOM events which ideally should not be done but it is fine in this particular case
element.addEventListener('dblclick', onDoubleClick as any);
rootElement.appendChild(element); rootElement.appendChild(element);
@ -31,7 +33,7 @@ const useItemElement = (
return () => { return () => {
element.remove(); element.remove();
}; };
}, [rootElement, itemSize, noteHtml, noteId, style, onClick, flow]); }, [rootElement, itemSize, noteHtml, noteId, style, onClick, onDoubleClick, flow]);
useEffect(() => { useEffect(() => {
if (!itemElement) return; if (!itemElement) return;