diff options
author | Michael Muré <batolettre@gmail.com> | 2018-12-23 21:46:47 +0100 |
---|---|---|
committer | Michael Muré <batolettre@gmail.com> | 2018-12-23 21:46:47 +0100 |
commit | 94b28b68e57cf683731467b73b3ba777d1e4f86d (patch) | |
tree | 491a67e1d148fb661c0137b180d8251ea5ee3cc3 | |
parent | 7454b9505ae2d680293d3d00d72df14f36f4e616 (diff) | |
download | git-bug-94b28b68e57cf683731467b73b3ba777d1e4f86d.tar.gz |
termui: display an explicit placeholder for empty messages
-rw-r--r-- | bug/timeline.go | 7 | ||||
-rw-r--r-- | graphql/graph/gen_graph.go | 114 | ||||
-rw-r--r-- | graphql/timeline.graphql | 2 | ||||
-rw-r--r-- | termui/show_bug.go | 39 | ||||
-rw-r--r-- | util/colors/colors.go | 1 |
5 files changed, 137 insertions, 26 deletions
diff --git a/bug/timeline.go b/bug/timeline.go index 2f879209..a84c45e4 100644 --- a/bug/timeline.go +++ b/bug/timeline.go @@ -1,6 +1,8 @@ package bug import ( + "strings" + "github.com/MichaelMure/git-bug/util/git" ) @@ -67,3 +69,8 @@ func (c *CommentTimelineItem) Append(comment Comment) { func (c *CommentTimelineItem) Edited() bool { return len(c.History) > 1 } + +// MessageIsEmpty return true is the message is empty or only made of spaces +func (c *CommentTimelineItem) MessageIsEmpty() bool { + return len(strings.TrimSpace(c.Message)) == 0 +} diff --git a/graphql/graph/gen_graph.go b/graphql/graph/gen_graph.go index 60a9bfa2..e7d09ef4 100644 --- a/graphql/graph/gen_graph.go +++ b/graphql/graph/gen_graph.go @@ -68,14 +68,15 @@ type ComplexityRoot struct { } AddCommentTimelineItem struct { - Hash func(childComplexity int) int - Author func(childComplexity int) int - Message func(childComplexity int) int - Files func(childComplexity int) int - CreatedAt func(childComplexity int) int - LastEdit func(childComplexity int) int - Edited func(childComplexity int) int - History func(childComplexity int) int + Hash func(childComplexity int) int + Author func(childComplexity int) int + Message func(childComplexity int) int + MessageIsEmpty func(childComplexity int) int + Files func(childComplexity int) int + CreatedAt func(childComplexity int) int + LastEdit func(childComplexity int) int + Edited func(childComplexity int) int + History func(childComplexity int) int } Bug struct { @@ -137,14 +138,15 @@ type ComplexityRoot struct { } CreateTimelineItem struct { - Hash func(childComplexity int) int - Author func(childComplexity int) int - Message func(childComplexity int) int - Files func(childComplexity int) int - CreatedAt func(childComplexity int) int - LastEdit func(childComplexity int) int - Edited func(childComplexity int) int - History func(childComplexity int) int + Hash func(childComplexity int) int + Author func(childComplexity int) int + Message func(childComplexity int) int + MessageIsEmpty func(childComplexity int) int + Files func(childComplexity int) int + CreatedAt func(childComplexity int) int + LastEdit func(childComplexity int) int + Edited func(childComplexity int) int + History func(childComplexity int) int } EditCommentOperation struct { @@ -1051,6 +1053,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.AddCommentTimelineItem.Message(childComplexity), true + case "AddCommentTimelineItem.messageIsEmpty": + if e.complexity.AddCommentTimelineItem.MessageIsEmpty == nil { + break + } + + return e.complexity.AddCommentTimelineItem.MessageIsEmpty(childComplexity), true + case "AddCommentTimelineItem.files": if e.complexity.AddCommentTimelineItem.Files == nil { break @@ -1360,6 +1369,13 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in return e.complexity.CreateTimelineItem.Message(childComplexity), true + case "CreateTimelineItem.messageIsEmpty": + if e.complexity.CreateTimelineItem.MessageIsEmpty == nil { + break + } + + return e.complexity.CreateTimelineItem.MessageIsEmpty(childComplexity), true + case "CreateTimelineItem.files": if e.complexity.CreateTimelineItem.Files == nil { break @@ -2183,6 +2199,11 @@ func (ec *executionContext) _AddCommentTimelineItem(ctx context.Context, sel ast if out.Values[i] == graphql.Null { invalid = true } + case "messageIsEmpty": + out.Values[i] = ec._AddCommentTimelineItem_messageIsEmpty(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalid = true + } case "files": out.Values[i] = ec._AddCommentTimelineItem_files(ctx, field, obj) if out.Values[i] == graphql.Null { @@ -2310,6 +2331,33 @@ func (ec *executionContext) _AddCommentTimelineItem_message(ctx context.Context, } // nolint: vetshadow +func (ec *executionContext) _AddCommentTimelineItem_messageIsEmpty(ctx context.Context, field graphql.CollectedField, obj *bug.AddCommentTimelineItem) graphql.Marshaler { + ctx = ec.Tracer.StartFieldExecution(ctx, field) + defer func() { ec.Tracer.EndFieldExecution(ctx) }() + rctx := &graphql.ResolverContext{ + Object: "AddCommentTimelineItem", + Args: nil, + Field: field, + } + ctx = graphql.WithResolverContext(ctx, rctx) + ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.MessageIsEmpty(), nil + }) + if resTmp == nil { + if !ec.HasError(rctx) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + rctx.Result = res + ctx = ec.Tracer.StartFieldChildExecution(ctx) + return graphql.MarshalBoolean(res) +} + +// nolint: vetshadow func (ec *executionContext) _AddCommentTimelineItem_files(ctx context.Context, field graphql.CollectedField, obj *bug.AddCommentTimelineItem) graphql.Marshaler { ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { ec.Tracer.EndFieldExecution(ctx) }() @@ -4022,6 +4070,11 @@ func (ec *executionContext) _CreateTimelineItem(ctx context.Context, sel ast.Sel if out.Values[i] == graphql.Null { invalid = true } + case "messageIsEmpty": + out.Values[i] = ec._CreateTimelineItem_messageIsEmpty(ctx, field, obj) + if out.Values[i] == graphql.Null { + invalid = true + } case "files": out.Values[i] = ec._CreateTimelineItem_files(ctx, field, obj) if out.Values[i] == graphql.Null { @@ -4149,6 +4202,33 @@ func (ec *executionContext) _CreateTimelineItem_message(ctx context.Context, fie } // nolint: vetshadow +func (ec *executionContext) _CreateTimelineItem_messageIsEmpty(ctx context.Context, field graphql.CollectedField, obj *bug.CreateTimelineItem) graphql.Marshaler { + ctx = ec.Tracer.StartFieldExecution(ctx, field) + defer func() { ec.Tracer.EndFieldExecution(ctx) }() + rctx := &graphql.ResolverContext{ + Object: "CreateTimelineItem", + Args: nil, + Field: field, + } + ctx = graphql.WithResolverContext(ctx, rctx) + ctx = ec.Tracer.StartFieldResolverExecution(ctx, rctx) + resTmp := ec.FieldMiddleware(ctx, obj, func(rctx context.Context) (interface{}, error) { + ctx = rctx // use context from middleware stack in children + return obj.MessageIsEmpty(), nil + }) + if resTmp == nil { + if !ec.HasError(rctx) { + ec.Errorf(ctx, "must not be null") + } + return graphql.Null + } + res := resTmp.(bool) + rctx.Result = res + ctx = ec.Tracer.StartFieldChildExecution(ctx) + return graphql.MarshalBoolean(res) +} + +// nolint: vetshadow func (ec *executionContext) _CreateTimelineItem_files(ctx context.Context, field graphql.CollectedField, obj *bug.CreateTimelineItem) graphql.Marshaler { ctx = ec.Tracer.StartFieldExecution(ctx, field) defer func() { ec.Tracer.EndFieldExecution(ctx) }() @@ -9079,6 +9159,7 @@ type CreateTimelineItem implements TimelineItem { hash: Hash! author: Person! message: String! + messageIsEmpty: Boolean! files: [Hash!]! createdAt: Time! lastEdit: Time! @@ -9092,6 +9173,7 @@ type AddCommentTimelineItem implements TimelineItem { hash: Hash! author: Person! message: String! + messageIsEmpty: Boolean! files: [Hash!]! createdAt: Time! lastEdit: Time! diff --git a/graphql/timeline.graphql b/graphql/timeline.graphql index 7cce87a7..75f72305 100644 --- a/graphql/timeline.graphql +++ b/graphql/timeline.graphql @@ -34,6 +34,7 @@ type CreateTimelineItem implements TimelineItem { hash: Hash! author: Person! message: String! + messageIsEmpty: Boolean! files: [Hash!]! createdAt: Time! lastEdit: Time! @@ -47,6 +48,7 @@ type AddCommentTimelineItem implements TimelineItem { hash: Hash! author: Person! message: String! + messageIsEmpty: Boolean! files: [Hash!]! createdAt: Time! lastEdit: Time! diff --git a/termui/show_bug.go b/termui/show_bug.go index cb2fe04c..a1f4b3fe 100644 --- a/termui/show_bug.go +++ b/termui/show_bug.go @@ -95,7 +95,7 @@ func (sb *showBug) layout(g *gocui.Gui) error { } v.Clear() - fmt.Fprintf(v, "[q] Save and return [←↓↑→,hjkl] Navigation [o] Toggle open/close [e] Edit [c] Comment [t] Change title") + _, _ = fmt.Fprintf(v, "[q] Save and return [←↓↑→,hjkl] Navigation [o] Toggle open/close [e] Edit [c] Comment [t] Change title") _, err = g.SetViewOnTop(showBugInstructionView) if err != nil { @@ -228,7 +228,7 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error { return err } - fmt.Fprint(v, bugHeader) + _, _ = fmt.Fprint(v, bugHeader) y0 += lines + 1 for _, op := range snap.Timeline { @@ -241,13 +241,21 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error { case *bug.CreateTimelineItem: create := op.(*bug.CreateTimelineItem) - content, lines := text.WrapLeftPadded(create.Message, maxX-1, 4) + + var content string + var lines int + + if create.MessageIsEmpty() { + content, lines = text.WrapLeftPadded(emptyMessagePlaceholder(), maxX-1, 4) + } else { + content, lines = text.WrapLeftPadded(create.Message, maxX-1, 4) + } v, err := sb.createOpView(g, viewName, x0, y0, maxX+1, lines, true) if err != nil { return err } - fmt.Fprint(v, content) + _, _ = fmt.Fprint(v, content) y0 += lines + 2 case *bug.AddCommentTimelineItem: @@ -258,7 +266,13 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error { edited = " (edited)" } - message, _ := text.WrapLeftPadded(comment.Message, maxX-1, 4) + var message string + if comment.MessageIsEmpty() { + message, _ = text.WrapLeftPadded(emptyMessagePlaceholder(), maxX-1, 4) + } else { + message, _ = text.WrapLeftPadded(comment.Message, maxX-1, 4) + } + content := fmt.Sprintf("%s commented on %s%s\n\n%s", colors.Magenta(comment.Author.DisplayName()), comment.CreatedAt.Time().Format(timeLayout), @@ -271,7 +285,7 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error { if err != nil { return err } - fmt.Fprint(v, content) + _, _ = fmt.Fprint(v, content) y0 += lines + 2 case *bug.SetTitleTimelineItem: @@ -288,7 +302,7 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error { if err != nil { return err } - fmt.Fprint(v, content) + _, _ = fmt.Fprint(v, content) y0 += lines + 2 case *bug.SetStatusTimelineItem: @@ -305,7 +319,7 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error { if err != nil { return err } - fmt.Fprint(v, content) + _, _ = fmt.Fprint(v, content) y0 += lines + 2 case *bug.LabelChangeTimelineItem: @@ -354,7 +368,7 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error { if err != nil { return err } - fmt.Fprint(v, content) + _, _ = fmt.Fprint(v, content) y0 += lines + 2 } } @@ -362,6 +376,11 @@ func (sb *showBug) renderMain(g *gocui.Gui, mainView *gocui.View) error { return nil } +// emptyMessagePlaceholder return a formatted placeholder for an empty message +func emptyMessagePlaceholder() string { + return colors.GreyBold("No description provided.") +} + func (sb *showBug) createOpView(g *gocui.Gui, name string, x0 int, y0 int, maxX int, height int, selectable bool) (*gocui.View, error) { v, err := g.SetView(name, x0, y0, maxX, y0+height+1) @@ -423,7 +442,7 @@ func (sb *showBug) renderSidebar(g *gocui.Gui, sideView *gocui.View) error { return err } - fmt.Fprint(v, content) + _, _ = fmt.Fprint(v, content) return nil } diff --git a/util/colors/colors.go b/util/colors/colors.go index c57e9019..f8c6d188 100644 --- a/util/colors/colors.go +++ b/util/colors/colors.go @@ -13,6 +13,7 @@ var ( YellowBg = color.New(color.BgYellow, color.FgBlack).SprintFunc() Green = color.New(color.FgGreen).SprintFunc() GreenBg = color.New(color.BgGreen, color.FgBlack).SprintFunc() + GreyBold = color.New(color.BgBlack, color.Bold).SprintfFunc() Red = color.New(color.FgRed).SprintFunc() Cyan = color.New(color.FgCyan).SprintFunc() CyanBg = color.New(color.BgCyan, color.FgBlack).SprintFunc() |