Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Desktop: Sort Order Buttons and Per-Notebook Sort Order #5437

Merged
merged 18 commits into from
Nov 11, 2021
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,15 @@ packages/app-desktop/gui/MainScreen/commands/toggleLayoutMoveMode.js.map
packages/app-desktop/gui/MainScreen/commands/toggleNoteList.d.ts
packages/app-desktop/gui/MainScreen/commands/toggleNoteList.js
packages/app-desktop/gui/MainScreen/commands/toggleNoteList.js.map
packages/app-desktop/gui/MainScreen/commands/toggleNotesSortOrderField.d.ts
packages/app-desktop/gui/MainScreen/commands/toggleNotesSortOrderField.js
packages/app-desktop/gui/MainScreen/commands/toggleNotesSortOrderField.js.map
packages/app-desktop/gui/MainScreen/commands/toggleNotesSortOrderReverse.d.ts
packages/app-desktop/gui/MainScreen/commands/toggleNotesSortOrderReverse.js
packages/app-desktop/gui/MainScreen/commands/toggleNotesSortOrderReverse.js.map
packages/app-desktop/gui/MainScreen/commands/togglePerFolderSortOrder.d.ts
packages/app-desktop/gui/MainScreen/commands/togglePerFolderSortOrder.js
packages/app-desktop/gui/MainScreen/commands/togglePerFolderSortOrder.js.map
packages/app-desktop/gui/MainScreen/commands/toggleSideBar.d.ts
packages/app-desktop/gui/MainScreen/commands/toggleSideBar.js
packages/app-desktop/gui/MainScreen/commands/toggleSideBar.js.map
Expand Down Expand Up @@ -715,6 +724,12 @@ packages/app-desktop/services/plugins/hooks/useViewIsReady.js.map
packages/app-desktop/services/plugins/hooks/useWebviewToPluginMessages.d.ts
packages/app-desktop/services/plugins/hooks/useWebviewToPluginMessages.js
packages/app-desktop/services/plugins/hooks/useWebviewToPluginMessages.js.map
packages/app-desktop/services/sortOrder/PerFolderSortOrderService.d.ts
packages/app-desktop/services/sortOrder/PerFolderSortOrderService.js
packages/app-desktop/services/sortOrder/PerFolderSortOrderService.js.map
packages/app-desktop/services/sortOrder/notesSortOrderUtils.d.ts
packages/app-desktop/services/sortOrder/notesSortOrderUtils.js
packages/app-desktop/services/sortOrder/notesSortOrderUtils.js.map
packages/app-desktop/services/spellChecker/SpellCheckerServiceDriverNative.d.ts
packages/app-desktop/services/spellChecker/SpellCheckerServiceDriverNative.js
packages/app-desktop/services/spellChecker/SpellCheckerServiceDriverNative.js.map
Expand Down
15 changes: 15 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,15 @@ packages/app-desktop/gui/MainScreen/commands/toggleLayoutMoveMode.js.map
packages/app-desktop/gui/MainScreen/commands/toggleNoteList.d.ts
packages/app-desktop/gui/MainScreen/commands/toggleNoteList.js
packages/app-desktop/gui/MainScreen/commands/toggleNoteList.js.map
packages/app-desktop/gui/MainScreen/commands/toggleNotesSortOrderField.d.ts
packages/app-desktop/gui/MainScreen/commands/toggleNotesSortOrderField.js
packages/app-desktop/gui/MainScreen/commands/toggleNotesSortOrderField.js.map
packages/app-desktop/gui/MainScreen/commands/toggleNotesSortOrderReverse.d.ts
packages/app-desktop/gui/MainScreen/commands/toggleNotesSortOrderReverse.js
packages/app-desktop/gui/MainScreen/commands/toggleNotesSortOrderReverse.js.map
packages/app-desktop/gui/MainScreen/commands/togglePerFolderSortOrder.d.ts
packages/app-desktop/gui/MainScreen/commands/togglePerFolderSortOrder.js
packages/app-desktop/gui/MainScreen/commands/togglePerFolderSortOrder.js.map
packages/app-desktop/gui/MainScreen/commands/toggleSideBar.d.ts
packages/app-desktop/gui/MainScreen/commands/toggleSideBar.js
packages/app-desktop/gui/MainScreen/commands/toggleSideBar.js.map
Expand Down Expand Up @@ -700,6 +709,12 @@ packages/app-desktop/services/plugins/hooks/useViewIsReady.js.map
packages/app-desktop/services/plugins/hooks/useWebviewToPluginMessages.d.ts
packages/app-desktop/services/plugins/hooks/useWebviewToPluginMessages.js
packages/app-desktop/services/plugins/hooks/useWebviewToPluginMessages.js.map
packages/app-desktop/services/sortOrder/PerFolderSortOrderService.d.ts
packages/app-desktop/services/sortOrder/PerFolderSortOrderService.js
packages/app-desktop/services/sortOrder/PerFolderSortOrderService.js.map
packages/app-desktop/services/sortOrder/notesSortOrderUtils.d.ts
packages/app-desktop/services/sortOrder/notesSortOrderUtils.js
packages/app-desktop/services/sortOrder/notesSortOrderUtils.js.map
packages/app-desktop/services/spellChecker/SpellCheckerServiceDriverNative.d.ts
packages/app-desktop/services/spellChecker/SpellCheckerServiceDriverNative.js
packages/app-desktop/services/spellChecker/SpellCheckerServiceDriverNative.js.map
Expand Down
3 changes: 3 additions & 0 deletions packages/app-desktop/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ const commands = mainScreenCommands
const globalCommands = appCommands.concat(libCommands);

import editorCommandDeclarations from './gui/NoteEditor/editorCommandDeclarations';
import PerFolderSortOrderService from './services/sortOrder/PerFolderSortOrderService';
import ShareService from '@joplin/lib/services/share/ShareService';
import checkForUpdates from './checkForUpdates';
import { AppState } from './app.reducer';
Expand Down Expand Up @@ -364,6 +365,8 @@ class Application extends BaseApplication {

this.initRedux();

PerFolderSortOrderService.initialize();

CommandService.instance().initialize(this.store(), Setting.value('env') == 'dev', stateToWhenClauseContext);

for (const command of commands) {
Expand Down
6 changes: 6 additions & 0 deletions packages/app-desktop/gui/MainScreen/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ import * as showSpellCheckerMenu from './showSpellCheckerMenu';
import * as toggleEditors from './toggleEditors';
import * as toggleLayoutMoveMode from './toggleLayoutMoveMode';
import * as toggleNoteList from './toggleNoteList';
import * as toggleNotesSortOrderField from './toggleNotesSortOrderField';
import * as toggleNotesSortOrderReverse from './toggleNotesSortOrderReverse';
import * as togglePerFolderSortOrder from './togglePerFolderSortOrder';
import * as toggleSideBar from './toggleSideBar';
import * as toggleVisiblePanes from './toggleVisiblePanes';

Expand Down Expand Up @@ -59,6 +62,9 @@ const index:any[] = [
toggleEditors,
toggleLayoutMoveMode,
toggleNoteList,
toggleNotesSortOrderField,
toggleNotesSortOrderReverse,
togglePerFolderSortOrder,
toggleSideBar,
toggleVisiblePanes,
];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { CommandContext, CommandDeclaration, CommandRuntime } from '@joplin/lib/services/CommandService';
import { setNotesSortOrder } from '../../../services/sortOrder/notesSortOrderUtils';
import { _ } from '@joplin/lib/locale';

export const declaration: CommandDeclaration = {
name: 'toggleNotesSortOrderField',
label: () => _('Toggle sort order field'),
parentLabel: () => _('Notes'),
};

export const runtime = (): CommandRuntime => {
return {
execute: async (_context: CommandContext, field?: string | Array<any>, reverse?: boolean) => {
// field: Sort order's field. undefined means switching a field.
// reverse: whether the sort order is reversed or not. undefined means toggling.
//
// To support CommandService.scheduleExecute(), field accepts an size-two Array,
// which means [field, reverse].
if (typeof field !== 'object') {
setNotesSortOrder(field, reverse);
} else {
setNotesSortOrder(field[0], field[1]);
}
},
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { CommandContext, CommandDeclaration, CommandRuntime } from '@joplin/lib/services/CommandService';
import Setting from '@joplin/lib/models/Setting';
import { _ } from '@joplin/lib/locale';
import { setNotesSortOrder } from '../../../services/sortOrder/notesSortOrderUtils';

export const declaration: CommandDeclaration = {
name: 'toggleNotesSortOrderReverse',
label: () => _('Reverse sort order'),
parentLabel: () => _('Notes'),
};

export const runtime = (): CommandRuntime => {
return {
execute: async (_context: CommandContext) => {
const reverse = Setting.value('notes.sortOrder.reverse');
setNotesSortOrder(undefined, !reverse);
},
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { CommandContext, CommandDeclaration, CommandRuntime } from '@joplin/lib/services/CommandService';
import { _ } from '@joplin/lib/locale';
import PerFolderSortOrderService from '../../../services/sortOrder/PerFolderSortOrderService';

export const declaration: CommandDeclaration = {
name: 'togglePerFolderSortOrder',
label: () => _('Toggle per-folder sort order'),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"per-notebook".

But also, when the per-notebook option is not enabled on the notebook, this is actually like a global setting that applies not, per-notebook, but to all notebooks, is that correct?

I don't think we can convey all that info in this tooltip, so simply "Toggle sort order" would be sufficient (it's implied it's for the notebook).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But also, when the per-notebook option is not enabled on the notebook, this is actually like a global setting that applies not, per-notebook, but to all notebooks, is that correct?

When notes.perFolderSortOrderEnabled is false, this command has no effect, and it is as expected.

I don't think we can convey all that info in this tooltip, so simply "Toggle sort order" would be sufficient (it's implied it's for the notebook).

Since this feature is not very common, I'm afraid that too brevity introduces misunderstanding such as 'toggle sort order field (title/update time/create time/custom)'. I agree that "Toggle per-notebook sort order" is too long. How about "Toggle own sort order"?

};

export const runtime = (): CommandRuntime => {
return {
enabledCondition: 'oneFolderSelected',

execute: async (_context: CommandContext, folderId?: string, own?: boolean) => {
PerFolderSortOrderService.set(folderId, own);
},
};
};
34 changes: 23 additions & 11 deletions packages/app-desktop/gui/MenuBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ function useMenuStates(menu: any, props: Props) {
menuItemSetChecked(`sort:${type}:${field}`, (props as any)[`${type}.sortOrder.field`] === field);
}

menuItemSetChecked(`sort:${type}:reverse`, (props as any)[`${type}.sortOrder.reverse`]);
const id = type == 'notes' ? 'toggleNotesSortOrderReverse' : `sort:${type}:reverse`;
menuItemSetChecked(id, (props as any)[`${type}.sortOrder.reverse`]);
}

applySortItemCheckState('notes');
Expand Down Expand Up @@ -267,22 +268,33 @@ function useMenu(props: Props) {
type: 'checkbox',
// checked: Setting.value(`${type}.sortOrder.field`) === field,
click: () => {
Setting.setValue(`${type}.sortOrder.field`, field);
if (type === 'notes') {
void CommandService.instance().execute('toggleNotesSortOrderField', field);
} else {
Setting.setValue(`${type}.sortOrder.field`, field);
}
},
});
}

sortItems.push({ type: 'separator' });

sortItems.push({
id: `sort:${type}:reverse`,
label: Setting.settingMetadata(`${type}.sortOrder.reverse`).label(),
type: 'checkbox',
// checked: Setting.value(`${type}.sortOrder.reverse`),
click: () => {
Setting.setValue(`${type}.sortOrder.reverse`, !Setting.value(`${type}.sortOrder.reverse`));
},
});
if (type == 'notes') {
sortItems.push(
{ ...menuItemDic.toggleNotesSortOrderReverse, type: 'checkbox' },
{ ...menuItemDic.toggleNotesSortOrderField, visible: false }
);
} else {
sortItems.push({
id: `sort:${type}:reverse`,
label: Setting.settingMetadata(`${type}.sortOrder.reverse`).label(),
type: 'checkbox',
// checked: Setting.value(`${type}.sortOrder.reverse`),
click: () => {
Setting.setValue(`${type}.sortOrder.reverse`, !Setting.value(`${type}.sortOrder.reverse`));
},
});
}

return sortItems;
};
Expand Down
91 changes: 90 additions & 1 deletion packages/app-desktop/gui/NoteListControls/NoteListControls.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import { AppState } from '../../app.reducer';
import * as React from 'react';
import { useEffect, useRef } from 'react';
import SearchBar from '../SearchBar/SearchBar';
import Button, { ButtonLevel } from '../Button/Button';
import CommandService from '@joplin/lib/services/CommandService';
import { runtime as focusSearchRuntime } from './commands/focusSearch';
import Note from '@joplin/lib/models/Note';
import { notesSortOrderNextField } from '../../services/sortOrder/notesSortOrderUtils';
const { connect } = require('react-redux');
const styled = require('styled-components').default;

interface Props {
showNewNoteButtons: boolean;
sortOrderButtonsVisible: boolean;
sortOrderField: string;
sortOrderReverse: boolean;
notesParentType: string;
height: number;
}

Expand All @@ -24,12 +32,27 @@ const StyledButton = styled(Button)`
margin-left: 8px;
`;

const StyledPairButtonL = styled(Button)`
margin-left: 8px;
border-radius: 5px 0 0 5px;
padding: 0 2px 0 4px;
`;

const StyledPairButtonR = styled(Button)`
margin-left: 0px;
border-radius: 0 5px 5px 0;
border-width: 1px 1px 1px 0;
padding: 0 4px 0 2px;
min-width: 8px;
width: auto;
`;

const ButtonContainer = styled.div`
display: flex;
flex-direction: row;
`;

export default function NoteListControls(props: Props) {
function NoteListControls(props: Props) {
const searchBarRef = useRef(null);

useEffect(function() {
Expand All @@ -48,11 +71,66 @@ export default function NoteListControls(props: Props) {
void CommandService.instance().execute('newNote');
}

function onSortOrderFieldButtonClick() {
void CommandService.instance().execute('toggleNotesSortOrderField');
}

function onSortOrderReverseButtonClick() {
void CommandService.instance().execute('toggleNotesSortOrderReverse');
}

function sortOrderFieldTooltip() {
const term1 = CommandService.instance().label('toggleNotesSortOrderField');
const field = props.sortOrderField;
const term2 = Note.fieldToLabel(field);
const term3 = Note.fieldToLabel(notesSortOrderNextField(field));
return `${term1}:\n ${term2} -> ${term3}`;
laurent22 marked this conversation as resolved.
Show resolved Hide resolved
}

function sortOrderFieldIcon() {
const field = props.sortOrderField;
const iconMap: any = {
user_updated_time: 'far fa-calendar-alt',
user_created_time: 'far fa-calendar-plus',
title: 'fas fa-font',
order: 'fas fa-wrench',
};
return `${iconMap[field] || iconMap['title']} ${field}`;
}

function sortOrderReverseIcon() {
return props.sortOrderReverse ? 'fas fa-long-arrow-alt-up' : 'fas fa-long-arrow-alt-down';
}

function showsSortOrderButtons() {
let visible = props.sortOrderButtonsVisible;
if (props.notesParentType === 'Search') visible = false;
return visible;
}

function renderNewNoteButtons() {
if (!props.showNewNoteButtons) return null;

return (
<ButtonContainer>
{showsSortOrderButtons() &&
<StyledPairButtonL
className="sort-order-field-button"
tooltip={sortOrderFieldTooltip()}
iconName={sortOrderFieldIcon()}
level={ButtonLevel.Secondary}
onClick={onSortOrderFieldButtonClick}
/>
}
{showsSortOrderButtons() &&
<StyledPairButtonR
className="sort-order-reverse-button"
tooltip={CommandService.instance().label('toggleNotesSortOrderReverse')}
iconName={sortOrderReverseIcon()}
level={ButtonLevel.Secondary}
onClick={onSortOrderReverseButtonClick}
/>
}
<StyledButton
className="new-todo-button"
tooltip={CommandService.instance().label('newTodo')}
Expand All @@ -78,3 +156,14 @@ export default function NoteListControls(props: Props) {
</StyledRoot>
);
}

const mapStateToProps = (state: AppState) => {
return {
sortOrderButtonsVisible: state.settings['notes.sortOrder.buttonsVisible'],
sortOrderField: state.settings['notes.sortOrder.field'],
sortOrderReverse: state.settings['notes.sortOrder.reverse'],
notesParentType: state.notesParentType,
};
};

export default connect(mapStateToProps)(NoteListControls);
8 changes: 8 additions & 0 deletions packages/app-desktop/gui/Sidebar/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import Logger from '@joplin/lib/Logger';
import { FolderEntity } from '@joplin/lib/services/database/types';
import stateToWhenClauseContext from '../../services/commands/stateToWhenClauseContext';
import { store } from '@joplin/lib/reducer';
import PerFolderSortOrderService from '../../services/sortOrder/PerFolderSortOrderService';
const { connect } = require('react-redux');
const shared = require('@joplin/lib/components/shared/side-menu-shared.js');
const { themeStyle } = require('@joplin/lib/theme');
Expand Down Expand Up @@ -324,6 +325,13 @@ class SidebarComponent extends React.Component<Props, State> {
submenu: exportMenu,
})
);
if (Setting.value('notes.perFolderSortOrderEnabled')) {
menu.append(new MenuItem({
...menuUtils.commandToStatefulMenuItem('togglePerFolderSortOrder', itemId),
type: 'checkbox',
checked: PerFolderSortOrderService.isSet(itemId),
}));
}
}

if (itemType === BaseModel.TYPE_TAG) {
Expand Down
3 changes: 3 additions & 0 deletions packages/app-desktop/gui/menuCommandNames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ export default function() {
'toggleExternalEditing',
'toggleLayoutMoveMode',
'toggleNoteList',
'toggleNotesSortOrderField',
'toggleNotesSortOrderReverse',
'togglePerFolderSortOrder',
'toggleSideBar',
'toggleVisiblePanes',
'editor.deleteLine',
Expand Down
Loading