aboutsummaryrefslogtreecommitdiff
path: root/widgets
AgeCommit message (Collapse)Author
2019-05-26Implement :edit in compose screenDrew DeVault
2019-05-26msgviewer: copy stderr into pagerDrew DeVault
This prevents a broken filter config from being a silent error
2019-05-25Fix special characters in address.PersonalNameDrew DeVault
2019-05-22Show account wizard if no accounts configuredDrew DeVault
2019-05-22Implement opening tutorial after account wizardDrew DeVault
2019-05-22Write new accounts to config and open tabDrew DeVault
2019-05-22Fix always showing last account tabDrew DeVault
2019-05-21Remove excess padding from incoming config pageDrew DeVault
2019-05-21New account wizard, part oneDrew DeVault
2019-05-20Load IMAP worker for imap+insecureDrew DeVault
2019-05-20Show unsupported mimetype message in redDrew DeVault
2019-05-20Show attachment names in multipart viewDrew DeVault
2019-05-20Implement :next-part, :prev-partDrew DeVault
2019-05-20Flesh out multipart switcherDrew DeVault
2019-05-20Refactor message part into dedicated widgetDrew DeVault
2019-05-20Verify TLS certificatesDrew DeVault
I was partway done implementing a UI for users to approve untrusted certs with, but let's just make them configure their servers right instead.
2019-05-19Advance cursor after :delete and :moveDrew DeVault
So that you can repeat the action on the next message if appropriate
2019-05-19Reset message list cursor when switching storesDrew DeVault
2019-05-19Advance message list cursor when messages arriveDrew DeVault
2019-05-19Update internal state and draw from the same goroutineSimon Ser
This commit introduces a new Aerc.Tick function that should be called to refresh the internal state. This in turn makes each AccountView process worker events. The UI goroutine repeatedly refreshes the internal state before drawing a new frame. The reason for this is that many worker messages may need to be processed for a single frame, and drawing the UI is far slower than refreshing the internal state. This has been confirmed in my testing (calling Aerc.Tick only once per frame results in a slower display). Many synchronization code has been removed. We can now write widgets without having to care so much about races. The remaining sync users are: - widgets/spinner: the spinner value is updated from inside an internal goroutine - lib/ui/invalidatable: Invalidate may be called from any goroutine - lib/ui/grid: same - lib/ui/ui: an internal goroutine needs read access to UI.exit - worker/types/worker: Worker.callbacks is used for both worker and UI callbacks The exact goroutine requirements for Drawable have been documented.
2019-05-19widgets/terminal: fix damage race conditionSimon Ser
Terminal.damage is accessed when drawing and when invalidating the widget. For this reason we need to protect it with a mutex. This seems to fix various damage issues I've been experiencing (where some regions of the terminal weren't correctly repainted). Race detector trace: Read at 0x00c0000c6670 by main goroutine: git.sr.ht/~sircmpwn/aerc/widgets.(*Terminal).Draw() /home/simon/src/aerc/widgets/terminal.go:292 +0x191 git.sr.ht/~sircmpwn/aerc/lib/ui.(*Grid).Draw() /home/simon/src/aerc/lib/ui/grid.go:117 +0x575 git.sr.ht/~sircmpwn/aerc/lib/ui.(*Grid).Draw() /home/simon/src/aerc/lib/ui/grid.go:117 +0x575 git.sr.ht/~sircmpwn/aerc/widgets.(*MessageViewer).Draw() /home/simon/src/aerc/widgets/msgviewer.go:231 +0x253 git.sr.ht/~sircmpwn/aerc/lib/ui.(*TabContent).Draw() /home/simon/src/aerc/lib/ui/tab.go:124 +0x12e git.sr.ht/~sircmpwn/aerc/lib/ui.(*Grid).Draw() /home/simon/src/aerc/lib/ui/grid.go:117 +0x575 git.sr.ht/~sircmpwn/aerc/widgets.(*Aerc).Draw() /home/simon/src/aerc/widgets/aerc.go:95 +0x5a git.sr.ht/~sircmpwn/aerc/lib/ui.(*UI).Tick() /home/simon/src/aerc/lib/ui/ui.go:93 +0x1dd main.main() /home/simon/src/aerc/aerc.go:105 +0x539 Previous write at 0x00c0000c6670 by goroutine 37: git.sr.ht/~sircmpwn/aerc/widgets.(*Terminal).onDamage-fm() /home/simon/src/aerc/widgets/terminal.go:429 +0x131 git.sr.ht/~sircmpwn/go-libvterm._go_handle_damage() /home/simon/go/pkg/mod/git.sr.ht/~sircmpwn/go-libvterm@v0.0.0-20190421201021-3184f6f13687/vterm.go:481 +0xf9 git.sr.ht/~sircmpwn/go-libvterm._cgoexpwrap_5e22200b58b7__go_handle_damage() _cgo_gotypes.go:731 +0x58 runtime.call32() /usr/lib/go/src/runtime/asm_amd64.s:519 +0x3a git.sr.ht/~sircmpwn/go-libvterm.(*VTerm).Write.func1() /home/simon/go/pkg/mod/git.sr.ht/~sircmpwn/go-libvterm@v0.0.0-20190421201021-3184f6f13687/vterm.go:329 +0x9d git.sr.ht/~sircmpwn/go-libvterm.(*VTerm).Write() /home/simon/go/pkg/mod/git.sr.ht/~sircmpwn/go-libvterm@v0.0.0-20190421201021-3184f6f13687/vterm.go:329 +0x7f git.sr.ht/~sircmpwn/aerc/widgets.NewTerminal.func1() /home/simon/src/aerc/widgets/terminal.go:131 +0x18c Goroutine 37 (running) created at: git.sr.ht/~sircmpwn/aerc/widgets.NewTerminal() /home/simon/src/aerc/widgets/terminal.go:121 +0x23f git.sr.ht/~sircmpwn/aerc/widgets.NewMessageViewer() /home/simon/src/aerc/widgets/msgviewer.go:147 +0xfbe git.sr.ht/~sircmpwn/aerc/commands/account.ViewMessage() /home/simon/src/aerc/commands/account/view-message.go:26 +0x4a4 git.sr.ht/~sircmpwn/aerc/commands.(*Commands).ExecuteCommand() /home/simon/src/aerc/commands/commands.go:47 +0x1f0 main.main.func1() /home/simon/src/aerc/aerc.go:76 +0x205 git.sr.ht/~sircmpwn/aerc/widgets.(*Aerc).BeginExCommand.func1() /home/simon/src/aerc/widgets/aerc.go:262 +0x89 git.sr.ht/~sircmpwn/aerc/widgets.(*ExLine).Event() /home/simon/src/aerc/widgets/exline.go:47 +0x222 git.sr.ht/~sircmpwn/aerc/widgets.(*Aerc).Event() /home/simon/src/aerc/widgets/aerc.go:133 +0x83c git.sr.ht/~sircmpwn/aerc/widgets.(*Aerc).simulate() /home/simon/src/aerc/widgets/aerc.go:126 +0x12a git.sr.ht/~sircmpwn/aerc/widgets.(*Aerc).Event() /home/simon/src/aerc/widgets/aerc.go:148 +0x766 git.sr.ht/~sircmpwn/aerc/lib/ui.(*UI).Tick() /home/simon/src/aerc/lib/ui/ui.go:86 +0x11b main.main() /home/simon/src/aerc/aerc.go:105 +0x539
2019-05-17s/aerc2/aerc/gDrew DeVault
2019-05-17Remove unimplemented color configurationDrew DeVault
Will probably end up doing this differently anyway
2019-05-17Implement ui.empty-message config optionDrew DeVault
Also removes some options that aren't going to be supported any time soon.
2019-05-17Fix date header on outgoing emailsDrew DeVault
2019-05-16Decode email when reading it for quotingDrew DeVault
2019-05-16Implement :reply -q and :reply -aDrew DeVault
2019-05-16Implement (basic form) of :replyDrew DeVault
2019-05-16Let caller pass in custom headers to composeDrew DeVault
2019-05-15Copy sent emails to the Sent folderDrew DeVault
Or rather, to a user-specified folder
2019-05-14Force INBOX to be included in dirlistDrew DeVault
2019-05-14Implement :copy (aka :cp)Drew DeVault
2019-05-14Update tab name as subject changesDrew DeVault
Also moves truncation to the tab widget
2019-05-14Add $EDITOR, internal config for composeDrew DeVault
2019-05-14Add distinct keybindings for each compose viewDrew DeVault
2019-05-14Implement sending emails /o/Drew DeVault
2019-05-14Add :send-message, prepares & writes email to /tmpDrew DeVault
2019-05-13Handle external message deletionsDrew DeVault
2019-05-13Handle incoming emails gracefullyDrew DeVault
2019-05-13Spec out review message screenDrew DeVault
2019-05-13Populate "From" header from config for new emailsDrew DeVault
2019-05-12Implement :{next,prev}-field in compose viewDrew DeVault
2019-05-12Expand compose focus handling a bitDrew DeVault
2019-05-12Add initial compose widgetDrew DeVault
2019-05-11"Press any key to close" for completed processesDrew DeVault
2019-05-11Refactor ctx stashing out of exlineDrew DeVault
2019-05-11Split ex line text handling into dedicated widgetDrew DeVault
2019-04-29lib/msgstore: protect with a mutexSimon Ser
MessageStore has a lot of exported fields that can be read from the outside. Each read must be protected, because a call from Update could happen at any time.
2019-04-29widgets/msglist: fix MessageList.store raceSimon Ser
This field could be written to in the middle of a Draw call, which reads it multiple times. Use an atomic variable instead.
2019-04-27lib/ui: introduce InvalidatableSimon Ser
Many Drawable implementations have their own Invalidate and OnInvalidate functions, with an unexported onInvalidate field. However OnInvalidate and Invalidate are usually not called in the same goroutine. This results in a race on this field, e.g.: Read at 0x00c000094748 by goroutine 7: git.sr.ht/~sircmpwn/aerc2/widgets.NewDirectoryList.func1() /home/simon/src/aerc2/widgets/dirlist.go:85 +0x56 git.sr.ht/~sircmpwn/aerc2/widgets.(*Spinner).Start.func1() /home/simon/src/aerc2/widgets/spinner.go:93 +0x1bb Previous write at 0x00c000094748 by main goroutine: [failed to restore the stack] Goroutine 7 (running) created at: git.sr.ht/~sircmpwn/aerc2/widgets.(*Spinner).Start() /home/simon/src/aerc2/widgets/spinner.go:46 +0x8f git.sr.ht/~sircmpwn/aerc2/widgets.NewDirectoryList() /home/simon/src/aerc2/widgets/dirlist.go:37 +0x286 git.sr.ht/~sircmpwn/aerc2/widgets.NewAccountView() /home/simon/src/aerc2/widgets/account.go:50 +0x5ca git.sr.ht/~sircmpwn/aerc2/widgets.NewAerc() /home/simon/src/aerc2/widgets/aerc.go:60 +0x800 main.main() /home/simon/src/aerc2/aerc.go:65 +0x33e To fix this, introduce a new type, Invalidatable, which protects the field. Unfortunately the Drawable must be passed to the callback function in Invalidate, so we still need to re-implement this in each Invalidatable user.