mirror of
https://github.com/laurent22/joplin.git
synced 2024-11-24 08:12:24 +02:00
Desktop: Fixes #9433: Fixed various scrolling issues when creating new notes or to-dos
This commit is contained in:
parent
07b4117aa1
commit
25b12a2366
@ -37,12 +37,11 @@ const StyledTitle = styled.span`
|
||||
|
||||
`;
|
||||
|
||||
// const buttonSizePx = 32;
|
||||
|
||||
export const buttonSizePx = (props: Props) => {
|
||||
if (!props.size || props.size === ButtonSize.Normal) return 32;
|
||||
if (props.size === ButtonSize.Small) return 26;
|
||||
throw new Error(`Unknown size: ${props.size}`);
|
||||
export const buttonSizePx = (props: Props | ButtonSize) => {
|
||||
const buttonSize = typeof props === 'number' ? props : props.size;
|
||||
if (!buttonSize || buttonSize === ButtonSize.Normal) return 32;
|
||||
if (buttonSize === ButtonSize.Small) return 26;
|
||||
throw new Error(`Unknown size: ${buttonSize}`);
|
||||
};
|
||||
|
||||
const isSquare = (props: Props) => {
|
||||
|
@ -29,6 +29,12 @@ export const runtime = (): CommandRuntime => {
|
||||
type: 'NOTE_SELECT',
|
||||
id: newNote.id,
|
||||
});
|
||||
|
||||
// Immediately sort the note list so that the new note is positioned correctly before
|
||||
// scrolling to it.
|
||||
utils.store.dispatch({
|
||||
type: 'NOTE_SORT',
|
||||
});
|
||||
},
|
||||
enabledCondition: 'oneFolderSelected && !inConflictFolder && !folderIsReadOnly',
|
||||
};
|
||||
|
@ -76,16 +76,6 @@ const NoteList = (props: Props) => {
|
||||
props.notes,
|
||||
);
|
||||
|
||||
// const renderedNotes = useRenderedNotes(
|
||||
// startNoteIndex,
|
||||
// endNoteIndex,
|
||||
// props.notes,
|
||||
// props.selectedNoteIds,
|
||||
// listRenderer,
|
||||
// props.highlightedWords,
|
||||
// props.watchedNoteFiles,
|
||||
// );
|
||||
|
||||
const noteItemStyle = useMemo(() => {
|
||||
return {
|
||||
width: 'auto',
|
||||
|
@ -30,3 +30,17 @@ export interface Props {
|
||||
parentFolderIsReadOnly: boolean;
|
||||
listRenderer: ListRenderer;
|
||||
}
|
||||
|
||||
export enum BaseBreakpoint {
|
||||
Sm = 75,
|
||||
Md = 80,
|
||||
Lg = 120,
|
||||
Xl = 474,
|
||||
}
|
||||
|
||||
export interface Breakpoints {
|
||||
Sm: number;
|
||||
Md: number;
|
||||
Lg: number;
|
||||
Xl: number;
|
||||
}
|
||||
|
@ -35,6 +35,9 @@ const useScroll = (itemsPerLine: number, noteCount: number, itemSize: Size, list
|
||||
if (setScrollTopLikeYouMeanItTimer.current) shim.clearInterval(setScrollTopLikeYouMeanItTimer.current);
|
||||
setScrollTopLikeYouMeanItStartTime.current = Date.now();
|
||||
|
||||
listRef.current.scrollTop = newScrollTop;
|
||||
lastScrollSetTime.current = Date.now();
|
||||
|
||||
setScrollTopLikeYouMeanItTimer.current = shim.setInterval(() => {
|
||||
if (!listRef.current) {
|
||||
shim.clearInterval(setScrollTopLikeYouMeanItTimer.current);
|
||||
@ -45,7 +48,7 @@ const useScroll = (itemsPerLine: number, noteCount: number, itemSize: Size, list
|
||||
listRef.current.scrollTop = newScrollTop;
|
||||
lastScrollSetTime.current = Date.now();
|
||||
|
||||
if (Date.now() - setScrollTopLikeYouMeanItStartTime.current > 500) {
|
||||
if (Date.now() - setScrollTopLikeYouMeanItStartTime.current > 1000) {
|
||||
shim.clearInterval(setScrollTopLikeYouMeanItTimer.current);
|
||||
setScrollTopLikeYouMeanItTimer.current = null;
|
||||
}
|
||||
@ -59,9 +62,9 @@ const useScroll = (itemsPerLine: number, noteCount: number, itemSize: Size, list
|
||||
|
||||
const makeItemIndexVisible = useCallback((itemIndex: number) => {
|
||||
const lineTopFloat = scrollTop / itemSize.height;
|
||||
const topFloat = lineTopFloat * itemsPerLine; // scrollTop / itemSize.height;
|
||||
const topFloat = lineTopFloat * itemsPerLine;
|
||||
const lineBottomFloat = (scrollTop + listSize.height - itemSize.height) / itemSize.height;
|
||||
const bottomFloat = lineBottomFloat * itemsPerLine; // (scrollTop + listSize.height - itemSize.height) / itemSize.height;
|
||||
const bottomFloat = lineBottomFloat * itemsPerLine;
|
||||
const top = Math.min(noteCount - 1, Math.floor(topFloat) + 1);
|
||||
const bottom = Math.max(0, Math.floor(bottomFloat));
|
||||
|
||||
@ -85,7 +88,7 @@ const useScroll = (itemsPerLine: number, noteCount: number, itemSize: Size, list
|
||||
|
||||
const onScroll = useCallback((event: any) => {
|
||||
// Ignore the scroll event if it has just been set programmatically.
|
||||
if (Date.now() - lastScrollSetTime.current < 100) return;
|
||||
if (Date.now() - lastScrollSetTime.current < 500) return;
|
||||
setScrollTop(event.target.scrollTop);
|
||||
}, []);
|
||||
|
||||
|
@ -41,6 +41,8 @@ const useVisibleRange = (itemsPerLine: number, scrollTop: number, listSize: Size
|
||||
}, [noteCount, itemsPerLine]);
|
||||
|
||||
// console.info('itemsPerLine', itemsPerLine);
|
||||
// console.info('listSize.height', listSize.height);
|
||||
// console.info('itemSize.height', itemSize.height);
|
||||
// console.info('startLineIndexFloat', startLineIndexFloat);
|
||||
// console.info('endLineIndexFloat', endLineIndexFloat);
|
||||
// console.info('visibleLineCount', visibleLineCount);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { AppState } from '../../app.reducer';
|
||||
import * as React from 'react';
|
||||
import { useEffect, useRef, useMemo, useState } from 'react';
|
||||
import { useEffect, useRef, useMemo } from 'react';
|
||||
import SearchBar from '../SearchBar/SearchBar';
|
||||
import Button, { ButtonLevel, ButtonSize, buttonSizePx } from '../Button/Button';
|
||||
import CommandService from '@joplin/lib/services/CommandService';
|
||||
@ -11,13 +11,7 @@ import { _ } from '@joplin/lib/locale';
|
||||
const { connect } = require('react-redux');
|
||||
import styled from 'styled-components';
|
||||
import stateToWhenClauseContext from '../../services/commands/stateToWhenClauseContext';
|
||||
|
||||
enum BaseBreakpoint {
|
||||
Sm = 75,
|
||||
Md = 80,
|
||||
Lg = 120,
|
||||
Xl = 474,
|
||||
}
|
||||
import { Breakpoints } from '../NoteList/utils/types';
|
||||
|
||||
interface Props {
|
||||
showNewNoteButtons: boolean;
|
||||
@ -29,23 +23,23 @@ interface Props {
|
||||
width: number;
|
||||
newNoteButtonEnabled: boolean;
|
||||
newTodoButtonEnabled: boolean;
|
||||
}
|
||||
|
||||
interface Breakpoints {
|
||||
Sm: number;
|
||||
Md: number;
|
||||
Lg: number;
|
||||
Xl: number;
|
||||
newNoteButtonRef: React.MutableRefObject<any>;
|
||||
lineCount: number;
|
||||
breakpoint: number;
|
||||
dynamicBreakpoints: Breakpoints;
|
||||
buttonSize: ButtonSize;
|
||||
padding: number;
|
||||
buttonVerticalGap: number;
|
||||
}
|
||||
|
||||
const StyledRoot = styled.div`
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: ${(props: any) => props.theme.mainPadding}px;
|
||||
padding: ${(props: any) => props.padding}px;
|
||||
background-color: ${(props: any) => props.theme.backgroundColor3};
|
||||
gap: 5px;
|
||||
`;
|
||||
gap: ${(props: any) => props.buttonVerticalGap}px;
|
||||
` as any;
|
||||
|
||||
const StyledButton = styled(Button)`
|
||||
width: auto;
|
||||
@ -93,47 +87,14 @@ const SortOrderButtonsContainer = styled.div`
|
||||
`;
|
||||
|
||||
function NoteListControls(props: Props) {
|
||||
const [dynamicBreakpoints, setDynamicBreakpoints] = useState<Breakpoints>({ Sm: BaseBreakpoint.Sm, Md: BaseBreakpoint.Md, Lg: BaseBreakpoint.Lg, Xl: BaseBreakpoint.Xl });
|
||||
|
||||
const searchBarRef = useRef(null);
|
||||
const newNoteRef = useRef(null);
|
||||
const newTodoRef = useRef(null);
|
||||
const newTodoButtonRef = useRef(null);
|
||||
const noteControlsRef = useRef(null);
|
||||
const searchAndSortRef = useRef(null);
|
||||
|
||||
const getTextWidth = (text: string): number => {
|
||||
const canvas = document.createElement('canvas');
|
||||
if (!canvas) throw new Error('Failed to create canvas element');
|
||||
const ctx = canvas.getContext('2d');
|
||||
if (!ctx) throw new Error('Failed to get context');
|
||||
const fontWeight = getComputedStyle(newNoteRef.current).getPropertyValue('font-weight');
|
||||
const fontSize = getComputedStyle(newNoteRef.current).getPropertyValue('font-size');
|
||||
const fontFamily = getComputedStyle(newNoteRef.current).getPropertyValue('font-family');
|
||||
ctx.font = `${fontWeight} ${fontSize} ${fontFamily}`;
|
||||
|
||||
return ctx.measureText(text).width;
|
||||
};
|
||||
|
||||
// Initialize language-specific breakpoints
|
||||
useEffect(() => {
|
||||
// Use the longest string to calculate the amount of extra width needed
|
||||
const smAdditional = getTextWidth(_('note')) > getTextWidth(_('to-do')) ? getTextWidth(_('note')) : getTextWidth(_('to-do'));
|
||||
const mdAdditional = getTextWidth(_('New note')) > getTextWidth(_('New to-do')) ? getTextWidth(_('New note')) : getTextWidth(_('New to-do'));
|
||||
|
||||
const Sm = BaseBreakpoint.Sm + smAdditional * 2;
|
||||
const Md = BaseBreakpoint.Md + mdAdditional * 2;
|
||||
const Lg = BaseBreakpoint.Lg + Md;
|
||||
const Xl = BaseBreakpoint.Xl;
|
||||
|
||||
setDynamicBreakpoints({ Sm, Md, Lg, Xl });
|
||||
}, []);
|
||||
|
||||
const breakpoint = useMemo(() => {
|
||||
// Find largest breakpoint that width is less than
|
||||
const index = Object.values(dynamicBreakpoints).findIndex(x => props.width < x);
|
||||
|
||||
return index === -1 ? dynamicBreakpoints.Xl : Object.values(dynamicBreakpoints)[index];
|
||||
}, [props.width, dynamicBreakpoints]);
|
||||
const breakpoint = props.breakpoint;
|
||||
const dynamicBreakpoints = props.dynamicBreakpoints;
|
||||
const lineCount = props.lineCount;
|
||||
|
||||
const noteButtonText = useMemo(() => {
|
||||
if (breakpoint === dynamicBreakpoints.Sm) {
|
||||
@ -180,13 +141,13 @@ function NoteListControls(props: Props) {
|
||||
}, [breakpoint, dynamicBreakpoints.Sm]);
|
||||
|
||||
useEffect(() => {
|
||||
if (breakpoint === dynamicBreakpoints.Xl) {
|
||||
if (lineCount === 1) {
|
||||
noteControlsRef.current.style.flexDirection = 'row';
|
||||
searchAndSortRef.current.style.flex = '2 1 50%';
|
||||
} else {
|
||||
noteControlsRef.current.style.flexDirection = 'column';
|
||||
}
|
||||
}, [breakpoint, dynamicBreakpoints]);
|
||||
}, [lineCount]);
|
||||
|
||||
useEffect(() => {
|
||||
CommandService.instance().registerRuntime('focusSearch', focusSearchRuntime(searchBarRef));
|
||||
@ -246,23 +207,23 @@ function NoteListControls(props: Props) {
|
||||
|
||||
return (
|
||||
<TopRow className="new-note-todo-buttons">
|
||||
<StyledButton ref={newNoteRef}
|
||||
<StyledButton ref={props.newNoteButtonRef}
|
||||
className="new-note-button"
|
||||
tooltip={ showTooltip ? CommandService.instance().label('newNote') : '' }
|
||||
iconName={noteIcon}
|
||||
title={_('%s', noteButtonText)}
|
||||
level={ButtonLevel.Primary}
|
||||
size={ButtonSize.Small}
|
||||
size={props.buttonSize}
|
||||
onClick={onNewNoteButtonClick}
|
||||
disabled={!props.newNoteButtonEnabled}
|
||||
/>
|
||||
<StyledButton ref={newTodoRef}
|
||||
<StyledButton ref={newTodoButtonRef}
|
||||
className="new-todo-button"
|
||||
tooltip={ showTooltip ? CommandService.instance().label('newTodo') : '' }
|
||||
iconName={todoIcon}
|
||||
title={_('%s', todoButtonText)}
|
||||
level={ButtonLevel.Secondary}
|
||||
size={ButtonSize.Small}
|
||||
size={props.buttonSize}
|
||||
onClick={onNewTodoButtonClick}
|
||||
disabled={!props.newTodoButtonEnabled}
|
||||
/>
|
||||
@ -271,7 +232,7 @@ function NoteListControls(props: Props) {
|
||||
}
|
||||
|
||||
return (
|
||||
<StyledRoot ref={noteControlsRef}>
|
||||
<StyledRoot ref={noteControlsRef} padding={props.padding} buttonVerticalGap={props.buttonVerticalGap}>
|
||||
{renderNewNoteButtons()}
|
||||
<BottomRow ref={searchAndSortRef} className="search-and-sort">
|
||||
<SearchBar inputRef={searchBarRef}/>
|
||||
@ -282,7 +243,7 @@ function NoteListControls(props: Props) {
|
||||
tooltip={sortOrderFieldTooltip()}
|
||||
iconName={sortOrderFieldIcon()}
|
||||
level={ButtonLevel.Secondary}
|
||||
size={ButtonSize.Small}
|
||||
size={props.buttonSize}
|
||||
onClick={onSortOrderFieldButtonClick}
|
||||
/>
|
||||
<StyledPairButtonR
|
||||
@ -290,7 +251,7 @@ function NoteListControls(props: Props) {
|
||||
tooltip={CommandService.instance().label('toggleNotesSortOrderReverse')}
|
||||
iconName={sortOrderReverseIcon()}
|
||||
level={ButtonLevel.Secondary}
|
||||
size={ButtonSize.Small}
|
||||
size={props.buttonSize}
|
||||
onClick={onSortOrderReverseButtonClick}
|
||||
/>
|
||||
</SortOrderButtonsContainer>
|
||||
@ -304,7 +265,6 @@ const mapStateToProps = (state: AppState) => {
|
||||
const whenClauseContext = stateToWhenClauseContext(state);
|
||||
|
||||
return {
|
||||
// TODO: showNewNoteButtons and the logic associated is not needed anymore.
|
||||
showNewNoteButtons: true,
|
||||
newNoteButtonEnabled: CommandService.instance().isEnabled('newNote', whenClauseContext),
|
||||
newTodoButtonEnabled: CommandService.instance().isEnabled('newTodo', whenClauseContext),
|
||||
|
@ -59,7 +59,7 @@ const NoteListItem = (props: NoteItemProps, ref: LegacyRef<HTMLDivElement>) => {
|
||||
|
||||
const rootElement = useRootElement(elementId);
|
||||
|
||||
const renderedNote = useRenderedNote(props.note, props.isSelected, props.isWatched, props.listRenderer, props.highlightedWords);
|
||||
const renderedNote = useRenderedNote(props.note, props.isSelected, props.isWatched, props.listRenderer, props.highlightedWords, props.index);
|
||||
|
||||
const itemElement = useItemElement(
|
||||
rootElement,
|
||||
|
@ -3,7 +3,7 @@ import { NoteEntity, TagEntity } from '@joplin/lib/services/database/types';
|
||||
import { Size } from '@joplin/utils/types';
|
||||
import Note from '@joplin/lib/models/Note';
|
||||
|
||||
const prepareViewProps = async (dependencies: ListRendererDependency[], note: NoteEntity, itemSize: Size, selected: boolean, noteTitleHtml: string, noteIsWatched: boolean, noteTags: TagEntity[]) => {
|
||||
const prepareViewProps = async (dependencies: ListRendererDependency[], note: NoteEntity, itemSize: Size, selected: boolean, noteTitleHtml: string, noteIsWatched: boolean, noteTags: TagEntity[], itemIndex: number) => {
|
||||
const output: any = {};
|
||||
|
||||
for (const dep of dependencies) {
|
||||
@ -45,6 +45,11 @@ const prepareViewProps = async (dependencies: ListRendererDependency[], note: No
|
||||
if (!output.item) output.item = {};
|
||||
output.item.selected = selected;
|
||||
}
|
||||
|
||||
if (dep === 'item.index') {
|
||||
if (!output.item) output.item = {};
|
||||
output.item.index = itemIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
|
@ -19,7 +19,7 @@ const hashContent = (content: any) => {
|
||||
return createHash('sha1').update(JSON.stringify(content)).digest('hex');
|
||||
};
|
||||
|
||||
export default (note: NoteEntity, isSelected: boolean, isWatched: boolean, listRenderer: ListRenderer, highlightedWords: string[]) => {
|
||||
export default (note: NoteEntity, isSelected: boolean, isWatched: boolean, listRenderer: ListRenderer, highlightedWords: string[], itemIndex: number) => {
|
||||
const [renderedNote, setRenderedNote] = useState<RenderedNote>(null);
|
||||
|
||||
useAsyncEffect(async (event) => {
|
||||
@ -56,6 +56,7 @@ export default (note: NoteEntity, isSelected: boolean, isWatched: boolean, listR
|
||||
titleHtml,
|
||||
isWatched,
|
||||
noteTags,
|
||||
itemIndex,
|
||||
);
|
||||
|
||||
if (event.cancelled) return null;
|
||||
|
@ -1,12 +1,15 @@
|
||||
import { themeStyle } from '@joplin/lib/theme';
|
||||
import * as React from 'react';
|
||||
import { useMemo, useState } from 'react';
|
||||
import { useMemo, useState, useEffect, useRef, useCallback } from 'react';
|
||||
import NoteList2 from '../NoteList/NoteList2';
|
||||
import NoteListControls from '../NoteListControls/NoteListControls';
|
||||
import { Size } from '../ResizableLayout/utils/types';
|
||||
import styled from 'styled-components';
|
||||
import { getDefaultListRenderer, getListRendererById } from '@joplin/lib/services/noteList/renderers';
|
||||
import Logger from '@joplin/utils/Logger';
|
||||
import { _ } from '@joplin/lib/locale';
|
||||
import { BaseBreakpoint, Breakpoints } from '../NoteList/utils/types';
|
||||
import { ButtonSize, buttonSizePx } from '../Button/Button';
|
||||
|
||||
const logger = Logger.create('NoteListWrapper');
|
||||
|
||||
@ -26,6 +29,52 @@ const StyledRoot = styled.div`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
// Even though these calculations mostly concern the NoteListControls component, we do them here
|
||||
// because we need to know the height of that control to calculate the note list height.
|
||||
const useNoteListControlsBreakpoints = (width: number, newNoteRef: React.MutableRefObject<any>) => {
|
||||
const [dynamicBreakpoints, setDynamicBreakpoints] = useState<Breakpoints>({ Sm: BaseBreakpoint.Sm, Md: BaseBreakpoint.Md, Lg: BaseBreakpoint.Lg, Xl: BaseBreakpoint.Xl });
|
||||
|
||||
const getTextWidth = useCallback((text: string): number => {
|
||||
const canvas = document.createElement('canvas');
|
||||
if (!canvas) throw new Error('Failed to create canvas element');
|
||||
const ctx = canvas.getContext('2d');
|
||||
if (!ctx) throw new Error('Failed to get context');
|
||||
const fontWeight = getComputedStyle(newNoteRef.current).getPropertyValue('font-weight');
|
||||
const fontSize = getComputedStyle(newNoteRef.current).getPropertyValue('font-size');
|
||||
const fontFamily = getComputedStyle(newNoteRef.current).getPropertyValue('font-family');
|
||||
ctx.font = `${fontWeight} ${fontSize} ${fontFamily}`;
|
||||
|
||||
return ctx.measureText(text).width;
|
||||
}, [newNoteRef]);
|
||||
|
||||
// Initialize language-specific breakpoints
|
||||
useEffect(() => {
|
||||
if (!newNoteRef.current) return;
|
||||
|
||||
// Use the longest string to calculate the amount of extra width needed
|
||||
const smAdditional = getTextWidth(_('note')) > getTextWidth(_('to-do')) ? getTextWidth(_('note')) : getTextWidth(_('to-do'));
|
||||
const mdAdditional = getTextWidth(_('New note')) > getTextWidth(_('New to-do')) ? getTextWidth(_('New note')) : getTextWidth(_('New to-do'));
|
||||
|
||||
const Sm = BaseBreakpoint.Sm + smAdditional * 2;
|
||||
const Md = BaseBreakpoint.Md + mdAdditional * 2;
|
||||
const Lg = BaseBreakpoint.Lg + Md;
|
||||
const Xl = BaseBreakpoint.Xl;
|
||||
|
||||
setDynamicBreakpoints({ Sm, Md, Lg, Xl });
|
||||
}, [newNoteRef, getTextWidth]);
|
||||
|
||||
const breakpoint: number = useMemo(() => {
|
||||
// Find largest breakpoint that width is less than
|
||||
const index = Object.values(dynamicBreakpoints).findIndex(x => width < x);
|
||||
|
||||
return index === -1 ? dynamicBreakpoints.Xl : Object.values(dynamicBreakpoints)[index];
|
||||
}, [width, dynamicBreakpoints]);
|
||||
|
||||
const lineCount = breakpoint !== dynamicBreakpoints.Xl ? 2 : 1;
|
||||
|
||||
return { breakpoint, dynamicBreakpoints, lineCount };
|
||||
};
|
||||
|
||||
// If the renderer ID that was saved to settings is already registered, we
|
||||
// return it. If not, we need to wait for all plugins to be loaded, because one
|
||||
// of them will most likely register the renderer we need. If none of them do,
|
||||
@ -44,13 +93,28 @@ export default function NoteListWrapper(props: Props) {
|
||||
const theme = themeStyle(props.themeId);
|
||||
const [controlHeight] = useState(theme.topRowHeight);
|
||||
const listRenderer = useListRenderer(props.listRendererId, props.startupPluginsLoaded);
|
||||
const newNoteButtonRef = useRef(null);
|
||||
|
||||
const { breakpoint, dynamicBreakpoints, lineCount } = useNoteListControlsBreakpoints(props.size.width, newNoteButtonRef);
|
||||
|
||||
const noteListControlsButtonSize = ButtonSize.Small;
|
||||
const noteListControlsPadding = theme.mainPadding;
|
||||
const noteListControlsButtonVerticalGap = 5;
|
||||
|
||||
const noteListControlsHeight = useMemo(() => {
|
||||
if (lineCount === 1) {
|
||||
return buttonSizePx(noteListControlsButtonSize) + noteListControlsPadding * 2;
|
||||
} else {
|
||||
return buttonSizePx(noteListControlsButtonSize) * 2 + noteListControlsPadding * 2 + noteListControlsButtonVerticalGap;
|
||||
}
|
||||
}, [lineCount, noteListControlsButtonSize, noteListControlsPadding, noteListControlsButtonVerticalGap]);
|
||||
|
||||
const noteListSize = useMemo(() => {
|
||||
return {
|
||||
width: props.size.width,
|
||||
height: props.size.height,
|
||||
height: props.size.height - noteListControlsHeight,
|
||||
};
|
||||
}, [props.size]);
|
||||
}, [props.size, noteListControlsHeight]);
|
||||
|
||||
const renderNoteList = () => {
|
||||
if (!listRenderer) return null;
|
||||
@ -64,7 +128,17 @@ export default function NoteListWrapper(props: Props) {
|
||||
|
||||
return (
|
||||
<StyledRoot>
|
||||
<NoteListControls height={controlHeight} width={noteListSize.width}/>
|
||||
<NoteListControls
|
||||
height={controlHeight}
|
||||
width={noteListSize.width}
|
||||
newNoteButtonRef={newNoteButtonRef}
|
||||
breakpoint={breakpoint}
|
||||
dynamicBreakpoints={dynamicBreakpoints}
|
||||
lineCount={lineCount}
|
||||
buttonSize={noteListControlsButtonSize}
|
||||
padding={noteListControlsPadding}
|
||||
buttonVerticalGap={noteListControlsButtonVerticalGap}
|
||||
/>
|
||||
{renderNoteList()}
|
||||
</StyledRoot>
|
||||
);
|
||||
|
@ -9,6 +9,7 @@ interface Props {
|
||||
todo_completed: number;
|
||||
};
|
||||
item: {
|
||||
// index: number;
|
||||
size: {
|
||||
height: number;
|
||||
};
|
||||
@ -29,6 +30,7 @@ const defaultListRenderer: ListRenderer = {
|
||||
},
|
||||
|
||||
dependencies: [
|
||||
// 'item.index',
|
||||
'item.selected',
|
||||
'item.size.height',
|
||||
'note.id',
|
||||
|
@ -44,6 +44,7 @@ export type OnChangeHandler = (event: OnChangeEvent)=> Promise<void>;
|
||||
*/
|
||||
export type ListRendererDependency =
|
||||
ListRendererDatabaseDependency |
|
||||
'item.index' |
|
||||
'item.size.width' |
|
||||
'item.size.height' |
|
||||
'item.selected' |
|
||||
|
Loading…
Reference in New Issue
Block a user