diff --git a/packages/app-desktop/gui/ResizableLayout/utils/movements.test.ts b/packages/app-desktop/gui/ResizableLayout/utils/movements.test.ts index 805464982d..6ce421ce6d 100644 --- a/packages/app-desktop/gui/ResizableLayout/utils/movements.test.ts +++ b/packages/app-desktop/gui/ResizableLayout/utils/movements.test.ts @@ -1,6 +1,6 @@ import { LayoutItem, LayoutItemDirection } from './types'; import validateLayout from './validateLayout'; -import { canMove, MoveDirection, moveHorizontal, moveVertical } from './movements'; +import { canMove, ItemSide, MoveDirection, moveHorizontal, moveItemNear, moveVertical } from './movements'; import findItemByKey from './findItemByKey'; describe('movements', () => { @@ -225,4 +225,37 @@ describe('movements', () => { expect(layout.children[1].width).toBe(undefined); }); + test('should move an item near another one', () => { + let layout: LayoutItem = validateLayout({ + key: 'root', + width: 200, + height: 100, + direction: LayoutItemDirection.Row, + children: [ + { + key: 'col1', + resizableRight: true, + direction: LayoutItemDirection.Column, + children: [ + { key: 'item1' }, + { key: 'item2' }, + ], + }, + { + key: 'col2', + }, + ], + }); + + // If parent is a ROW and putting item on top of sibling - first move to + // the left, then move right so that item goes inside new container + + layout = moveItemNear(layout, 'item1', 'col2', ItemSide.Top); + + console.info(layout); + + // expect(layout.children[0].width).toBe(20); + // expect(layout.children[1].width).toBe(undefined); + }); + }); diff --git a/packages/app-desktop/gui/ResizableLayout/utils/movements.ts b/packages/app-desktop/gui/ResizableLayout/utils/movements.ts index eee79ca20d..0f4e0cee3c 100644 --- a/packages/app-desktop/gui/ResizableLayout/utils/movements.ts +++ b/packages/app-desktop/gui/ResizableLayout/utils/movements.ts @@ -3,6 +3,8 @@ import { LayoutItem, LayoutItemDirection, tempContainerPrefix } from './types'; import produce from 'immer'; import uuid from '@joplin/lib/uuid'; import validateLayout from './validateLayout'; +import findItemByKey from './findItemByKey'; +import removeItem from './removeItem'; export enum MoveDirection { Up = 'up', @@ -11,6 +13,13 @@ export enum MoveDirection { Right = 'right', } +export enum ItemSide { + Top = 'top', + Bottom = 'bottom', + Left = 'left', + Right = 'right', +} + enum MovementDirection { Horizontal = 1, Vertical = 2, @@ -188,3 +197,42 @@ export function move(layout: LayoutItem, key: string, direction: MoveDirection): if (direction === MoveDirection.Right) return moveHorizontal(layout, key, +1); throw new Error('Unreachable'); } + +export function moveItemNear(layout:LayoutItem, itemKey:string, nearItemKey:string, side: ItemSide): LayoutItem { + const itemToInsert = findItemByKey(layout, itemKey); + const layoutWithoutItem = removeItem(layout, itemKey); + + let moveDirection:MoveDirection = null; + + const sideToDirectionMap = { + [ItemSide.Top]: MoveDirection.Up, + [ItemSide.Bottom]: MoveDirection.Down, + [ItemSide.Left]: MoveDirection.Left, + [ItemSide.Right]: MoveDirection.Right, + }; + + const layoutWithInsertedItem = produce(layoutWithoutItem, (draft: any) => { + iterateItems(draft, (itemIndex: number, item: LayoutItem, parent: LayoutItem) => { + if (item.key !== nearItemKey) return true; + parent.children.splice(itemIndex, 0, itemToInsert); + + if ( + parent.direction === LayoutItemDirection.Column && side === ItemSide.Top || + parent.direction === LayoutItemDirection.Row && side === ItemSide.Left + ) { + // Nothing to do - already in position + } else { + moveDirection = sideToDirectionMap[side]; + } + + return false; + }); + }); + + console.info(JSON.stringify(layoutWithInsertedItem, null, 4)); + + console.info('MOVE', moveDirection); + + const updatedLayout = moveDirection ? move(layoutWithInsertedItem, itemKey, moveDirection) : layoutWithInsertedItem; + return validateLayout(updatedLayout); +} \ No newline at end of file diff --git a/packages/lib/services/plugins/api/JoplinViewsPanels.ts b/packages/lib/services/plugins/api/JoplinViewsPanels.ts index 60395b4a78..62bdf323a7 100644 --- a/packages/lib/services/plugins/api/JoplinViewsPanels.ts +++ b/packages/lib/services/plugins/api/JoplinViewsPanels.ts @@ -3,6 +3,20 @@ import createViewHandle from '../utils/createViewHandle'; import WebviewController, { ContainerType } from '../WebviewController'; import { ViewHandle } from './types'; +interface InitialPosition { + nextTo: string, +} + +// initialPosition: { +// nextTo: 'editor', +// side: '',top, right, bottom , left +// size: 100, +// } + +interface CreateOptions { + initialPosition: InitialPosition, +} + /** * Allows creating and managing view panels. View panels currently are * displayed at the right of the sidebar and allows displaying any HTML @@ -29,7 +43,7 @@ export default class JoplinViewsPanels { /** * Creates a new panel */ - async create(id: string): Promise { + async create(id: string, options:CreateOptions = null): Promise { if (!id) { this.plugin.deprecationNotice('1.5', 'Creating a view without an ID is deprecated. To fix it, change your call to `joplin.views.panels.create("my-unique-id")`'); id = `${this.plugin.viewCount}`;