Skip to content

Commit

Permalink
Merge pull request #14 from vpoluyaktov/feature_GH-13_Default_Sort_Order
Browse files Browse the repository at this point in the history
Saving sorting settings implemented (resolving https://github.com/vpo…
  • Loading branch information
vpoluyaktov authored Apr 24, 2024
2 parents a180daa + bdc6e7d commit 6a9d874
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 24 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,16 @@ To install Audiobook Builder (`abb_ia`) on your system, follow these steps:
2. Move the downloaded binary file to a directory in your system's `PATH`.
3. Open a terminal and navigate to the directory where the binary file is located.
4. Run the binary file by executing the command `./abb_ia`. The TUI interface will appear.
5. Follow the instructions on the application interface to do a search, create an audiobook, and upload it to the [Audiobookshelf server](https://www.audiobookshelf.org) if necessary. You can try searching for:
5. Follow the instructions on the application interface to do a search, create an audiobook, and upload it to the [Audiobookshelf server](https://www.audiobookshelf.org) if necessary. <br/>
You can try searching for:

- **Old Time Radio Researchers Group: Single Episodes**

- **BBC Radio 4: Radio Drama** (make sure to check if the show is copyrighted).
- **CBS Radio: Radio Mystery Theater**
- **Boxcars711:***
- **Greg Lauer:***
- **Relic Radio:***
- **Radio Memories Network:***
- **CBC: Radio Mystery Theater**

6. Enjoy listening to an audiobook on your favorite device.

Expand Down Expand Up @@ -92,7 +92,7 @@ If you prefer to build the program from source, follow these instructions:
- On some systems, you may not see a cursor in the input fields. This is because the color of the cursor in your terminal application settings is the same as the background color of the input field. To solve this issue, you can adjust the settings of your terminal program. You can either change the cursor color (so that it is different from the color of the input fields) or make the cursor blink.
- On some Windows systems, the Audiobook builder has a problem launching ffmpeg (there is an issue with the input file path). If you encounter this problem, please enable DEBUG mode in the application settings, replicate the error, and file a GitHub Bug report by attaching the application log file.
- Sometimes, when the application crashes, the terminal window may be filled with random characters and you won't see a cursor anymore. This happens because of a problem with the TUI framework that was used to create the application. To solve this issue, you can either reopen the terminal window or try running the `reset` command.
- Downloading audiobooks using `abb_id` is incredibly easy and fast. This means that over time, you might collect hundreds of audiobooks with thousands of hours of content. However, this can be a problem because it would be practically impossible to listen to all of them in your lifetime. :-)
- Downloading audiobooks using `abb_id` is incredibly easy and fast. This means that over time, you might collect hundreds of audiobooks with thousands of hours of content. However, this can be a problem because it would be practically impossible to listen to all of them in your lifetime. Congratulations!!! You are a data hoarder now! :-)

## Reporting Bugs through GitHub Issues

Expand Down Expand Up @@ -145,6 +145,6 @@ Since the copyrights for the majority of old-time radio shows have expired and m
## Todo
- The Text to Speech (**TTS**) version of Audiobook Builder is coming soon. It will allow you to create audiobooks from .epub, fb2, and other formats of electronic books.

## Join us on Discord
## Join me on Discord
https://discord.gg/ntYyJ7xfzX

28 changes: 28 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ var (
type Config struct {
DefaultAuthor string `yaml:"DefaultAuthor"`
DefaultTitle string `yaml:"DefaultTitle"`
SortBy string `yaml:"SortBy"`
SortOrder string `yaml:"SortOrder"`
RowsPerPage int `yaml:"RowsPerPage"`
LogFileName string `yaml:"LogFileName"`
OutputDir string `yaml:"Outputdir"`
Expand Down Expand Up @@ -80,6 +82,8 @@ func Load() {
config.SaveMock = false
config.DefaultAuthor = "Old Time Radio Researchers Group"
config.DefaultTitle = "Single Episodes"
config.SortBy = "Date"
config.SortOrder = "Descending"
config.ConcurrentDownloaders = 5
config.ConcurrentEncoders = 5
config.ReEncodeFiles = true
Expand Down Expand Up @@ -226,6 +230,30 @@ func (c *Config) GetDefaultTitle() string {
return c.DefaultTitle
}

func (c *Config) SetSortBy(s string) {
c.SortBy = s
}

func (c *Config) GetSortBy() string {
return c.SortBy
}

func (c *Config) GetSortByOptions() []string {
return []string{"Creator", "Title", "Date", "Size"}
}

func (c *Config) SetSortOrder(s string) {
c.SortOrder = s
}

func (c *Config) GetSortOrder() string {
return c.SortOrder
}

func (c *Config) GetSortOrderOptions() []string {
return []string{"Ascending", "Descending"}
}

func (c *Config) SetConcurrentDownloaders(n int) {
c.ConcurrentDownloaders = n
}
Expand Down
4 changes: 4 additions & 0 deletions internal/controller/config_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"abb_ia/internal/dto"
"abb_ia/internal/logger"
"abb_ia/internal/mq"
"abb_ia/internal/utils"
)

type ConfigController struct {
Expand Down Expand Up @@ -41,6 +42,9 @@ func (c *ConfigController) updateConfig(cmd *dto.SaveConfigCommand) {

config.SaveConfig(&cmd.Config)

logger.SetLogLevel(logger.LogLevelType(utils.GetIndex(logger.LogLeves(), cmd.Config.GetLogLevel()) + 1))
c.mq.SendMessage(mq.ConfigController, mq.SearchPage, &dto.UpdateSearchConfigCommand{Config: cmd.Config}, true)

c.mq.SendMessage(mq.ConfigController, mq.Footer, &dto.SetBusyIndicator{Busy: false}, false)
c.mq.SendMessage(mq.ConfigController, mq.Footer, &dto.UpdateStatus{Message: ""}, false)
}
2 changes: 1 addition & 1 deletion internal/controller/search_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func (c *SearchController) fetchDetails(resp *ia_client.SearchResponse) (int, er
if d != nil {
item.Server = d.Server
item.Dir = d.Dir
if len(doc.Creator) > 0 && d.Metadata.Creator[0] != "" {
if len(doc.Creator) > 0 && doc.Creator[0] != "" {
item.Creator = doc.Creator[0]
} else if len(d.Metadata.Creator) > 0 && d.Metadata.Creator[0] != "" {
item.Creator = d.Metadata.Creator[0]
Expand Down
13 changes: 12 additions & 1 deletion internal/dto/search.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package dto

import "fmt"
import (
"abb_ia/internal/config"
"fmt"
)

type SearchCondition struct {
Author string
Expand All @@ -17,6 +20,14 @@ func (c *SearchCommand) String() string {
return fmt.Sprintf("SearchCommand: Author: %s, Title: %s", c.Condition.Author, c.Condition.Title)
}

type UpdateSearchConfigCommand struct {
Config config.Config
}

func (c *UpdateSearchConfigCommand) String() string {
return fmt.Sprintf("UpdateSearchConfigCommand: Creator: %s, Title: %s", c.Config.DefaultAuthor, c.Config.DefaultTitle)
}

type GetNextPageCommand struct {
Condition SearchCondition
}
Expand Down
3 changes: 2 additions & 1 deletion internal/ia/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,8 +172,9 @@ func (client *IAClient) DownloadFile(localDir string, localFile string, iaServer

req, _ := http.NewRequest("GET", fileUrl, nil)
resp, _ := http.DefaultClient.Do(req)
if resp.StatusCode != 200 {
if resp == nil || resp.StatusCode != 200 {
logger.Fatal("Error while downloading: " + resp.Status)
return
}
defer resp.Body.Close()

Expand Down
24 changes: 14 additions & 10 deletions internal/ui/config_page.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ type ConfigPage struct {
logLevelField *tview.DropDown
defaultAuthor *tview.InputField
defaultTitle *tview.InputField
sortByField *tview.DropDown
sortOrderField *tview.DropDown
rowsPerPage *tview.InputField
useMockField *tview.Checkbox
saveMockField *tview.Checkbox
Expand Down Expand Up @@ -66,18 +68,20 @@ func newConfigPage(dispatcher *mq.Dispatcher) *ConfigPage {

// Audobookbuilder config section
p.configSection = newGrid()
p.configSection.SetColumns(-2, -2, -1)
p.configSection.SetColumns(-2, -2, 15)
p.configSection.SetBorder(true)
p.configSection.SetTitle(" Audiobook Builder Configuration: ")
p.configSection.SetTitleAlign(tview.AlignLeft)

configFormLeft := newForm()
configFormLeft.SetHorizontal(false)
p.defaultAuthor = configFormLeft.AddInputField("Creator:", "", 20, nil, func(t string) { p.configCopy.SetDefaultAuthor(t) })
p.defaultTitle = configFormLeft.AddInputField("Title:", "", 20, nil, func(t string) { p.configCopy.SetDefaultTitle(t) })
p.defaultAuthor = configFormLeft.AddInputField("Creator:", "", 25, nil, func(t string) { p.configCopy.SetDefaultAuthor(t) })
p.defaultTitle = configFormLeft.AddInputField("Title:", "", 25, nil, func(t string) { p.configCopy.SetDefaultTitle(t) })
p.sortByField = configFormLeft.AddDropdown("Sort By:", utils.AddSpaces(p.configCopy.GetSortByOptions()), 1, func(o string, i int) { p.configCopy.SetSortBy(strings.TrimSpace(o)) })
p.sortOrderField = configFormLeft.AddDropdown("Sort Order:", utils.AddSpaces(p.configCopy.GetSortOrderOptions()), 1, func(o string, i int) { p.configCopy.SetSortOrder(strings.TrimSpace(o)) })
p.rowsPerPage = configFormLeft.AddInputField("Page size:", "", 4, acceptInt, func(t string) { p.configCopy.SetRowsPerPage(utils.ToInt(t)) })
p.useMockField = configFormLeft.AddCheckbox("Use mock?", false, func(t bool) { p.configCopy.SetUseMock(t) })
p.saveMockField = configFormLeft.AddCheckbox("Save mock?", false, func(t bool) { p.configCopy.SetSaveMock(t) })
// p.useMockField = configFormLeft.AddCheckbox("Use mock?", false, func(t bool) { p.configCopy.SetUseMock(t) })
// p.saveMockField = configFormLeft.AddCheckbox("Save mock?", false, func(t bool) { p.configCopy.SetSaveMock(t) })
p.configSection.AddItem(configFormLeft.Form, 0, 0, 1, 1, 0, 0, true)

configFormRight := newForm()
Expand All @@ -95,7 +99,7 @@ func newConfigPage(dispatcher *mq.Dispatcher) *ConfigPage {
buttonsForm := newForm()
buttonsForm.SetHorizontal(false)
buttonsForm.SetButtonsAlign(tview.AlignRight)
p.saveConfigButton = buttonsForm.AddButton(" Save ", p.SaveConfig)
p.saveConfigButton = buttonsForm.AddButton(" Save ", p.SaveConfig)
buttonsGrid.AddItem(buttonsForm, 0, 0, 1, 1, 0, 0, true)
buttonsForm = newForm()
buttonsForm.SetHorizontal(false)
Expand Down Expand Up @@ -156,9 +160,9 @@ func newConfigPage(dispatcher *mq.Dispatcher) *ConfigPage {
p.mainGrid.SetNavigationOrder(
p.defaultAuthor,
p.defaultTitle,
p.sortByField,
p.sortOrderField,
p.rowsPerPage,
p.useMockField,
p.saveMockField,
p.outputDir,
p.copyToOutputDir,
p.tmpDir,
Expand Down Expand Up @@ -210,9 +214,9 @@ func (p *ConfigPage) displayConfig(c *dto.DisplayConfigCommand) {
p.logLevelField.SetCurrentOption(utils.GetIndex(logger.LogLeves(), p.configCopy.GetLogLevel()))
p.defaultAuthor.SetText(p.configCopy.GetDefaultAuthor())
p.defaultTitle.SetText(p.configCopy.GetDefaultTitle())
p.sortByField.SetCurrentOption(utils.GetIndex(config.Instance().GetSortByOptions(), p.configCopy.GetSortBy()))
p.sortOrderField.SetCurrentOption(utils.GetIndex(config.Instance().GetSortOrderOptions(), p.configCopy.GetSortOrder()))
p.rowsPerPage.SetText(utils.ToString(p.configCopy.GetRowsPerPage()))
p.useMockField.SetChecked(p.configCopy.IsUseMock())
p.saveMockField.SetChecked(p.configCopy.IsSaveMock())

p.concurrentDownloaders.SetText(utils.ToString(p.configCopy.GetConcurrentDownloaders()))
p.concurrentEncoders.SetText(utils.ToString(p.configCopy.GetConcurrentEncoders()))
Expand Down
45 changes: 39 additions & 6 deletions internal/ui/search_page.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ type SearchPage struct {

resultSection *grid
resultTable *table
urlSection *grid
urlField *tview.TextView

detailsSection *grid
descriptionView *tview.TextView
Expand All @@ -48,7 +50,7 @@ func newSearchPage(dispatcher *mq.Dispatcher) *SearchPage {
p.searchCondition.Title = config.Instance().GetDefaultTitle()

p.mainGrid = newGrid()
p.mainGrid.SetRows(9, -1, -1)
p.mainGrid.SetRows(9, -1, -1, 3)
p.mainGrid.SetColumns(0)

// search section
Expand All @@ -67,8 +69,8 @@ func newSearchPage(dispatcher *mq.Dispatcher) *SearchPage {
f.SetButtonsAlign(tview.AlignRight)
p.searchSection.AddItem(f, 0, 0, 1, 1, 0, 0, true)
f = newForm()
p.SortBy = f.AddDropdown("Sort by:", utils.AddSpaces([]string{"Creator", "Title", "Date", "Size "}), 1, func(o string, i int) { p.searchCondition.SortBy = p.mapSortBy(o) })
p.sortOrder = f.AddDropdown("Sort order:", utils.AddSpaces([]string{"Ascending", "Descending"}), 1, func(o string, i int) { p.searchCondition.SortOrder = p.mapSortOrder(o) })
p.SortBy = f.AddDropdown("Sort by:", utils.AddSpaces(config.Instance().GetSortByOptions()), utils.GetIndex(config.Instance().GetSortByOptions(), config.Instance().GetSortBy()), func(o string, i int) { p.searchCondition.SortBy = p.mapSortBy(o) })
p.sortOrder = f.AddDropdown("Sort order:", utils.AddSpaces(config.Instance().GetSortOrderOptions()), utils.GetIndex(config.Instance().GetSortOrderOptions(), config.Instance().GetSortOrder()), func(o string, i int) { p.searchCondition.SortOrder = p.mapSortOrder(o) })
p.searchSection.AddItem(f, 0, 1, 1, 1, 0, 0, true)
g := newGrid()
g.SetRows(-1, -1)
Expand Down Expand Up @@ -129,11 +131,26 @@ func newSearchPage(dispatcher *mq.Dispatcher) *SearchPage {

p.mainGrid.AddItem(p.detailsSection.Grid, 2, 0, 1, 1, 0, 0, true)

// URL section
p.urlSection = newGrid()
p.urlSection.SetRows(1)
p.urlSection.SetColumns(-1)
p.urlSection.SetBorder(true)
p.urlSection.SetTitle(" Internet Archive item url: ")
p.urlSection.SetTitleAlign(tview.AlignLeft)
p.urlField = tview.NewTextView()
p.urlSection.AddItem(p.urlField, 0, 0, 1, 1, 0, 0, false)
p.mainGrid.AddItem(p.urlSection.Grid, 3, 0, 1, 1, 0, 0, true)

p.mq.SendMessage(mq.SearchPage, mq.Frame, &dto.SwitchToPageCommand{Name: "SearchPage"}, false)
ui.SetFocus(p.searchSection.Grid)

p.mainGrid.Focus(func(pr tview.Primitive) {
ui.SetFocus(p.searchSection.Grid)
if p.resultTable.GetRowCount() == 0 {
ui.SetFocus(p.searchSection.Grid)
} else {
ui.SetFocus(p.resultSection.Grid)
}
})

// screen navigation order
Expand Down Expand Up @@ -163,6 +180,8 @@ func (p *SearchPage) checkMQ() {

func (p *SearchPage) dispatchMessage(m *mq.Message) {
switch dto := m.Dto.(type) {
case *dto.UpdateSearchConfigCommand:
p.updateSearchConfig(dto)
case *dto.IAItem:
p.updateResult(dto)
case *dto.SearchProgress:
Expand Down Expand Up @@ -205,6 +224,17 @@ func (p *SearchPage) clearEverything() {
p.author.SetText("")
p.title.SetText("")
p.clearSearchResults()
p.urlField.SetText("")
}

func (p *SearchPage) updateSearchConfig(c *dto.UpdateSearchConfigCommand) {
if p.author.GetText() == "" && p.title.GetText() == "" {
p.author.SetText(c.Config.GetDefaultAuthor())
p.title.SetText(c.Config.GetDefaultTitle())
p.SortBy.SetCurrentOption(utils.GetIndex(c.Config.GetSortByOptions(), c.Config.GetSortBy()))
p.sortOrder.SetCurrentOption(utils.GetIndex(c.Config.GetSortOrderOptions(), c.Config.GetSortOrder()))
ui.Draw()
}
}

func (p *SearchPage) lastRowEvent() {
Expand All @@ -230,17 +260,20 @@ func (p *SearchPage) updateTitle(sp *dto.SearchProgress) {

func (p *SearchPage) updateDetails(row int, col int) {
if row > 0 && len(p.searchResult) > 0 && len(p.searchResult) >= row {
d := p.searchResult[row-1].Description
item := p.searchResult[row-1]
d := item.Description
p.descriptionView.SetText(d)
p.descriptionView.ScrollToBeginning()

p.filesTable.Clear()
p.filesTable.showHeader()
files := p.searchResult[row-1].AudioFiles
files := item.AudioFiles
for _, f := range files {
p.filesTable.appendRow(f.Name, f.Format, utils.SecondsToTime(f.Length), utils.BytesToHuman(f.Size))
}
p.filesTable.ScrollToBeginning()

p.urlField.SetText(" " + item.IaURL)
}
}

Expand Down

0 comments on commit 6a9d874

Please sign in to comment.