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

feat: multiple tabs - [INS-4225] #8151

Open
wants to merge 34 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
d12e356
feat: multiple tabs
CurryYangxx Nov 6, 2024
c176263
fix: lint error
CurryYangxx Nov 6, 2024
3e3baef
fix: type error
CurryYangxx Nov 6, 2024
49300e4
fix: ui border align
CurryYangxx Nov 7, 2024
c004802
feat: sync with db
CurryYangxx Nov 7, 2024
0003691
feat: sync with database
CurryYangxx Nov 7, 2024
c89b5af
ui improvement
CurryYangxx Nov 11, 2024
d9f0666
fix: mock route display
CurryYangxx Nov 11, 2024
1f01e20
add dropdown
CurryYangxx Nov 12, 2024
dbd5825
+ button
CurryYangxx Nov 12, 2024
1fc8336
move search box to center
CurryYangxx Nov 14, 2024
4ee9901
fix: cannot del request tab
CurryYangxx Nov 14, 2024
4c1a28a
fix ui
CurryYangxx Nov 15, 2024
e6df7a1
tab background improvement
CurryYangxx Nov 15, 2024
1da43ee
change tab background
CurryYangxx Nov 18, 2024
53397d1
feat: add list scroll
CurryYangxx Nov 18, 2024
3435d73
ui improvement
CurryYangxx Nov 18, 2024
530be35
feat: add tab contextmenu
CurryYangxx Nov 20, 2024
1fe4abd
modify menu text
CurryYangxx Nov 20, 2024
154a3c5
fix(ui): tab disappear in panelgroup
CurryYangxx Nov 21, 2024
394aa87
feat: optimize tablist scroll button
CurryYangxx Nov 21, 2024
9cbd86b
add context menu enum
CurryYangxx Nov 21, 2024
f631130
del log
CurryYangxx Nov 25, 2024
24e205f
fix: rename workspace
CurryYangxx Nov 26, 2024
45bbd0f
feat: scroll into view if needed
CurryYangxx Nov 27, 2024
dc4e323
fix: runner request list not update after switch tab
CurryYangxx Nov 27, 2024
2ea4b20
fix: runner not update
CurryYangxx Nov 28, 2024
e133d3c
feat: use different tab if for collection runner and folder runner
CurryYangxx Nov 28, 2024
cf41482
fix: update tab data after move request or folder
CurryYangxx Dec 2, 2024
eb0314c
fix: database test
CurryYangxx Dec 2, 2024
85b6ac4
feat: support drag and drop
CurryYangxx Dec 3, 2024
0225ba9
fix: ui
CurryYangxx Dec 3, 2024
91e3eca
cr feedback
CurryYangxx Dec 5, 2024
f4cbf3c
fix tab update
CurryYangxx Dec 9, 2024
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
24 changes: 12 additions & 12 deletions packages/insomnia/src/common/__tests__/database.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ describe('onChange()', () => {
name: 'bar',
});
expect(changesSeen).toEqual([
[['insert', newDoc, false]],
[['update', updatedDoc, false]],
[['insert', newDoc, false, []]],
[['update', updatedDoc, false, [{ name: 'bar' }]]],
]);
db.offChange(callback);
await models.request.create(doc);
Expand Down Expand Up @@ -71,16 +71,16 @@ describe('bufferChanges()', () => {
await db.flushChanges();
expect(changesSeen).toEqual([
[
['insert', newDoc, false],
['update', updatedDoc, false],
['insert', newDoc, false, []],
['update', updatedDoc, false, [true]],
],
]);
// Assert no more changes seen after flush again
await db.flushChanges();
expect(changesSeen).toEqual([
[
['insert', newDoc, false],
['update', updatedDoc, false],
['insert', newDoc, false, []],
['update', updatedDoc, false, [true]],
],
]);
});
Expand All @@ -106,8 +106,8 @@ describe('bufferChanges()', () => {
await new Promise(resolve => setTimeout(resolve, 1500));
expect(changesSeen).toEqual([
[
['insert', newDoc, false],
['update', updatedDoc, false],
['insert', newDoc, false, []],
['update', updatedDoc, false, [true]],
],
]);
});
Expand All @@ -132,8 +132,8 @@ describe('bufferChanges()', () => {
await new Promise(resolve => setTimeout(resolve, 1000));
expect(changesSeen).toEqual([
[
['insert', newDoc, false],
['update', updatedDoc, false],
['insert', newDoc, false, []],
['update', updatedDoc, false, [true]],
],
]);
});
Expand Down Expand Up @@ -166,8 +166,8 @@ describe('bufferChangesIndefinitely()', () => {
await db.flushChanges();
expect(changesSeen).toEqual([
[
['insert', newDoc, false],
['update', updatedDoc, false],
['insert', newDoc, false, []],
['update', updatedDoc, false, [true]],
],
]);
});
Expand Down
14 changes: 8 additions & 6 deletions packages/insomnia/src/common/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export const database = {
},
...patches,
);
return database.update<T>(doc);
return database.update<T>(doc, false, patches);
},

/** duplicate doc and its decendents recursively */
Expand Down Expand Up @@ -524,7 +524,7 @@ export const database = {
notifyOfChange('remove', doc, fromSync);
},

update: async function<T extends BaseModel>(doc: T, fromSync = false) {
update: async function <T extends BaseModel>(doc: T, fromSync = false, patches: Patch<T>[] = []) {
if (db._empty) {
return _send<T>('update', ...arguments);
}
Expand All @@ -550,7 +550,7 @@ export const database = {

resolve(docWithDefaults);
// NOTE: This needs to be after we resolve
notifyOfChange('update', docWithDefaults, fromSync);
notifyOfChange('update', docWithDefaults, fromSync, patches);
},
);
});
Expand Down Expand Up @@ -698,7 +698,8 @@ let bufferChangesId = 1;
export type ChangeBufferEvent<T extends BaseModel = BaseModel> = [
event: ChangeType,
doc: T,
fromSync: boolean
fromSync: boolean,
patches: Patch<T>[],
];

let changeBuffer: ChangeBufferEvent[] = [];
Expand All @@ -709,10 +710,11 @@ let changeListeners: ChangeListener[] = [];

/** push changes into the buffer, so that changeListeners can get change contents when database.flushChanges is called,
* this method should be called whenever a document change happens */
async function notifyOfChange<T extends BaseModel>(event: ChangeType, doc: T, fromSync: boolean) {
async function notifyOfChange<T extends BaseModel>(event: ChangeType, doc: T, fromSync: boolean, patches: Patch<T>[] = []) {
const updatedDoc = doc;

changeBuffer.push([event, updatedDoc, fromSync]);
// TODO: Use object is better than array
changeBuffer.push([event, updatedDoc, fromSync, patches]);

// Flush right away if we're not buffering
if (!bufferingChanges) {
Expand Down
27 changes: 21 additions & 6 deletions packages/insomnia/src/main/ipc/electron.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ export type MainOnChannels =
| 'restart'
| 'set-hidden-window-busy-status'
| 'setMenuBarVisibility'
| 'show-context-menu'
| 'show-nunjucks-context-menu'
| 'showContextMenu'
| 'showItemInFolder'
| 'showOpenDialog'
| 'showSaveDialog'
Expand All @@ -73,7 +74,8 @@ export type MainOnChannels =
export type RendererOnChannels =
'clear-all-models'
| 'clear-model'
| 'context-menu-command'
| 'nunjucks-context-menu-command'
| 'contextMenuCommand'
| 'grpc.data'
| 'grpc.end'
| 'grpc.error'
Expand Down Expand Up @@ -114,10 +116,10 @@ const getTemplateValue = (arg: NunjucksParsedTagArg) => {
return arg.defaultValue;
};
export function registerElectronHandlers() {
ipcMainOn('show-context-menu', (event, options: { key: string; nunjucksTag: ReturnType<typeof extractNunjucksTagFromCoords> }) => {
ipcMainOn('show-nunjucks-context-menu', (event, options: { key: string; nunjucksTag: ReturnType<typeof extractNunjucksTagFromCoords> }) => {
const { key, nunjucksTag } = options;
const sendNunjuckTagContextMsg = (type: NunjucksTagContextMenuAction) => {
event.sender.send('context-menu-command', { key, nunjucksTag: { ...nunjucksTag, type } });
event.sender.send('nunjucks-context-menu-command', { key, nunjucksTag: { ...nunjucksTag, type } });
};
try {
const baseTemplate: MenuItemConstructorOptions[] = nunjucksTag ?
Expand Down Expand Up @@ -170,7 +172,7 @@ export function registerElectronHandlers() {
{
click: () => {
const tag = `{% ${l.templateTag.name} ${l.templateTag.args?.map(getTemplateValue).join(', ')} %}`;
event.sender.send('context-menu-command', { key, tag });
event.sender.send('nunjucks-context-menu-command', { key, tag });
},
} :
{
Expand All @@ -179,7 +181,7 @@ export function registerElectronHandlers() {
click: () => {
const additionalTagFields = additionalArgs.length ? ', ' + additionalArgs.map(getTemplateValue).join(', ') : '';
const tag = `{% ${l.templateTag.name} '${action.value}'${additionalTagFields} %}`;
event.sender.send('context-menu-command', { key, tag });
event.sender.send('nunjucks-context-menu-command', { key, tag });
},
})),
}),
Expand Down Expand Up @@ -236,4 +238,17 @@ export function registerElectronHandlers() {
ipcMainOn('getAppPath', event => {
event.returnValue = app.getAppPath();
});

ipcMainOn('showContextMenu', (event, options: { key: string; menuItems: MenuItemConstructorOptions[]; extra?: Record<string, any> }) => {
const menuItems = options.menuItems.map(item => {
return {
...item,
click: () => {
event.sender.send('contextMenuCommand', { key: options.key, label: item.label, extra: options.extra });
},
};
});
const menu = Menu.buildFromTemplate(menuItems);
menu.popup();
});
}
6 changes: 4 additions & 2 deletions packages/insomnia/src/main/ipc/main.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as Sentry from '@sentry/electron/main';
import type { MarkerRange } from 'codemirror';
import { app, BrowserWindow, type IpcRendererEvent, shell } from 'electron';
import { app, BrowserWindow, type IpcRendererEvent, type MenuItemConstructorOptions, shell } from 'electron';
import fs from 'fs';

import { APP_START_TIME, LandingPage, SentryMetrics } from '../../common/sentry';
Expand Down Expand Up @@ -39,7 +39,9 @@ export interface RendererToMainBridgeAPI {
curl: CurlBridgeAPI;
trackSegmentEvent: (options: { event: string; properties?: Record<string, unknown> }) => void;
trackPageView: (options: { name: string }) => void;
showContextMenu: (options: { key: string; nunjucksTag?: { template: string; range: MarkerRange } }) => void;
showNunjucksContextMenu: (options: { key: string; nunjucksTag?: { template: string; range: MarkerRange } }) => void;
showContextMenu: (options: { key: string; menuItems: MenuItemConstructorOptions[]; extra?: Record<string, any> }) => void;

database: {
caCertificate: {
create: (options: { parentId: string; path: string }) => Promise<string>;
Expand Down
3 changes: 2 additions & 1 deletion packages/insomnia/src/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ const main: Window['main'] = {
curl,
trackSegmentEvent: options => ipcRenderer.send('trackSegmentEvent', options),
trackPageView: options => ipcRenderer.send('trackPageView', options),
showContextMenu: options => ipcRenderer.send('show-context-menu', options),
showNunjucksContextMenu: options => ipcRenderer.send('show-nunjucks-context-menu', options),
showContextMenu: options => ipcRenderer.send('showContextMenu', options),
database: {
caCertificate: {
create: options => ipcRenderer.invoke('database.caCertificate.create', options),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ export const CodeEditor = memo(forwardRef<CodeEditorHandle, CodeEditorProps>(({
}
};
useEffect(() => {
const unsubscribe = window.main.on('context-menu-command', (_, { key, tag, nunjucksTag }) => {
const unsubscribe = window.main.on('nunjucks-context-menu-command', (_, { key, tag, nunjucksTag }) => {
if (id === key) {
if (nunjucksTag) {
const { type, template, range } = nunjucksTag as nunjucksTagContextMenuOptions;
Expand Down Expand Up @@ -657,10 +657,10 @@ export const CodeEditor = memo(forwardRef<CodeEditorHandle, CodeEditorProps>(({
const nunjucksTag = extractNunjucksTagFromCoords({ left: clientX, top: clientY }, codeMirror);
if (nunjucksTag) {
// show context menu for nunjucks tag
window.main.showContextMenu({ key: id, nunjucksTag });
window.main.showNunjucksContextMenu({ key: id, nunjucksTag });
}
} else {
window.main.showContextMenu({ key: id });
window.main.showNunjucksContextMenu({ key: id });
}
}}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ export const OneLineEditor = forwardRef<OneLineEditorHandle, OneLineEditorProps>
}, [onChange]);

useEffect(() => {
const unsubscribe = window.main.on('context-menu-command', (_, { key, tag, nunjucksTag }) => {
const unsubscribe = window.main.on('nunjucks-context-menu-command', (_, { key, tag, nunjucksTag }) => {
if (id === key) {
if (nunjucksTag) {
const { type, template, range } = nunjucksTag as nunjucksTagContextMenuOptions;
Expand Down Expand Up @@ -310,10 +310,10 @@ export const OneLineEditor = forwardRef<OneLineEditorHandle, OneLineEditorProps>
const nunjucksTag = extractNunjucksTagFromCoords({ left: clientX, top: clientY }, codeMirror);
if (nunjucksTag) {
// show context menu for nunjucks tag
window.main.showContextMenu({ key: id, nunjucksTag });
window.main.showNunjucksContextMenu({ key: id, nunjucksTag });
}
} else {
window.main.showContextMenu({ key: id });
window.main.showNunjucksContextMenu({ key: id });
}
}}
>
Expand Down
34 changes: 34 additions & 0 deletions packages/insomnia/src/ui/components/document-tab.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import classnames from 'classnames';
import React from 'react';
import { NavLink } from 'react-router-dom';

interface Props {
organizationId: string;
projectId: string;
workspaceId: string;
className?: string;
}

export const DocumentTab = ({ organizationId, projectId, workspaceId, className }: Props) => {
return (
<nav className={`flex w-full h-[40px] items-center ${className} px-1 justify-around`}>
{[
{ id: 'spec', name: 'Spec' },
{ id: 'debug', name: 'Collection' },
{ id: 'test', name: 'Tests' },
].map(item => (
<NavLink
key={item.id}
to={`/organization/${organizationId}/project/${projectId}/workspace/${workspaceId}/${item.id}`}
className={({ isActive, isPending }) => classnames('text-center rounded-full px-2', {
'text-[--color-font] bg-[--color-surprise]': isActive,
'animate-pulse': isPending,
})}
data-testid={`workspace-${item.id}`}
>
{item.name}
</NavLink>
))}
</nav>
);
};
Loading
Loading