Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
8 changes: 5 additions & 3 deletions Frontend/src/scripts/features/repo/hotkeys.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { filterInput } from './context';
import { disableDefaultSelectAll, state } from '../../state/state';
import { disableDefaultSelectAll, prefs, state } from '../../state/state';
import { getVisibleFiles } from './selectionState';
import { toggleSelectAll } from './interactions';
import { renderList } from './list';
Expand Down Expand Up @@ -29,12 +29,14 @@ export function bindRepoHotkeys(
if (chord && key === 'r') { e.preventDefault(); openSheet('switch'); }
if (chord && e.key === 'Enter') { e.preventDefault(); commitBtn?.click(); }

if (chord && key === 'a' && !e.shiftKey && !e.altKey && !modalOpen && !inEditable) {
if (chord && key === 'a' && !e.shiftKey && !e.altKey && !inEditable) {
e.preventDefault(); // prevent browser "select all text" behavior
if (modalOpen) return;
if (prefs.tab !== 'changes') return;
const visible = getVisibleFiles();
if (visible.length === 0) return;
const selected = visible.filter((f) => f.path && state.selectedFiles.has(f.path)).length;
const allSelected = selected === visible.length;
e.preventDefault();
disableDefaultSelectAll();
toggleSelectAll(!allSelected, visible);
renderList();
Expand Down
35 changes: 18 additions & 17 deletions Frontend/src/scripts/features/repo/interactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,13 +194,16 @@ export function toggleSelectAll(on: boolean, visible: FileStatus[]) {
export function onFileContextMenu(ev: MouseEvent, f: FileStatus) {
ev.preventDefault();
const x = ev.clientX, y = ev.clientY;
const totalFiles = Array.isArray(state.files) ? state.files.length : 0;
const selectedPaths = Array.from(state.selectedFiles || []);
const hasManualSelection = (!state.defaultSelectAll) || (selectedPaths.length > 0 && selectedPaths.length !== totalFiles);
const manualSelection = hasManualSelection ? selectedPaths : [];
const clickedInSelection = manualSelection.includes(f.path);
const hasMultiSelection = manualSelection.length > 1 && clickedInSelection;
const hasSingleSelection = manualSelection.length === 1 && clickedInSelection;
const selectedPaths = Array.from(state.selectedFiles || []).filter(Boolean);
const clickedInSelection = !!f.path && (state.selectedFiles?.has(f.path) ?? false);
const explicitMultiSelection =
clickedInSelection &&
selectedPaths.length > 1 &&
!state.selectionImplicitAll;
const hasSingleSelection =
clickedInSelection &&
selectedPaths.length === 1 &&
!state.selectionImplicitAll;
const items: CtxItem[] = [];
const openStashForPaths = (paths: string[], defaultMessage: string) => {
if (!paths.length) return;
Expand All @@ -221,22 +224,20 @@ export function onFileContextMenu(ev: MouseEvent, f: FileStatus) {
try { await TAURI.invoke('git_discard_paths', { paths: [f.path] }); await Promise.allSettled([hydrateStatus()]); }
catch { notify('Discard failed'); }
}});
if (hasManualSelection && clickedInSelection) {
items.push({ label: 'Discard selected files', action: async () => {
if (explicitMultiSelection) {
items.push({ label: 'Discard all selected', action: async () => {
if (!TAURI.has) return;
const paths = manualSelection.slice();
const paths = selectedPaths.slice();
const ok = window.confirm(`Discard all changes in ${paths.length} selected file(s)? This cannot be undone.`);
if (!ok) return;
try { await TAURI.invoke('git_discard_paths', { paths }); await Promise.allSettled([hydrateStatus()]); }
catch { notify('Discard failed'); }
}});
if (hasMultiSelection) {
items.push({ label: 'Create stash from selection…', action: () => {
openStashForPaths(manualSelection.slice(), 'WIP selection');
}});
}
items.push({ label: 'Create stash from selection…', action: () => {
openStashForPaths(selectedPaths.slice(), 'WIP selection');
}});
}
const singleTarget = hasSingleSelection ? manualSelection[0] : f.path;
const singleTarget = hasSingleSelection ? selectedPaths[0] : f.path;
const defaultMsg = `WIP ${singleTarget}`;
items.push({ label: 'Create stash for this file…', action: () => {
openStashForPaths([singleTarget], defaultMsg);
Expand All @@ -247,7 +248,7 @@ export function onFileContextMenu(ev: MouseEvent, f: FileStatus) {
notify('Git LFS is available in the desktop app');
return;
}
const targets = (hasManualSelection && clickedInSelection ? manualSelection.slice() : [f.path]).filter(Boolean);
const targets = (explicitMultiSelection ? selectedPaths.slice() : [f.path]).filter(Boolean);
if (!targets.length) return;
(async () => {
try {
Expand Down
Loading