feat(electron): app tabs dnd (#7684)

<div class='graphite__hidden'>
          <div>🎥 Video uploaded on Graphite:</div>
            <a href="https://app.graphite.dev/media/video/T2klNLEk0wxLh4NRDzhk/cd84e155-9f2e-4d12-a933-8673eb6bc6cb.mp4">
              <img src="https://app.graphite.dev/api/v1/graphite/video/thumbnail/T2klNLEk0wxLh4NRDzhk/cd84e155-9f2e-4d12-a933-8673eb6bc6cb.mp4">
            </a>
          </div>
<video src="https://graphite-user-uploaded-assets-prod.s3.amazonaws.com/T2klNLEk0wxLh4NRDzhk/cd84e155-9f2e-4d12-a933-8673eb6bc6cb.mp4">Kapture 2024-07-31 at 19.39.30.mp4</video>

fix AF-1149
fix PD-1513
fix PD-1515
This commit is contained in:
pengx17
2024-08-02 02:02:03 +00:00
parent 4719ffadc6
commit bfff10e25e
13 changed files with 567 additions and 188 deletions

View File

@@ -18,6 +18,7 @@ import {
initAndShowMainWindow,
isActiveTab,
launchStage,
moveTab,
pingAppLayoutReady,
showDevTools,
showTab,
@@ -193,6 +194,9 @@ export const uiHandlers = {
activateView: async (_, ...args: Parameters<typeof activateView>) => {
await activateView(...args);
},
moveTab: async (_, ...args: Parameters<typeof moveTab>) => {
moveTab(...args);
},
toggleRightSidebar: async (_, tabId?: string) => {
tabId ??= getTabViewsMeta().activeWorkbenchId;
if (tabId) {

View File

@@ -115,8 +115,14 @@ type TabAction =
| OpenInSplitViewAction;
type AddTabOption = {
basename: string;
basename?: string;
view?: Omit<WorkbenchViewMeta, 'id'> | Array<Omit<WorkbenchViewMeta, 'id'>>;
target?: string;
edge?: 'left' | 'right';
/**
* Whether to show the tab after adding.
*/
show?: boolean;
};
export class WebContentViewsManager {
@@ -405,27 +411,32 @@ export class WebContentViewsManager {
id: nanoid(),
};
});
const targetItem =
workbenches.find(w => w.id === option.target) ?? workbenches.at(-1);
const newIndex =
(targetItem ? workbenches.indexOf(targetItem) : workbenches.length) +
(option.edge === 'left' ? 0 : 1);
const workbench: WorkbenchMeta = {
basename: option.basename,
basename: option.basename ?? this.activeWorkbenchMeta?.basename ?? '/',
activeViewIndex: 0,
views: views,
id: newKey,
pinned: false,
pinned: targetItem?.pinned ?? false,
};
this.patchTabViewsMeta({
activeWorkbenchId: newKey,
workbenches: [...workbenches, workbench],
workbenches: workbenches.toSpliced(newIndex, 0, workbench),
activeWorkbenchId: this.activeWorkbenchId ?? newKey,
});
await this.showTab(newKey);
await (option.show !== false ? this.showTab(newKey) : this.loadTab(newKey));
this.tabAction$.next({
type: 'add-tab',
payload: workbench,
});
return {
...option,
key: newKey,
};
return workbench;
};
loadTab = async (id: string): Promise<WebContentsView | undefined> => {
@@ -521,6 +532,42 @@ export class WebContentViewsManager {
await this.showTab(tabId);
};
moveTab = (from: string, to: string, edge?: 'left' | 'right') => {
const workbenches = this.tabViewsMeta.workbenches;
let fromItem = workbenches.find(w => w.id === from);
const toItem = workbenches.find(w => w.id === to);
if (!fromItem || !toItem) {
return;
}
const fromIndex = workbenches.indexOf(fromItem);
fromItem = {
...fromItem,
pinned: toItem.pinned,
};
let workbenchesAfterMove = workbenches.toSpliced(fromIndex, 1);
const toIndex = workbenchesAfterMove.indexOf(toItem);
if (edge === 'left') {
workbenchesAfterMove = workbenchesAfterMove.toSpliced(
toIndex,
0,
fromItem
);
} else {
workbenchesAfterMove = workbenchesAfterMove.toSpliced(
toIndex + 1,
0,
fromItem
);
}
this.patchTabViewsMeta({
workbenches: workbenchesAfterMove,
});
};
separateView = (tabId: string, viewIndex: number) => {
const tabMeta = this.tabViewsMeta.workbenches.find(w => w.id === tabId);
if (!tabMeta) {
@@ -906,6 +953,7 @@ export const showTab = WebContentViewsManager.instance.showTab;
export const closeTab = WebContentViewsManager.instance.closeTab;
export const undoCloseTab = WebContentViewsManager.instance.undoCloseTab;
export const activateView = WebContentViewsManager.instance.activateView;
export const moveTab = WebContentViewsManager.instance.moveTab;
export const reloadView = async () => {
const id = WebContentViewsManager.instance.activeWorkbenchId;