@@ -34,7 +34,7 @@ type GitPane struct {
3434 passInput textinput.Model // Input field for Git password or GitHub PAT (ghp_*)
3535
3636 // Button state
37- // selectedButton: 0=Clone, 1=Pull, 2=Push , 3=Fetch , 4=Stage , 5=Status , 6=Restore
37+ // selectedButton: 0=Clone, 1=Pull, 2=Fetch , 3=Stage , 4=Commit , 5=Push , 6=Status, 7 =Restore
3838 selectedButton int
3939
4040 // Status display
@@ -143,6 +143,11 @@ type GitFetchMsg struct {
143143// GitStageMsg is sent when the user activates the Stage button.
144144type GitStageMsg struct {}
145145
146+ // GitCommitMsg is sent when the user activates the Commit button.
147+ type GitCommitMsg struct {
148+ Message string
149+ }
150+
146151// GitStatusMsg is sent when the user activates the Status button.
147152type GitStatusMsg struct {}
148153
@@ -319,6 +324,19 @@ func (g *GitPane) executeStage() tea.Cmd {
319324 }
320325}
321326
327+ // executeCommit triggers an async commit operation.
328+ // It sets the isProcessing flag and returns a command that will execute the commit
329+ // and send a GitCommitMsg when complete.
330+ func (g * GitPane ) executeCommit (message string ) tea.Cmd {
331+ g .isProcessing = true
332+
333+ return func () tea.Msg {
334+ return GitCommitMsg {
335+ Message : message ,
336+ }
337+ }
338+ }
339+
322340// executeStatus triggers an async status operation.
323341// It sets the isProcessing flag and returns a command that will execute the status
324342// and send a GitStatusMsg when complete.
@@ -462,6 +480,18 @@ func (g *GitPane) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
462480 }
463481 }
464482
483+ case GitCommitMsg :
484+ // Handle commit operation - execute async via GitClient
485+ return g , func () tea.Msg {
486+ result , _ := g .gitClient .Commit (msg .Message )
487+ return GitOperationCompleteMsg {
488+ Operation : "commit" ,
489+ Success : result .Success ,
490+ Message : result .Message ,
491+ Error : result .Error ,
492+ }
493+ }
494+
465495 case GitStatusMsg :
466496 // Handle status operation - execute async via GitClient
467497 return g , func () tea.Msg {
@@ -531,15 +561,17 @@ func (g *GitPane) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
531561 return g , g .executeClone (url , username , password )
532562 case 1 : // Pull
533563 return g , g .executePull (username , password )
534- case 2 : // Push
535- return g , g .executePush (username , password )
536- case 3 : // Fetch
564+ case 2 : // Fetch
537565 return g , g .executeFetch (username , password )
538- case 4 : // Stage
566+ case 3 : // Stage
539567 return g , g .executeStage ()
540- case 5 : // Status
568+ case 4 : // Commit
569+ return g , g .executeCommit ("Update files" )
570+ case 5 : // Push
571+ return g , g .executePush (username , password )
572+ case 6 : // Status
541573 return g , g .executeStatus ()
542- case 6 : // Restore
574+ case 7 : // Restore
543575 return g , g .executeRestore ()
544576 }
545577 return g , nil
@@ -552,11 +584,11 @@ func (g *GitPane) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
552584 if msg .String () == "left" {
553585 g .selectedButton --
554586 if g .selectedButton < 0 {
555- g .selectedButton = 6 // Wrap to last button (Restore)
587+ g .selectedButton = 7 // Wrap to last button (Restore)
556588 }
557589 } else { // "right"
558590 g .selectedButton ++
559- if g .selectedButton > 6 {
591+ if g .selectedButton > 7 {
560592 g .selectedButton = 0 // Wrap to first button (Clone)
561593 }
562594 }
@@ -616,7 +648,7 @@ func (g *GitPane) View() string {
616648 Border (lipgloss .RoundedBorder ()).
617649 BorderForeground (lipgloss .Color ("62" )).
618650 Padding (1 , 2 ).
619- Width (80 )
651+ Width (84 )
620652
621653 buttonStyle := lipgloss .NewStyle ().
622654 Foreground (lipgloss .Color ("230" )).
@@ -654,8 +686,8 @@ func (g *GitPane) View() string {
654686 content .WriteString (g .passInput .View ())
655687 content .WriteString ("\n \n " )
656688
657- // Buttons - distribute evenly across the panel width
658- buttonNames := []string {"Clone" , "Pull" , "Push " , "Fetch " , "Stage " , "Status" , "Restore" }
689+ // Buttons - reordered and grouped: Clone Pull Fetch | Stage Commit Push | Status Restore
690+ buttonNames := []string {"Clone" , "Pull" , "Fetch " , "Stage " , "Commit" , "Push " , "Status" , "Restore" }
659691 var buttons []string
660692 for i , name := range buttonNames {
661693 if g .focusedInput == 3 && g .selectedButton == i {
@@ -665,21 +697,18 @@ func (g *GitPane) View() string {
665697 }
666698 }
667699
668- // Calculate total button width and spacing
669- // Panel content width is 84 - 4 (border) - 4 (padding) = 76
670- // Each button has padding(0, 1) which adds 2 chars per button, plus the text length
671- // Button text lengths: Clone(5), Pull(4), Push(4), Fetch(5), Stage(5), Status(6), Restore(7)
672- // Total text: 36 chars, with padding: 36 + (7 buttons * 2) = 50 chars
673- // Available space for gaps: 76 - 50 = 26 chars
674- // Number of gaps between 7 buttons: 6 gaps
675- // Space per gap: 26 / 6 ≈ 4 chars (with some remainder)
700+ // Create button row with spacing and separators
701+ // Group 1: Clone Pull Fetch (remote operations)
702+ buttonRow := buttons [0 ] + " " + buttons [1 ] + " " + buttons [2 ]
703+ // Separator
704+ buttonRow += " | "
705+ // Group 2: Stage Commit Push (local to remote workflow)
706+ buttonRow += buttons [3 ] + " " + buttons [4 ] + " " + buttons [5 ]
707+ // Separator
708+ buttonRow += " | "
709+ // Group 3: Status Restore (info and undo)
710+ buttonRow += buttons [6 ] + " " + buttons [7 ]
676711
677- // Create evenly spaced button row
678- buttonRow := buttons [0 ]
679- for i := 1 ; i < len (buttons ); i ++ {
680- // Add spacing between buttons (4 spaces for even distribution)
681- buttonRow += " " + buttons [i ]
682- }
683712 content .WriteString (buttonRow )
684713 content .WriteString ("\n \n " )
685714
0 commit comments