v0.33.1 9577fee

extract_pane_to_tab_list.go RawHistoryFolder

1package usecase
2
3import (
4	"fmt"
5
6	"github.com/bnema/dumber/internal/domain/entity"
7)
8
9// ExtractPaneToTabListUseCase moves a pane from a source tab list into a new
10// tab in a target tab list. It is pure domain manipulation and has no
11// knowledge of browser windows or UI objects.
12type ExtractPaneToTabListUseCase struct {
13	idGenerator IDGenerator
14}
15
16func NewExtractPaneToTabListUseCase(idGenerator IDGenerator) *ExtractPaneToTabListUseCase {
17	return &ExtractPaneToTabListUseCase{idGenerator: idGenerator}
18}
19
20type ExtractPaneToTabListInput struct {
21	SourceTabs   *entity.TabList
22	SourceTabID  entity.TabID
23	SourcePaneID entity.PaneID
24	TargetTabs   *entity.TabList
25}
26
27type ExtractPaneToTabListOutput struct {
28	NewTab          *entity.Tab
29	MovedPaneNode   *entity.PaneNode
30	SourceTabClosed bool
31}
32
33func (uc *ExtractPaneToTabListUseCase) Execute(input ExtractPaneToTabListInput) (*ExtractPaneToTabListOutput, error) {
34	if err := validateExtractPaneToTabListInput(uc, input); err != nil {
35		return nil, err
36	}
37
38	sourceTab, err := findSourceTab(input.SourceTabs, input.SourceTabID)
39	if err != nil {
40		return nil, err
41	}
42
43	movedPane, sourceNode, err := findSourcePane(sourceTab.Workspace, input.SourcePaneID)
44	if err != nil {
45		return nil, err
46	}
47
48	if err := detachPaneFromWorkspace(sourceTab.Workspace, sourceNode); err != nil {
49		return nil, err
50	}
51
52	sourceTabClosed := closeSourceTabIfEmpty(input.SourceTabs, sourceTab)
53
54	tabID := entity.TabID(uc.idGenerator())
55	workspaceID := entity.WorkspaceID(uc.idGenerator())
56	newTab := entity.NewTab(tabID, workspaceID, movedPane)
57	input.TargetTabs.Add(newTab)
58
59	return &ExtractPaneToTabListOutput{
60		NewTab:          newTab,
61		MovedPaneNode:   newTab.Workspace.Root,
62		SourceTabClosed: sourceTabClosed,
63	}, nil
64}
65
66func validateExtractPaneToTabListInput(uc *ExtractPaneToTabListUseCase, input ExtractPaneToTabListInput) error {
67	if uc == nil {
68		return fmt.Errorf("extract pane to tab list use case is nil")
69	}
70	if input.SourceTabs == nil {
71		return fmt.Errorf("source tabs are required")
72	}
73	if input.TargetTabs == nil {
74		return fmt.Errorf("target tabs are required")
75	}
76	if input.SourceTabID == "" {
77		return fmt.Errorf("source tab id is required")
78	}
79	if input.SourcePaneID == "" {
80		return fmt.Errorf("source pane id is required")
81	}
82	if uc.idGenerator == nil {
83		return fmt.Errorf("id generator is required")
84	}
85	return nil
86}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 8

Tags 42

↑↓ moveenter openesc close