From ae13a3394d3a1f1a78e02cd2dc7bcdaa1b51943e Mon Sep 17 00:00:00 2001 From: Chris Cummer Date: Sun, 23 Jun 2019 14:49:06 -0700 Subject: [PATCH 1/4] WIP Transmission --- modules/hibp/settings.go | 1 - modules/transmission/settings.go | 38 ++++++++++++++++++++++++++++++++ modules/transmission/widget.go | 1 + 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 modules/transmission/settings.go create mode 100644 modules/transmission/widget.go diff --git a/modules/hibp/settings.go b/modules/hibp/settings.go index a387443e..b9b7c269 100644 --- a/modules/hibp/settings.go +++ b/modules/hibp/settings.go @@ -29,7 +29,6 @@ type Settings struct { // NewSettingsFromYAML creates a new settings instance from a YAML config block func NewSettingsFromYAML(name string, ymlConfig *config.Config, globalConfig *config.Config) *Settings { - settings := Settings{ common: cfg.NewCommonSettingsFromModule(name, defaultTitle, ymlConfig, globalConfig), diff --git a/modules/transmission/settings.go b/modules/transmission/settings.go new file mode 100644 index 00000000..3c8072a5 --- /dev/null +++ b/modules/transmission/settings.go @@ -0,0 +1,38 @@ +package transmission + +import ( + "github.com/olebedev/config" + "github.com/wtfutil/wtf/cfg" +) + +// Settings defines the configuration properties for this module +type Settings struct { + common *cfg.Common + + host string + https bool + password string + port int + url string + username string +} + +const ( + defaultTitle = "Transmission" +) + +// NewSettingsFromYAML creates a new settings instance from a YAML config block +func NewSettingsFromYAML(name string, ymlConfig *config.Config, globalConfig *config.Config) *Settings { + settings := Settings{ + common: cfg.NewCommonSettingsFromModule(name, defaultTitle, ymlConfig, globalConfig), + + host: ymlConfig.UString("host"), + https: ymlConfig.UBool("https", false), + password: ymlConfig.UString("password"), + port: ymlConfig.UInt("port", 9091), + url: ymlConfig.UString("url", "/transmission/"), + username: ymlConfig.UString("username", ""), + } + + return &settings +} diff --git a/modules/transmission/widget.go b/modules/transmission/widget.go new file mode 100644 index 00000000..dc9c0ba8 --- /dev/null +++ b/modules/transmission/widget.go @@ -0,0 +1 @@ +package transmission From 9244d60abe0c6ea509735936da71af3df73959d5 Mon Sep 17 00:00:00 2001 From: Chris Cummer Date: Tue, 25 Jun 2019 23:04:12 -0700 Subject: [PATCH 2/4] Add a rudimentary Transmission module (https://transmissionbt.com) --- go.mod | 3 + go.sum | 6 ++ maker/widget_maker.go | 4 + modules/hibp/widget.go | 6 +- modules/transmission/keyboard.go | 10 +++ modules/transmission/widget.go | 123 +++++++++++++++++++++++++++++++ 6 files changed, 149 insertions(+), 3 deletions(-) create mode 100644 modules/transmission/keyboard.go diff --git a/go.mod b/go.mod index 9ae21c1f..7fb0caf2 100644 --- a/go.mod +++ b/go.mod @@ -39,7 +39,10 @@ require ( github.com/google/pprof v0.0.0-20190515194954-54271f7e092f // indirect github.com/gorilla/mux v1.7.1 // indirect github.com/grpc-ecosystem/grpc-gateway v1.9.0 // indirect + github.com/hashicorp/go-cleanhttp v0.5.1 // indirect github.com/hashicorp/golang-lru v0.5.1 // indirect + github.com/hekmon/cunits v2.0.1+incompatible // indirect + github.com/hekmon/transmissionrpc v0.0.0-20190525133028-1d589625bacd github.com/jessevdk/go-flags v1.4.0 github.com/kisielk/errcheck v1.2.0 // indirect github.com/kisielk/gotool v1.0.0 // indirect diff --git a/go.sum b/go.sum index 35f0a27a..6d2cd83e 100644 --- a/go.sum +++ b/go.sum @@ -122,9 +122,15 @@ github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2z github.com/gorilla/mux v1.7.1/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hekmon/cunits v2.0.1+incompatible h1:yy/Wq5YvNtrweqfeRjvrvMdBMH6axBrlL8t7arLlm5A= +github.com/hekmon/cunits v2.0.1+incompatible/go.mod h1:0QdfIGGkucx1VgStMNiHOYn84t/Ru65b+D3z1QszVPc= +github.com/hekmon/transmissionrpc v0.0.0-20190525133028-1d589625bacd h1:bZZYKxyrUV8EsKB5AjsPsJiWE7n0FDURijlSzYZVqAM= +github.com/hekmon/transmissionrpc v0.0.0-20190525133028-1d589625bacd/go.mod h1:b1R6hlzo+gEUNWGh53mw9mPWyYyODdZu/qlVqT+W+PU= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= diff --git a/maker/widget_maker.go b/maker/widget_maker.go index d02a970a..4d3a2791 100644 --- a/maker/widget_maker.go +++ b/maker/widget_maker.go @@ -41,6 +41,7 @@ import ( "github.com/wtfutil/wtf/modules/textfile" "github.com/wtfutil/wtf/modules/todo" "github.com/wtfutil/wtf/modules/todoist" + "github.com/wtfutil/wtf/modules/transmission" "github.com/wtfutil/wtf/modules/travisci" "github.com/wtfutil/wtf/modules/trello" "github.com/wtfutil/wtf/modules/twitter" @@ -181,6 +182,9 @@ func MakeWidget( case "todoist": settings := todoist.NewSettingsFromYAML(widgetName, moduleConfig, globalConfig) widget = todoist.NewWidget(app, pages, settings) + case "transmission": + settings := transmission.NewSettingsFromYAML(widgetName, moduleConfig, globalConfig) + widget = transmission.NewWidget(app, pages, settings) case "travisci": settings := travisci.NewSettingsFromYAML(widgetName, moduleConfig, globalConfig) widget = travisci.NewWidget(app, pages, settings) diff --git a/modules/hibp/widget.go b/modules/hibp/widget.go index c623ace0..c33a390c 100644 --- a/modules/hibp/widget.go +++ b/modules/hibp/widget.go @@ -17,18 +17,18 @@ type Widget struct { // NewWidget creates a new instance of a widget func NewWidget(app *tview.Application, settings *Settings) *Widget { - widget := Widget{ + widget := &Widget{ TextWidget: wtf.NewTextWidget(app, settings.common, false), settings: settings, } - return &widget + return widget } /* -------------------- Exported Functions -------------------- */ -// Fetch rettrieves HIBP data from the HIBP API +// Fetch retrieves HIBP data from the HIBP API func (widget *Widget) Fetch(accounts []string) ([]*Status, error) { data := []*Status{} diff --git a/modules/transmission/keyboard.go b/modules/transmission/keyboard.go new file mode 100644 index 00000000..d6009aab --- /dev/null +++ b/modules/transmission/keyboard.go @@ -0,0 +1,10 @@ +package transmission + +// import "github.com/gdamore/tcell" + +func (widget *Widget) initializeKeyboardControls() { + widget.SetKeyboardChar("/", widget.ShowHelp, "Show/hide this help prompt") + widget.SetKeyboardChar("m", nil, "Add new magnet torrent") + widget.SetKeyboardChar("p", nil, "Pause torrent") + widget.SetKeyboardChar("r", nil, "Remove torrent from list") +} diff --git a/modules/transmission/widget.go b/modules/transmission/widget.go index dc9c0ba8..16e2732b 100644 --- a/modules/transmission/widget.go +++ b/modules/transmission/widget.go @@ -1 +1,124 @@ package transmission + +import ( + "fmt" + "strings" + + "github.com/hekmon/transmissionrpc" + "github.com/rivo/tview" + "github.com/wtfutil/wtf/wtf" +) + +// Widget is the container for transmission data +type Widget struct { + wtf.KeyboardWidget + wtf.TextWidget + + settings *Settings +} + +// NewWidget creates a new instance of a widget +func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { + widget := &Widget{ + KeyboardWidget: wtf.NewKeyboardWidget(app, pages, settings.common), + TextWidget: wtf.NewTextWidget(app, settings.common, true), + + settings: settings, + } + + widget.initializeKeyboardControls() + widget.View.SetInputCapture(widget.InputCapture) + widget.KeyboardWidget.SetView(widget.View) + + return widget +} + +/* -------------------- Exported Functions -------------------- */ + +// Fetch retrieves torrent data from the Transmission daemon +func (widget *Widget) Fetch() ([]*transmissionrpc.Torrent, error) { + transmissionbt, err := transmissionrpc.New(widget.settings.host, widget.settings.username, widget.settings.password, nil) + if err != nil { + return nil, err + } + + torrents, err := transmissionbt.TorrentGetAll() + if err != nil { + return nil, err + } + + return torrents, nil +} + +// Refresh updates the data for this widget and displays it onscreen +func (widget *Widget) Refresh() { + torrents, err := widget.Fetch() + + var content string + if err != nil { + content = err.Error() + } else { + content = widget.contentFrom(torrents) + } + + widget.Redraw(widget.CommonSettings.Title, content, false) +} + +// HelpText returns the help text for this widget +func (widget *Widget) HelpText() string { + return widget.KeyboardWidget.HelpText() +} + +/* -------------------- Unexported Functions -------------------- */ + +func (widget *Widget) contentFrom(data []*transmissionrpc.Torrent) string { + str := "" + + for _, torrent := range data { + str += fmt.Sprintf( + " %s %s%s[white]\n", + widget.torrentPercentDone(torrent), + widget.torrentState(torrent), + widget.prettyTorrentName(*torrent.Name), + ) + } + + return str +} + +func (widget *Widget) prettyTorrentName(name string) string { + str := strings.Replace(name, "[", "(", -1) + str = strings.Replace(str, "]", ")", -1) + + return str +} + +func (widget *Widget) torrentPercentDone(torrent *transmissionrpc.Torrent) string { + pctDone := *torrent.PercentDone + str := fmt.Sprintf("%3d", int(pctDone*100)) + + if pctDone == 0.0 { + str = "[gray::b]" + str + } else if pctDone == 1.0 { + str = "[green::b]" + str + } else { + str = "[lightblue::b]" + str + } + + return str + "[white]" +} + +func (widget *Widget) torrentState(torrent *transmissionrpc.Torrent) string { + str := "" + + switch *torrent.Status { + case transmissionrpc.TorrentStatusStopped: + str += "[gray]" + case transmissionrpc.TorrentStatusDownload: + str += "[lightblue]" + case transmissionrpc.TorrentStatusSeed: + str += "[green]" + } + + return str +} From 5dbce09e4ffeac8cf87b79139da0202fae29ff22 Mon Sep 17 00:00:00 2001 From: Chris Cummer Date: Wed, 26 Jun 2019 06:57:32 -0700 Subject: [PATCH 3/4] Make Transmission widget scrollable --- modules/todoist/display.go | 8 ++-- modules/transmission/keyboard.go | 11 +++++- modules/transmission/widget.go | 65 ++++++++++++++++++++++++-------- wtf/scrollable.go | 2 +- 4 files changed, 64 insertions(+), 22 deletions(-) diff --git a/modules/todoist/display.go b/modules/todoist/display.go index e88fcaab..1c24df64 100644 --- a/modules/todoist/display.go +++ b/modules/todoist/display.go @@ -17,15 +17,15 @@ func (widget *Widget) display() { title := fmt.Sprintf("[green]%s[white]", proj.Project.Name) str := "" - for index, item := range proj.tasks { + for idx, item := range proj.tasks { row := fmt.Sprintf( `[%s]| | %s[%s]`, - widget.RowColor(index), + widget.RowColor(idx), tview.Escape(item.Content), - widget.RowColor(index), + widget.RowColor(idx), ) - str += wtf.HighlightableHelper(widget.View, row, index, len(item.Content)) + str += wtf.HighlightableHelper(widget.View, row, idx, len(item.Content)) } widget.ScrollableWidget.Redraw(title, str, false) diff --git a/modules/transmission/keyboard.go b/modules/transmission/keyboard.go index d6009aab..27a69804 100644 --- a/modules/transmission/keyboard.go +++ b/modules/transmission/keyboard.go @@ -1,10 +1,17 @@ package transmission -// import "github.com/gdamore/tcell" +import "github.com/gdamore/tcell" func (widget *Widget) initializeKeyboardControls() { widget.SetKeyboardChar("/", widget.ShowHelp, "Show/hide this help prompt") - widget.SetKeyboardChar("m", nil, "Add new magnet torrent") + widget.SetKeyboardChar("j", widget.Prev, "Select previous item") + widget.SetKeyboardChar("k", widget.Next, "Select next item") + widget.SetKeyboardChar("n", nil, "Add new magnet URL") widget.SetKeyboardChar("p", nil, "Pause torrent") widget.SetKeyboardChar("r", nil, "Remove torrent from list") + widget.SetKeyboardChar("u", widget.Unselect, "Clear selection") + + widget.SetKeyboardKey(tcell.KeyDown, widget.Next, "Select next item") + widget.SetKeyboardKey(tcell.KeyEsc, widget.Unselect, "Clear selection") + widget.SetKeyboardKey(tcell.KeyUp, widget.Prev, "Select previous item") } diff --git a/modules/transmission/widget.go b/modules/transmission/widget.go index 16e2732b..53891683 100644 --- a/modules/transmission/widget.go +++ b/modules/transmission/widget.go @@ -12,25 +12,28 @@ import ( // Widget is the container for transmission data type Widget struct { wtf.KeyboardWidget - wtf.TextWidget + wtf.ScrollableWidget settings *Settings + torrents []*transmissionrpc.Torrent } // NewWidget creates a new instance of a widget func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) *Widget { - widget := &Widget{ - KeyboardWidget: wtf.NewKeyboardWidget(app, pages, settings.common), - TextWidget: wtf.NewTextWidget(app, settings.common, true), + widget := Widget{ + KeyboardWidget: wtf.NewKeyboardWidget(app, pages, settings.common), + ScrollableWidget: wtf.NewScrollableWidget(app, settings.common, true), settings: settings, } + widget.SetRenderFunction(widget.display) widget.initializeKeyboardControls() widget.View.SetInputCapture(widget.InputCapture) + widget.KeyboardWidget.SetView(widget.View) - return widget + return &widget } /* -------------------- Exported Functions -------------------- */ @@ -53,15 +56,16 @@ func (widget *Widget) Fetch() ([]*transmissionrpc.Torrent, error) { // Refresh updates the data for this widget and displays it onscreen func (widget *Widget) Refresh() { torrents, err := widget.Fetch() - - var content string if err != nil { - content = err.Error() - } else { - content = widget.contentFrom(torrents) + widget.SetItemCount(0) + widget.ScrollableWidget.Redraw(widget.CommonSettings.Title, err.Error(), false) + return } - widget.Redraw(widget.CommonSettings.Title, content, false) + widget.torrents = torrents + widget.SetItemCount(len(torrents)) + + widget.display() } // HelpText returns the help text for this widget @@ -69,18 +73,49 @@ func (widget *Widget) HelpText() string { return widget.KeyboardWidget.HelpText() } +// Next selects the next item in the list +func (widget *Widget) Next() { + widget.ScrollableWidget.Next() +} + +// Prev selects the previous item in the list +func (widget *Widget) Prev() { + widget.ScrollableWidget.Prev() +} + +// Unselect clears the selection of list items +func (widget *Widget) Unselect() { + widget.ScrollableWidget.Unselect() + widget.RenderFunction() +} + /* -------------------- Unexported Functions -------------------- */ +func (widget *Widget) display() { + if len(widget.torrents) == 0 { + widget.ScrollableWidget.Redraw(widget.CommonSettings.Title, "no torrents", false) + return + } + + content := widget.contentFrom(widget.torrents) + widget.ScrollableWidget.Redraw(widget.CommonSettings.Title, content, false) +} + func (widget *Widget) contentFrom(data []*transmissionrpc.Torrent) string { str := "" - for _, torrent := range data { - str += fmt.Sprintf( - " %s %s%s[white]\n", + for idx, torrent := range data { + torrName := *torrent.Name + + row := fmt.Sprintf( + "[%s] %s %s%s[white]", + widget.RowColor(idx), widget.torrentPercentDone(torrent), widget.torrentState(torrent), - widget.prettyTorrentName(*torrent.Name), + tview.Escape(widget.prettyTorrentName(torrName)), ) + + str += wtf.HighlightableHelper(widget.View, row, idx, len(torrName)) } return str diff --git a/wtf/scrollable.go b/wtf/scrollable.go index 496151ed..78385e2a 100644 --- a/wtf/scrollable.go +++ b/wtf/scrollable.go @@ -24,6 +24,7 @@ func NewScrollableWidget(app *tview.Application, commonSettings *cfg.Common, foc widget.Unselect() widget.View.SetScrollable(true) widget.View.SetRegions(true) + return widget } @@ -71,7 +72,6 @@ func (widget *ScrollableWidget) Unselect() { } func (widget *ScrollableWidget) Redraw(title, content string, wrap bool) { - widget.TextWidget.Redraw(title, content, wrap) widget.app.QueueUpdateDraw(func() { widget.View.Highlight(strconv.Itoa(widget.Selected)).ScrollToHighlight() From 3a65dad74329d112242172c1cb8da4b0ddbdea31 Mon Sep 17 00:00:00 2001 From: Chris Cummer Date: Wed, 26 Jun 2019 09:48:49 -0700 Subject: [PATCH 4/4] Add pause/unpause and delete functionality to Transmisson widget --- modules/transmission/display.go | 77 +++++++++++++++++++++++ modules/transmission/keyboard.go | 5 +- modules/transmission/widget.go | 105 ++++++++++++++----------------- 3 files changed, 127 insertions(+), 60 deletions(-) create mode 100644 modules/transmission/display.go diff --git a/modules/transmission/display.go b/modules/transmission/display.go new file mode 100644 index 00000000..32fb263a --- /dev/null +++ b/modules/transmission/display.go @@ -0,0 +1,77 @@ +package transmission + +import ( + "fmt" + "strings" + + "github.com/hekmon/transmissionrpc" + "github.com/rivo/tview" + "github.com/wtfutil/wtf/wtf" +) + +func (widget *Widget) contentFrom(data []*transmissionrpc.Torrent) string { + str := "" + + for idx, torrent := range data { + torrName := *torrent.Name + + row := fmt.Sprintf( + "[%s] %s %s%s[white]", + widget.RowColor(idx), + widget.torrentPercentDone(torrent), + widget.torrentState(torrent), + tview.Escape(widget.prettyTorrentName(torrName)), + ) + + str += wtf.HighlightableHelper(widget.View, row, idx, len(torrName)) + } + + return str +} + +func (widget *Widget) display() { + if len(widget.torrents) == 0 { + widget.ScrollableWidget.Redraw(widget.CommonSettings.Title, "no torrents", false) + return + } + + content := widget.contentFrom(widget.torrents) + widget.ScrollableWidget.Redraw(widget.CommonSettings.Title, content, false) +} + +func (widget *Widget) prettyTorrentName(name string) string { + str := strings.Replace(name, "[", "(", -1) + str = strings.Replace(str, "]", ")", -1) + + return str +} + +func (widget *Widget) torrentPercentDone(torrent *transmissionrpc.Torrent) string { + pctDone := *torrent.PercentDone + str := fmt.Sprintf("%3d", int(pctDone*100)) + + if pctDone == 0.0 { + str = "[gray::b]" + str + } else if pctDone == 1.0 { + str = "[green::b]" + str + } else { + str = "[lightblue::b]" + str + } + + return str + "[white]" +} + +func (widget *Widget) torrentState(torrent *transmissionrpc.Torrent) string { + str := "" + + switch *torrent.Status { + case transmissionrpc.TorrentStatusStopped: + str += "[gray]" + case transmissionrpc.TorrentStatusDownload: + str += "[lightblue]" + case transmissionrpc.TorrentStatusSeed: + str += "[green]" + } + + return str +} diff --git a/modules/transmission/keyboard.go b/modules/transmission/keyboard.go index 27a69804..a52ccd04 100644 --- a/modules/transmission/keyboard.go +++ b/modules/transmission/keyboard.go @@ -6,12 +6,11 @@ func (widget *Widget) initializeKeyboardControls() { widget.SetKeyboardChar("/", widget.ShowHelp, "Show/hide this help prompt") widget.SetKeyboardChar("j", widget.Prev, "Select previous item") widget.SetKeyboardChar("k", widget.Next, "Select next item") - widget.SetKeyboardChar("n", nil, "Add new magnet URL") - widget.SetKeyboardChar("p", nil, "Pause torrent") - widget.SetKeyboardChar("r", nil, "Remove torrent from list") widget.SetKeyboardChar("u", widget.Unselect, "Clear selection") + widget.SetKeyboardKey(tcell.KeyCtrlD, widget.deleteSelectedTorrent, "Delete selected torrent") widget.SetKeyboardKey(tcell.KeyDown, widget.Next, "Select next item") + widget.SetKeyboardKey(tcell.KeyEnter, widget.pauseUnpauseTorrent, "Pause/unpause torrent") widget.SetKeyboardKey(tcell.KeyEsc, widget.Unselect, "Clear selection") widget.SetKeyboardKey(tcell.KeyUp, widget.Prev, "Select previous item") } diff --git a/modules/transmission/widget.go b/modules/transmission/widget.go index 53891683..d53297e1 100644 --- a/modules/transmission/widget.go +++ b/modules/transmission/widget.go @@ -1,8 +1,7 @@ package transmission import ( - "fmt" - "strings" + "errors" "github.com/hekmon/transmissionrpc" "github.com/rivo/tview" @@ -14,6 +13,7 @@ type Widget struct { wtf.KeyboardWidget wtf.ScrollableWidget + client *transmissionrpc.Client settings *Settings torrents []*transmissionrpc.Torrent } @@ -33,6 +33,13 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) * widget.KeyboardWidget.SetView(widget.View) + // Create a persisten transmission client for use in the calls below + client, err := transmissionrpc.New(widget.settings.host, widget.settings.username, widget.settings.password, nil) + if err != nil { + client = nil + } + widget.client = client + return &widget } @@ -40,12 +47,11 @@ func NewWidget(app *tview.Application, pages *tview.Pages, settings *Settings) * // Fetch retrieves torrent data from the Transmission daemon func (widget *Widget) Fetch() ([]*transmissionrpc.Torrent, error) { - transmissionbt, err := transmissionrpc.New(widget.settings.host, widget.settings.username, widget.settings.password, nil) - if err != nil { - return nil, err + if widget.client == nil { + return nil, errors.New("client could not be initialized") } - torrents, err := transmissionbt.TorrentGetAll() + torrents, err := widget.client.TorrentGetAll() if err != nil { return nil, err } @@ -91,69 +97,54 @@ func (widget *Widget) Unselect() { /* -------------------- Unexported Functions -------------------- */ -func (widget *Widget) display() { +func (widget *Widget) currentTorrent() *transmissionrpc.Torrent { if len(widget.torrents) == 0 { - widget.ScrollableWidget.Redraw(widget.CommonSettings.Title, "no torrents", false) + return nil + } + + return widget.torrents[widget.Selected] +} + +// deleteSelected removes the selected torrent from transmission +// This action is non-destructive, it does not delete the files on the host +func (widget *Widget) deleteSelectedTorrent() { + if widget.client == nil { return } - content := widget.contentFrom(widget.torrents) - widget.ScrollableWidget.Redraw(widget.CommonSettings.Title, content, false) -} - -func (widget *Widget) contentFrom(data []*transmissionrpc.Torrent) string { - str := "" - - for idx, torrent := range data { - torrName := *torrent.Name - - row := fmt.Sprintf( - "[%s] %s %s%s[white]", - widget.RowColor(idx), - widget.torrentPercentDone(torrent), - widget.torrentState(torrent), - tview.Escape(widget.prettyTorrentName(torrName)), - ) - - str += wtf.HighlightableHelper(widget.View, row, idx, len(torrName)) + currTorrent := widget.currentTorrent() + if currTorrent == nil { + return } - return str + ids := []int64{*currTorrent.ID} + + removePayload := &transmissionrpc.TorrentRemovePayload{ + IDs: ids, + DeleteLocalData: false, + } + + widget.client.TorrentRemove(removePayload) } -func (widget *Widget) prettyTorrentName(name string) string { - str := strings.Replace(name, "[", "(", -1) - str = strings.Replace(str, "]", ")", -1) +// pauseUnpauseTorrent either pauses or unpauses the downloading and seeding of the selected torrent +func (widget *Widget) pauseUnpauseTorrent() { + if widget.client == nil { + return + } - return str -} + currTorrent := widget.currentTorrent() + if currTorrent == nil { + return + } -func (widget *Widget) torrentPercentDone(torrent *transmissionrpc.Torrent) string { - pctDone := *torrent.PercentDone - str := fmt.Sprintf("%3d", int(pctDone*100)) + ids := []int64{*currTorrent.ID} - if pctDone == 0.0 { - str = "[gray::b]" + str - } else if pctDone == 1.0 { - str = "[green::b]" + str + if *currTorrent.Status == transmissionrpc.TorrentStatusStopped { + widget.client.TorrentStartIDs(ids) } else { - str = "[lightblue::b]" + str + widget.client.TorrentStopIDs(ids) } - return str + "[white]" -} - -func (widget *Widget) torrentState(torrent *transmissionrpc.Torrent) string { - str := "" - - switch *torrent.Status { - case transmissionrpc.TorrentStatusStopped: - str += "[gray]" - case transmissionrpc.TorrentStatusDownload: - str += "[lightblue]" - case transmissionrpc.TorrentStatusSeed: - str += "[green]" - } - - return str + widget.display() }