Skip to content

Commit c4eed02

Browse files
committed
enhance(hotkeys): add select-all-nodes hotkey
1 parent 1d89929 commit c4eed02

14 files changed

Lines changed: 98 additions & 14 deletions

File tree

src/lang/hotkey-groups.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ export const hotkeyGroups = {
5454
'extend_select_to_end_of_group',
5555
'extend_select_to_start_of_column',
5656
'extend_select_to_end_of_column',
57+
'select_all_nodes',
5758
]),
5859
[lang.hkg_history]: new Set(['undo_change', 'redo_change']),
5960
[lang.hkg_search]: new Set(['toggle_search_input']),

src/lang/hotkeys-lang.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,5 @@ export const hotkeysLang = {
6060
toggle_collapse_all: lang.hk_outline_toggle_collapse_all,
6161
toggle_outline_mode: lang.hk_toggle_outline_mode,
6262
add_parent_sibling: lang.hk_add_parent_sibling,
63+
select_all_nodes: lang.hk_select_all,
6364
};

src/lang/lang.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,12 @@ export const lang = {
5858
cm_copy: 'Copy',
5959
cm_copy_branches: 'Copy branches',
6060
cm_copy_branch: 'Copy branch',
61-
cm_copy_branches_wo_formatting: 'Copy branches without formatting',
62-
cm_copy_branch_wo_formatting: 'Copy branch without formatting',
61+
cm_copy_branches_wo_formatting: 'Copy branches as plain text',
62+
cm_copy_branch_wo_formatting: 'Copy branch as plain text',
6363
cm_copy_section_wo_subitems: 'Copy sections without sub-items',
6464
cm_copy_sections_wo_subitems: 'Copy section without sub-items',
6565
hk_copy_node: 'Copy branch',
66-
hk_copy_node_unformatted: 'Copy branch without formatting',
66+
hk_copy_node_unformatted: 'Copy branch as plain text',
6767
hk_copy_node_without_subitems: 'Copy without subitems',
6868
cm_copy_link_to_block: 'Copy link to block',
6969
hkg_clipboard: 'Clipboard',
@@ -172,6 +172,7 @@ export const lang = {
172172
hk_extend_select_to_start_of_column: 'Extend selection to start of column',
173173
hk_extend_select_to_end_of_column: 'Extend selection to end of column',
174174
hkg_selection: 'Selection',
175+
hk_select_all: 'Select all cards',
175176

176177
// navigate spatially
177178
hk_navigate_to_next_node: 'Select next card',
@@ -218,7 +219,7 @@ export const lang = {
218219
'Always center active card vertically',
219220
cmd_toggle_horizontal_scrolling_mode: `Toggle 'always center active card horizontally'`,
220221
cmd_toggle_vertical_scrolling_mode: `Toggle 'always center active card vertically'`,
221-
card_btn_scroll_to_reveal: 'Scroll to reveal',
222+
card_btn_scroll_to_reveal: 'Reveal',
222223
hkg_scrolling: 'Align branch',
223224

224225
// theme
@@ -279,7 +280,7 @@ export const lang = {
279280
// rules
280281
modals_rules_add_rule: 'New rule',
281282
modals_rules_no_rules: 'No rules',
282-
controls_rules: 'Style rules',
283+
controls_rules: 'Card style rules',
283284
modals_rules_matches: 'Number of matches',
284285
modals_rules_drag_handle: 'Change priority',
285286
modals_rules_tab_global_rules: 'Global rules',

src/stores/view/helpers/get-view-event-type.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const stateEvents = new Set<ActionType>([
2020
'view/set-active-node/search',
2121
'DOCUMENT/NAVIGATE_USING_KEYBOARD',
2222
'DOCUMENT/JUMP_TO_NODE',
23+
'view/selection/select-all',
2324
]);
2425

2526
const editMainSplitEvents = new Set<ActionType>([
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { Column } from 'src/stores/document/document-state-type';
2+
import { DocumentViewState } from 'src/stores/view/view-state-type';
3+
import { findGroupByNodeId } from 'src/lib/tree-utils/find/find-group-by-node-id';
4+
import invariant from 'tiny-invariant';
5+
import { findNodeColumn } from 'src/lib/tree-utils/find/find-node-column';
6+
7+
export type SelectAllNodesAction = {
8+
type: 'view/selection/select-all';
9+
};
10+
11+
const compareSetToArray = (set: Set<string>, array: string[]) => {
12+
return set.size === array.length && array.every((node) => set.has(node));
13+
};
14+
15+
export const selectAllNodes = (state: DocumentViewState, columns: Column[]) => {
16+
const firstColumnNodes = columns[0].groups[0].nodes;
17+
const rootColumnIsSelected = compareSetToArray(
18+
state.selectedNodes,
19+
firstColumnNodes,
20+
);
21+
22+
if (rootColumnIsSelected) {
23+
return;
24+
}
25+
26+
const column = columns[findNodeColumn(columns, state.activeNode)];
27+
invariant(column);
28+
const nodeColumnNodes = column.groups.flatMap((g) => g.nodes);
29+
const columnIsSelected = compareSetToArray(
30+
state.selectedNodes,
31+
nodeColumnNodes,
32+
);
33+
if (columnIsSelected) {
34+
state.selectedNodes = new Set(firstColumnNodes);
35+
state.activeNode = state.activeBranch.sortedParentNodes[0];
36+
return;
37+
}
38+
39+
const nodeGroup = findGroupByNodeId(columns, state.activeNode);
40+
invariant(nodeGroup);
41+
const groupIsSelected = compareSetToArray(
42+
state.selectedNodes,
43+
nodeGroup.nodes,
44+
);
45+
if (groupIsSelected) {
46+
state.selectedNodes = new Set(nodeColumnNodes);
47+
return;
48+
}
49+
50+
state.selectedNodes = new Set(nodeGroup.nodes);
51+
};

src/stores/view/subscriptions/effects/align-branch/constants/action-priority.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const actionPriorityRecord: Partial<Record<PluginAction['type'], number>> = {
1313
'view/set-active-node/search': 30,
1414
'view/align-branch/center-node': 30,
1515
'view/align-branch/reveal-node': 30,
16+
'view/selection/select-all': 30,
1617
'DOCUMENT/SET_NODE_CONTENT': 30,
1718
'view/set-active-node/document': 20,
1819
'view/main/disable-edit': 20,

src/stores/view/view-reducer.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { toggleCollapseAllNodes } from 'src/stores/view/reducers/outline/toggle-
2727
import { collapseNode } from 'src/stores/view/reducers/outline/helpers/collapse-node';
2828
import { expandParentsOfActiveNode } from 'src/stores/view/reducers/outline/expand-parents-of-active-node';
2929
import { LineageDocument } from 'src/stores/document/document-state-type';
30+
import { selectAllNodes } from 'src/stores/view/reducers/selection/select-all-nodes';
3031

3132
const updateDocumentState = (
3233
state: ViewState,
@@ -149,6 +150,8 @@ const updateDocumentState = (
149150
toggleFuzzySearch(state);
150151
} else if (action.type === 'DOCUMENT/CLEAR_SELECTION') {
151152
resetSelectionState(state.document);
153+
} else if (action.type === 'view/selection/select-all') {
154+
selectAllNodes(state.document, context.columns);
152155
} else if (action.type === 'NAVIGATION/SELECT_NEXT_NODE') {
153156
navigateActiveNode(state.document, state, action);
154157
} else if (action.type === 'view/pinned-nodes/set-active-node') {

src/stores/view/view-store-actions.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { ToggleShowAllNodesAction } from 'src/stores/view/reducers/search/toggle
1515
import { StyleRulesResult } from 'src/stores/view/subscriptions/effects/style-rules/helpers/process-style-rules';
1616
import { LeftSidebarTab } from 'src/stores/settings/settings-type';
1717
import { ConflictingHotkeys } from 'src/obsidian/helpers/get-used-hotkeys';
18+
import { SelectAllNodesAction } from 'src/stores/view/reducers/selection/select-all-nodes';
1819

1920
export type ViewStoreAction =
2021
| SearchAction
@@ -103,7 +104,8 @@ export type NodeSelectionAction =
103104
| JumpToNodeAction
104105
| ChangeActiveNodeAction
105106
| SetActiveNodeAction
106-
| NodeNavigationAction;
107+
| NodeNavigationAction
108+
| SelectAllNodesAction;
107109

108110
export type SidebarActions =
109111
| PinnedNodesActions

src/view/actions/context-menu/card-context-menu/helpers/copy-link-to-block.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export const copyLinkToBlock = async (
4545
});
4646
const link = `[[${fileName}#^${output.blockId}]]`;
4747
await navigator.clipboard.writeText(link);
48-
new Notice('Link copied to clipboard');
48+
new Notice('Copied');
4949
} else {
5050
new Notice('Could not copy link to clipboard');
5151
}

src/view/actions/keyboard-shortcuts/helpers/commands/commands/selection-commands.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,23 @@ import { DefaultViewCommand } from 'src/view/actions/keyboard-shortcuts/helpers/
33
export const selectionCommands = () => {
44
const commands: DefaultViewCommand[] = [];
55
commands.push(
6+
{
7+
name: 'select_all_nodes',
8+
callback: (view, e) => {
9+
e.preventDefault();
10+
e.stopPropagation();
11+
view.viewStore.dispatch({
12+
type: 'view/selection/select-all',
13+
});
14+
},
15+
hotkeys: [
16+
{
17+
key: 'a',
18+
modifiers: ['Mod'],
19+
editorState: 'editor-off',
20+
},
21+
],
22+
},
623
{
724
name: 'extend_select_up',
825
callback: (view, event) => {

0 commit comments

Comments
 (0)