@@ -78,6 +78,7 @@ type Model struct {
7878 listView listViewModel
7979 workflowView workflowViewModel
8080 detail * detailModel // non-nil when detail overlay is open
81+ edit * editModel // non-nil when edit overlay is open
8182 transition * transitionModel // non-nil when transition overlay is open
8283 assign * assignModel // non-nil when assign overlay is open
8384}
@@ -296,7 +297,11 @@ func (m *Model) openDetail() tea.Cmd {
296297 return nil
297298 }
298299
299- m .detail = & detailModel {loading : true }
300+ currentName := ""
301+ if m .currentUser != nil {
302+ currentName = m .currentUser .Name
303+ }
304+ m .detail = & detailModel {loading : true , currentUserName : currentName }
300305 return fetchTaskDetail (m .client , boardSlug , num )
301306}
302307
@@ -467,6 +472,18 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
467472 }
468473 }
469474
475+ // When edit overlay is open, delegate all keys to it.
476+ if m .edit != nil {
477+ if msg .String () == "ctrl+c" {
478+ return m , tea .Quit
479+ }
480+ closed , cmd := m .edit .update (msg , m .client )
481+ if closed {
482+ m .edit = nil
483+ }
484+ return m , cmd
485+ }
486+
470487 // When assign or transition overlays are open, delegate all keys
471488 // to the overlay (except ctrl+c) so the search filter works.
472489 if m .assign != nil {
@@ -500,6 +517,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
500517 case "esc" , "backspace" :
501518 if m .detail != nil {
502519 m .detail = nil
520+ m .edit = nil
503521 return m , nil
504522 }
505523 if m .view == viewBoard || m .view == viewMyTasks {
@@ -529,6 +547,13 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
529547 if (m .view == viewBoard || m .view == viewMyTasks ) && m .assign == nil && m .transition == nil {
530548 return m , m .openAssignFromContext ()
531549 }
550+ case "e" :
551+ if m .detail != nil && m .detail .data != nil && ! m .detail .commenting {
552+ data := m .detail .data
553+ em , cmd := newEdit (m .client , data .task .BoardSlug , data .task , m .currentUser , data .dependencies , data .attachments )
554+ m .edit = em
555+ return m , cmd
556+ }
532557 case "c" :
533558 if m .detail != nil && m .detail .data != nil && ! m .detail .commenting {
534559 m .detail .startComment ()
@@ -598,6 +623,28 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
598623 m .myTasks .rebuild ()
599624 return m , nil
600625
626+ case depAdded , depRemoved , depTasksLoaded , attachAdded , attachRemoved :
627+ if m .edit != nil {
628+ m .edit .update (msg , m .client )
629+ }
630+ return m , nil
631+
632+ case editResult :
633+ if m .edit != nil {
634+ if msg .err != nil {
635+ m .edit .err = msg .err .Error ()
636+ return m , nil
637+ }
638+ m .edit = nil
639+ // Refetch detail to show updated data.
640+ if m .detail != nil {
641+ m .detail .loading = true
642+ m .detail .invalidateContent ()
643+ return m , fetchTaskDetail (m .client , msg .task .BoardSlug , msg .task .Num )
644+ }
645+ }
646+ return m , nil
647+
601648 case boardSelected :
602649 m .activeBoard = & msg .board
603650 m .view = viewBoard
@@ -620,7 +667,17 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
620667 }
621668 return m , nil
622669
623- case actorsLoaded , assignResult :
670+ case actorsLoaded :
671+ if m .assign != nil {
672+ _ , cmd := m .assign .update (msg , m .client )
673+ return m , cmd
674+ }
675+ if m .edit != nil {
676+ m .edit .update (msg , m .client )
677+ }
678+ return m , nil
679+
680+ case assignResult :
624681 if m .assign != nil {
625682 closed , cmd := m .assign .update (msg , m .client )
626683 if closed {
@@ -629,8 +686,8 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
629686 return m , cmd
630687 }
631688 // "Take" action result (no overlay open).
632- if result , ok := msg .( assignResult ); ok && result .err != nil {
633- m .lastError = result .err .Error ()
689+ if msg .err != nil {
690+ m .lastError = msg .err .Error ()
634691 }
635692 return m , nil
636693
@@ -807,7 +864,10 @@ func (m Model) myTasksView() string {
807864 b .WriteString ("\n " ) // no tabs
808865
809866 // Content.
810- if m .detail != nil && m .assign == nil && m .transition == nil {
867+ if m .edit != nil {
868+ m .viewport .SetContent (m .edit .view (m .viewport .Width ))
869+ b .WriteString (m .viewport .View ())
870+ } else if m .detail != nil && m .assign == nil && m .transition == nil {
811871 b .WriteString (m .detail .view (m .viewport .Width , m .viewport .Height ))
812872 } else {
813873 var content string
@@ -866,10 +926,10 @@ func (m Model) boardView() string {
866926 }
867927
868928 // Tab content rendered into the viewport.
869- // The workflow tab has its own viewport for independent scrolling.
870- // Views with their own viewport render directly.
871- // Others go through the shared viewport.
872- if m .detail != nil && m .assign == nil && m .transition == nil {
929+ if m . edit != nil {
930+ m . viewport . SetContent ( m . edit . view ( m . viewport . Width ))
931+ b . WriteString ( m . viewport .View ())
932+ } else if m .detail != nil && m .assign == nil && m .transition == nil {
873933 b .WriteString (m .detail .view (m .viewport .Width , m .viewport .Height ))
874934 } else if m .activeTab == tabWorkflow && m .detail == nil && m .transition == nil && m .assign == nil {
875935 b .WriteString (m .workflowView .view (m .viewport .Width , m .viewport .Height ))
0 commit comments