Add support for color themes

This commit is contained in:
Adriano Caloiaro 2023-07-08 08:39:12 -06:00
parent fee58c2c38
commit 503a4b26fe
No known key found for this signature in database
GPG key ID: C2BC56DE73CE3F75
6 changed files with 202 additions and 76 deletions

View file

@ -3,13 +3,13 @@ A simple terminal UI player for [di.fm Premium](http://di.fm)
![App Screenshot](https://user-images.githubusercontent.com/3331648/81481515-bb668400-91fe-11ea-8a7c-39e1bb76c55d.png)
# Dependencies
## Dependencies
## PulseAudio
### PulseAudio
Both linux and MacOS depend on pulseaudio to be running.
### MacOS
#### MacOS
By default, pulseaudio on MacOS runs as "root", which is not ideal. PulseAudio is best run by non-root users. By symbolically linking the pulseaudio plist file into your user's `~/Library/LaunchAgents/`, it runs as your user.
@ -19,17 +19,17 @@ ln -s $(brew info pulseaudio | grep "/usr/local/Cellar" | awk '{print $1}')//hom
brew services start pulseaudio
```
### Linux
#### Debian / Ubuntu
`apt install pulseaudio`
# Install
## Install
## Binary Releases
### Binary Releases
There are binary builds available in [releases](https://github.com/acaloiaro/di-tui/releases).
## With `go install`
### With `go install`
`go install github.com/acaloiaro/di-tui@latest`
If `$GOPATH/bin` is not on your `$PATH` (modify accordingly for ZSH users `~/.zshrc`)
@ -40,14 +40,14 @@ source ~/.bashrc
If your `$GOPATH` is not set, see https://github.com/golang/go/wiki/SettingGOPATH
# Authenticate
## Authenticate
There are two authentication options
- Enter your username and password directly into `di-tui`
- If you're justifiably uncomfortable with entering your username/password into this application, copy your "Listen Key" from (https://www.di.fm/settings) and create the following file:
## ~/.config/di-tui/config.yml
### ~/.config/di-tui/config.yml
```yml
token: <YOUR LISTEN KEY>
album_art: <BOOLEAN>
@ -58,6 +58,23 @@ album_art: <BOOLEAN>
| token | Your di.fm authentication "Listen Key" found at https://www.di.fm/settings |
| album_art | Turn album art on or off |
# Run
## Configuration
### Themes
By default, `di-tui` respects your terminal's color scheme. However, there are four color settings that one can change by adding a `theme` to `config.yml`.
**Tomorrow-Night** inspired theme
```yml
theme:
primary_color: "#81a2be"
background_color: "#2a1f1a"
primary_text_color: "#969896"
secondary_text_color: "#81a2be"
```
## Run
`di-tui`

View file

@ -8,6 +8,14 @@ import (
"github.com/spf13/viper"
)
// TODO This application is migrating to having all of its configuration read into this `Config` struct, rather than
// using individual `ReadType` functions from viper. Migrating all `Get*` methods to use `Config` instead.
type Config struct {
Theme map[string]string
}
var C Config
func init() {
viper.SetConfigName("config")
viper.SetConfigType("yaml")
@ -21,6 +29,11 @@ func init() {
if err != nil {
saveConfig()
}
if err := viper.Unmarshal(&C); err != nil {
fmt.Fprintf(os.Stderr, "unable to load di-tui configuration file: %v", err)
os.Exit(1)
}
}
// AlbumArt returns true if album art should be fetched when a new song begins playing
@ -76,6 +89,35 @@ func SaveListenToken(token string) {
saveConfig()
}
// HasTheme returns true if the di-tui config has a Theme set
func HasTheme() bool {
if C.Theme["primary_color"] != "" {
return true
} else {
return false
}
}
// GetThemePrimaryColor gets the theme's primary color
func GetThemePrimaryColor() string {
return C.Theme["primary_color"]
}
// GetThemePrimaryColor gets the theme's background color
func GetThemeBackgroundColor() string {
return C.Theme["background_color"]
}
// GetThemePrimaryTextColor gets the theme's primary text color
func GetThemePrimaryTextColor() string {
return C.Theme["primary_text_color"]
}
// GetThemePrimaryColor gets the theme's primary color
func GetThemeSecondaryTextColor() string {
return C.Theme["secondary_text_color"]
}
func saveConfig() {
viper.SetConfigFile(configFilePath())
viper.SetConfigType("yaml")

11
go.mod
View file

@ -4,12 +4,12 @@ go 1.19
require (
github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8
github.com/gdamore/tcell v1.3.0
github.com/gdamore/tcell/v2 v2.6.0
github.com/hajimehoshi/go-mp3 v0.2.1
github.com/jfreymuth/pulse v0.1.0
github.com/michiwend/gomusicbrainz v0.0.0-20181012083520-6c07e13dd396
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
github.com/rivo/tview v0.0.0-20200219210816-cd38d7432498
github.com/rivo/tview v0.0.0-20230621164836-6cc0565babaf
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.6.2
gopkg.in/ini.v1 v1.52.0
@ -21,19 +21,20 @@ require (
github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/kr/pretty v0.2.0 // indirect
github.com/lucasb-eyer/go-colorful v1.0.3 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/magiconair/properties v1.8.1 // indirect
github.com/mattn/go-runewidth v0.0.8 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/michiwend/golang-pretty v0.0.0-20141116172505-8ac61812ea3f // indirect
github.com/mitchellh/mapstructure v1.1.2 // indirect
github.com/pelletier/go-toml v1.6.0 // indirect
github.com/rivo/uniseg v0.1.0 // indirect
github.com/rivo/uniseg v0.4.3 // indirect
github.com/spf13/afero v1.2.2 // indirect
github.com/spf13/cast v1.3.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/stretchr/testify v1.4.0 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/term v0.5.0 // indirect
golang.org/x/text v0.8.0 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/yaml.v2 v2.2.8 // indirect

52
go.sum
View file

@ -1,7 +1,6 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@ -26,8 +25,8 @@ github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko=
github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg=
github.com/gdamore/tcell v1.3.0 h1:r35w0JBADPZCVQijYebl6YMWWtHRqVEGt7kL2eBADRM=
github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM=
github.com/gdamore/tcell/v2 v2.6.0 h1:OKbluoP9VYmJwZwq/iLb4BxwKcwGthaa1YNBJIyCySg=
github.com/gdamore/tcell/v2 v2.6.0/go.mod h1:be9omFATkdr0D9qewWW3d+MEvl5dha+Etb5y65J2H8Y=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
@ -54,8 +53,6 @@ github.com/hajimehoshi/go-mp3 v0.2.1/go.mod h1:Rr+2P46iH6PwTPVgSsEwBkon0CK5DxCAe
github.com/hajimehoshi/oto v0.3.4/go.mod h1:PgjqsBJff0efqL2nlMJidJgVJywLn6M4y8PI4TfeWfA=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/jfreymuth/pulse v0.0.0-20201014123913-1e525c426c93 h1:gDcaH96SZ7q1JU6hj0tSv8FiuqadFERU17lLxhphLa8=
github.com/jfreymuth/pulse v0.0.0-20201014123913-1e525c426c93/go.mod h1:cpYspI6YljhkUf1WLXLLDmeaaPFc3CnGLjDZf9dZ4no=
github.com/jfreymuth/pulse v0.1.0 h1:KN38/9hoF9PJvP5DpEVhMRKNuwnJUonc8c9ARorRXUA=
github.com/jfreymuth/pulse v0.1.0/go.mod h1:cpYspI6YljhkUf1WLXLLDmeaaPFc3CnGLjDZf9dZ4no=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
@ -72,14 +69,12 @@ github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfn
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s=
github.com/lucasb-eyer/go-colorful v1.0.3 h1:QIbQXiugsb+q10B+MI+7DI1oQLdmnep86tWFlaaUAac=
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.8 h1:3tS41NlGYSmhhe/8fhGRzc+z3AYCw1Fe1WAyLuujKs0=
github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/michiwend/golang-pretty v0.0.0-20141116172505-8ac61812ea3f h1:oF0u/1VBm5gYitYvcIh443XZuYYkR50CP0Vsj3gAa1o=
github.com/michiwend/golang-pretty v0.0.0-20141116172505-8ac61812ea3f/go.mod h1:k0nOQg5bmAmEwWAuodvib9B74Oyny6aRMpkBcVWEtKs=
@ -106,10 +101,11 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rivo/tview v0.0.0-20200219210816-cd38d7432498 h1:4CFNy7/q7P06AsIONZzuWy7jcdqEmYQvOZ9FAFZdbls=
github.com/rivo/tview v0.0.0-20200219210816-cd38d7432498/go.mod h1:6lkG1x+13OShEf0EaOCaTQYyB7d5nSbb181KtjlS+84=
github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/tview v0.0.0-20230621164836-6cc0565babaf h1:IchpMMtnfvzg7T3je672bP1nKWz1M4tW3kMZT6CbgoM=
github.com/rivo/tview v0.0.0-20230621164836-6cc0565babaf/go.mod h1:nVwGv4MP47T0jvlk7KuTTjjuSmrGO4JF0iaiNt4bufE=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw=
github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
@ -143,26 +139,34 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -170,12 +174,21 @@ golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -184,6 +197,9 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=

25
main.go
View file

@ -12,18 +12,13 @@ import (
"github.com/acaloiaro/di-tui/views"
"github.com/rivo/tview"
"github.com/gdamore/tcell"
"github.com/gdamore/tcell/v2"
"github.com/spf13/pflag"
"github.com/spf13/viper"
)
var ctx *context.AppContext
func init() {
// when true color is on, tcell does not respect your terminal colors
os.Setenv("TCELL_TRUECOLOR", "disable")
}
func main() {
pflag.String("username", "", "your di.fm username")
pflag.String("password", "", "your di.fm password")
@ -55,9 +50,10 @@ func main() {
func run() {
configureEventHandling()
updateScreenLayout()
configureKeybindings(ctx)
FetchFavoritesAndChannels()
ctx.View.Keybindings.Bindings = views.GetKeybindings()
err := ctx.View.App.Run()
if err != nil {
@ -173,21 +169,6 @@ func configureEventHandling() {
}
func configureKeybindings(ctx *context.AppContext) {
bindings := []views.UIKeybinding{
views.UIKeybinding{Shortcut: "c", Description: "Channels", Func: func() {}},
views.UIKeybinding{Shortcut: "f", Description: "Favorites", Func: func() {}},
views.UIKeybinding{Shortcut: "F", Description: "Toggle Favorite", Func: func() {}},
views.UIKeybinding{Shortcut: "j", Description: "Scroll Down", Func: func() {}},
views.UIKeybinding{Shortcut: "k", Description: "Scroll Up", Func: func() {}},
views.UIKeybinding{Shortcut: "q", Description: "Quit", Func: func() {}},
views.UIKeybinding{Shortcut: "p", Description: "Pause", Func: func() {}},
views.UIKeybinding{Shortcut: "Enter", Description: "Play", Func: func() {}},
}
ctx.View.Keybindings.Bindings = bindings
}
func FetchFavoritesAndChannels() {
ctx.View.ChannelList.Clear()
ctx.View.FavoriteList.Clear()

View file

@ -2,13 +2,43 @@ package views
import (
"fmt"
"os"
"strings"
"github.com/acaloiaro/di-tui/components"
"github.com/gdamore/tcell"
"github.com/acaloiaro/di-tui/config"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
)
var primaryTextColorString string
var secondaryTextColorString string
var primaryColor tcell.Color
var backgroundColor tcell.Color
var primaryTextColor tcell.Color
var secondaryTextColor tcell.Color
func init() {
if config.HasTheme() {
os.Setenv("COLORTERM", "24bit")
primaryTextColorString = config.GetThemePrimaryTextColor()
secondaryTextColorString = config.GetThemeSecondaryTextColor()
secondaryTextColor = tcell.GetColor(secondaryTextColorString)
primaryColor = tcell.GetColor(config.GetThemePrimaryColor())
backgroundColor = tcell.GetColor(config.GetThemeBackgroundColor())
} else {
// do not override the terminal's theme, use all of its defaults
os.Setenv("TCELL_TRUECOLOR", "disable")
primaryTextColorString = "white"
secondaryTextColorString = "blue"
primaryColor = tcell.ColorBlue
primaryTextColor = tcell.GetColor(primaryTextColorString)
secondaryTextColor = tcell.GetColor(secondaryTextColorString)
}
primaryTextColor = tcell.GetColor(primaryTextColorString)
}
// ViewContext holds references to all the top-level UI elements in the application
type ViewContext struct {
App *tview.Application
@ -62,19 +92,21 @@ func CreateViewContext() *ViewContext {
// Draw draws a NowPlayingView onto the scren
func (n *NowPlayingView) Draw(screen tcell.Screen) {
n.Box.Draw(screen)
n.Box.SetBackgroundColor(backgroundColor)
x, y, width, _ := n.GetInnerRect()
line := fmt.Sprintf("%s[white] %s", "Channel:", n.Channel.Name)
tview.Print(screen, line, x, y, width, tview.AlignLeft, tcell.ColorBlue)
line := fmt.Sprintf("%s[%s] %s", "Channel:", secondaryTextColorString, n.Channel.Name)
tview.Print(screen, line, x, y, width, tview.AlignLeft, primaryTextColor)
line = fmt.Sprintf("%s[white] %s", "Artist:", n.Track.Artist)
tview.Print(screen, line, x, y+1, width, tview.AlignLeft, tcell.ColorBlue)
line = fmt.Sprintf("%s[%s] %s", "Artist:", secondaryTextColorString, n.Track.Artist)
tview.Print(screen, line, x, y+1, width, tview.AlignLeft, primaryTextColor)
line = fmt.Sprintf("%s[white] %s", "Track:", n.Track.Title)
tview.Print(screen, line, x, y+2, width, tview.AlignLeft, tcell.ColorBlue)
line = fmt.Sprintf("%s[%s] %s", "Track:", secondaryTextColorString, n.Track.Title)
tview.Print(screen, line, x, y+2, width, tview.AlignLeft, primaryTextColor)
line = fmt.Sprintf("%s[white] %s", "Elapsed:", n.elapsedString())
tview.Print(screen, line, x, y+3, width, tview.AlignLeft, tcell.ColorBlue)
line = fmt.Sprintf("%s[%s] %s", "Elapsed:", secondaryTextColorString, n.elapsedString())
tview.Print(screen, line, x, y+3, width, tview.AlignLeft, primaryTextColor)
if n.Art == "" {
return
@ -83,12 +115,12 @@ func (n *NowPlayingView) Draw(screen tcell.Screen) {
artLines := strings.Split(n.Art, "\n")
for i, line := range artLines {
if i == 0 {
label := fmt.Sprintf("[white] %s", "Album Cover")
tview.Print(screen, label, x, y+4, width, tview.AlignCenter, tcell.ColorBlue)
label := fmt.Sprintf("[%s] %s", primaryTextColorString, "Album Cover")
tview.Print(screen, label, x, y+4, width, tview.AlignCenter, secondaryTextColor)
}
l := fmt.Sprintf("[white] %s", line)
tview.Print(screen, l, x, y+5+i, width, tview.AlignCenter, tcell.ColorBlue)
l := fmt.Sprintf("[%s] %s", primaryTextColorString, line)
tview.Print(screen, l, x, y+5+i, width, tview.AlignCenter, secondaryTextColor)
}
}
@ -107,20 +139,24 @@ func (n *NowPlayingView) elapsedString() (str string) {
func (s *StatusView) Draw(screen tcell.Screen) {
s.Box.Draw(screen)
s.Box.SetBackgroundColor(backgroundColor)
x, y, width, _ := s.GetInnerRect()
line := fmt.Sprintf("%s[white] %s", "Message:", s.Message)
tview.Print(screen, line, x, y, width, tview.AlignLeft, tcell.ColorBlue)
line := fmt.Sprintf("%s[%s] %s", "Message:", secondaryTextColorString, s.Message)
tview.Print(screen, line, x, y, width, tview.AlignLeft, primaryTextColor)
}
// Draw draws the key bindings view on to the screen
func (k *KeybindingView) Draw(screen tcell.Screen) {
k.Box.Draw(screen)
k.Box.SetBackgroundColor(backgroundColor)
x, y, width, _ := k.GetInnerRect()
previousWidth := 0
for j, bnd := range k.Bindings {
line := fmt.Sprintf("(%s)[white] %s", bnd.Shortcut, bnd.Description)
tview.Print(screen, line, x+previousWidth, y, width, tview.AlignLeft, tcell.ColorBlue)
line := fmt.Sprintf("(%s)[%s] %s", bnd.Shortcut, primaryTextColorString, bnd.Description)
tview.Print(screen, line, x+previousWidth, y, width, tview.AlignLeft, secondaryTextColor)
previousWidth += len(bnd.Shortcut) + len(bnd.Description) + 4
// virtically separate playback controls from ui controls
// yes, this is hacky, but there's a comment, so it's ok, right?
@ -136,7 +172,12 @@ func createChannelList() *tview.List {
list.
ShowSecondaryText(false).
SetBorder(true).
SetTitle(" Channels ")
SetTitle(" Channels ").
SetTitleColor(primaryTextColor).
SetBorderColor(primaryColor)
list.SetMainTextColor(primaryTextColor)
list.Box.SetBackgroundColor(backgroundColor)
return list
}
@ -146,7 +187,12 @@ func createFavoriteList() *tview.List {
list.
ShowSecondaryText(false).
SetBorder(true).
SetTitle(" Favorites ")
SetBorderColor(primaryColor).
SetTitle(" Favorites ").
SetTitleColor(primaryTextColor)
list.Box.SetBackgroundColor(backgroundColor)
list.SetMainTextColor(primaryTextColor)
return list
}
@ -155,8 +201,12 @@ func createKeybindings() *KeybindingView {
kbv := &KeybindingView{Box: tview.NewBox()}
kbv.
SetBorder(true).
SetBorderColor(primaryColor).
SetTitleColor(primaryTextColor).
SetTitle(" Keyboard Controls ")
kbv.SetBorderColor(primaryColor)
return kbv
}
@ -167,8 +217,10 @@ func createNowPlaying() *NowPlayingView {
Elapsed: 0.0,
}
np.SetTitle(" Now Playing ")
np.SetBorder(true)
np.SetTitle(" Now Playing ").
SetBorder(true).
SetBorderColor(primaryColor).
SetTitleColor(primaryTextColor)
return np
}
@ -179,7 +231,24 @@ func createStatusView() *StatusView {
Message: "Ready to Play",
}
sv.SetTitle(" Status ")
sv.SetTitleColor(primaryTextColor)
sv.SetBorder(true)
sv.SetBorderColor(primaryColor)
return sv
}
func GetKeybindings() (bindings []UIKeybinding) {
bindings = []UIKeybinding{
UIKeybinding{Shortcut: "c", Description: "Channels", Func: func() {}},
UIKeybinding{Shortcut: "f", Description: "Favorites", Func: func() {}},
UIKeybinding{Shortcut: "F", Description: "Toggle Favorite", Func: func() {}},
UIKeybinding{Shortcut: "j", Description: "Scroll Down", Func: func() {}},
UIKeybinding{Shortcut: "k", Description: "Scroll Up", Func: func() {}},
UIKeybinding{Shortcut: "q", Description: "Quit", Func: func() {}},
UIKeybinding{Shortcut: "p", Description: "Pause", Func: func() {}},
UIKeybinding{Shortcut: "Enter", Description: "Play", Func: func() {}},
}
return bindings
}