v/GTT
1
0
mirror of https://github.com/eeeXun/GTT.git synced 2025-05-19 09:10:42 -07:00

refactor: to multi directory

This commit is contained in:
eeeXun 2022-10-24 22:38:43 +08:00
parent e09e846077
commit 8efb962eee
10 changed files with 272 additions and 255 deletions

123
color.go
View File

@ -1,123 +0,0 @@
package main
import (
"github.com/gdamore/tcell/v2"
)
var (
AllTheme = []string{"Gruvbox", "Nord"}
Palette = []string{"red", "green", "yellow", "blue", "purple", "cyan", "orange"}
Themes = map[string]map[string]tcell.Color{
"Gruvbox": {
"bg": tcell.NewHexColor(0x282828),
"fg": tcell.NewHexColor(0xebdbb2),
"gray": tcell.NewHexColor(0x665c54),
"red": tcell.NewHexColor(0xfb4934),
"green": tcell.NewHexColor(0xb8bb26),
"yellow": tcell.NewHexColor(0xfabd2f),
"blue": tcell.NewHexColor(0x83a598),
"purple": tcell.NewHexColor(0xd3869b),
"cyan": tcell.NewHexColor(0x8ec07c),
"orange": tcell.NewHexColor(0xfe8019),
},
"Nord": {
"bg": tcell.NewHexColor(0x3b4252),
"fg": tcell.NewHexColor(0xeceff4),
"gray": tcell.NewHexColor(0x4c566a),
"red": tcell.NewHexColor(0xbf616a),
"green": tcell.NewHexColor(0xa3be8c),
"yellow": tcell.NewHexColor(0xebcb8b),
"blue": tcell.NewHexColor(0x81a1c1),
"purple": tcell.NewHexColor(0xb48ead),
"cyan": tcell.NewHexColor(0x8fbcbb),
"orange": tcell.NewHexColor(0xd08770),
},
}
)
type WindowStyle struct {
borderColor string
}
type Style struct {
src WindowStyle
dst WindowStyle
backgroundColor string
foregroundColor string
selectedColor string
prefixColor string
labelColor string
pressColor string
highLightColor string
Theme string
Transparent bool
}
func NewStyle() *Style {
return &Style{
backgroundColor: "bg",
foregroundColor: "fg",
selectedColor: "gray",
prefixColor: "cyan",
labelColor: "yellow",
pressColor: "purple",
highLightColor: "orange",
}
}
func (s Style) BackgroundColor() tcell.Color {
if s.Transparent {
return tcell.ColorDefault
}
return Themes[s.Theme][s.backgroundColor]
}
func (s Style) ForegroundColor() tcell.Color {
return Themes[s.Theme][s.foregroundColor]
}
func (s Style) SelectedColor() tcell.Color {
return Themes[s.Theme][s.selectedColor]
}
func (s Style) PrefixColor() tcell.Color {
return Themes[s.Theme][s.prefixColor]
}
func (s Style) LabelColor() tcell.Color {
return Themes[s.Theme][s.labelColor]
}
func (s Style) PressColor() tcell.Color {
return Themes[s.Theme][s.pressColor]
}
func (s Style) HighLightColor() tcell.Color {
return Themes[s.Theme][s.highLightColor]
}
func (s Style) SrcBorderColor() tcell.Color {
return Themes[s.Theme][s.src.borderColor]
}
func (s Style) DstBorderColor() tcell.Color {
return Themes[s.Theme][s.dst.borderColor]
}
func (s Style) SrcBorderStr() string {
return s.src.borderColor
}
func (s Style) DstBorderStr() string {
return s.dst.borderColor
}
func (s *Style) SetSrcBorderColor(color string) *Style {
s.src.borderColor = color
return s
}
func (s *Style) SetDstBorderColor(color string) *Style {
s.dst.borderColor = color
return s
}

View File

@ -33,8 +33,8 @@ func configInit() {
}
// setup
translator.srcLang = config.GetString("source.language")
translator.dstLang = config.GetString("destination.language")
translator.SrcLang = config.GetString("source.language")
translator.DstLang = config.GetString("destination.language")
style.Theme = config.GetString("theme")
style.Transparent = config.GetBool("transparent")
style.SetSrcBorderColor(config.GetString("source.borderColor")).
@ -53,17 +53,17 @@ func updateConfig() {
changed = true
config.Set("transparent", style.Transparent)
}
if config.GetString("source.language") != translator.srcLang {
if config.GetString("source.language") != translator.SrcLang {
changed = true
config.Set("source.language", translator.srcLang)
config.Set("source.language", translator.SrcLang)
}
if config.GetString("source.borderColor") != style.SrcBorderStr() {
changed = true
config.Set("source.borderColor", style.SrcBorderStr())
}
if config.GetString("destination.language") != translator.dstLang {
if config.GetString("destination.language") != translator.DstLang {
changed = true
config.Set("destination.language", translator.dstLang)
config.Set("destination.language", translator.DstLang)
}
if config.GetString("destination.borderColor") != style.DstBorderStr() {
changed = true

36
internal/color/color.go Normal file
View File

@ -0,0 +1,36 @@
package color
import (
"github.com/gdamore/tcell/v2"
)
var (
AllTheme = []string{"Gruvbox", "Nord"}
Palette = []string{"red", "green", "yellow", "blue", "purple", "cyan", "orange"}
themes = map[string]map[string]tcell.Color{
"Gruvbox": {
"bg": tcell.NewHexColor(0x282828),
"fg": tcell.NewHexColor(0xebdbb2),
"gray": tcell.NewHexColor(0x665c54),
"red": tcell.NewHexColor(0xfb4934),
"green": tcell.NewHexColor(0xb8bb26),
"yellow": tcell.NewHexColor(0xfabd2f),
"blue": tcell.NewHexColor(0x83a598),
"purple": tcell.NewHexColor(0xd3869b),
"cyan": tcell.NewHexColor(0x8ec07c),
"orange": tcell.NewHexColor(0xfe8019),
},
"Nord": {
"bg": tcell.NewHexColor(0x3b4252),
"fg": tcell.NewHexColor(0xeceff4),
"gray": tcell.NewHexColor(0x4c566a),
"red": tcell.NewHexColor(0xbf616a),
"green": tcell.NewHexColor(0xa3be8c),
"yellow": tcell.NewHexColor(0xebcb8b),
"blue": tcell.NewHexColor(0x81a1c1),
"purple": tcell.NewHexColor(0xb48ead),
"cyan": tcell.NewHexColor(0x8fbcbb),
"orange": tcell.NewHexColor(0xd08770),
},
}
)

92
internal/color/control.go Normal file
View File

@ -0,0 +1,92 @@
package color
import (
"github.com/gdamore/tcell/v2"
)
type windowStyle struct {
borderColor string
}
type Style struct {
src windowStyle
dst windowStyle
backgroundColor string
foregroundColor string
selectedColor string
prefixColor string
labelColor string
pressColor string
highLightColor string
Theme string
Transparent bool
}
func NewStyle() *Style {
return &Style{
backgroundColor: "bg",
foregroundColor: "fg",
selectedColor: "gray",
prefixColor: "cyan",
labelColor: "yellow",
pressColor: "purple",
highLightColor: "orange",
}
}
func (s Style) BackgroundColor() tcell.Color {
if s.Transparent {
return tcell.ColorDefault
}
return themes[s.Theme][s.backgroundColor]
}
func (s Style) ForegroundColor() tcell.Color {
return themes[s.Theme][s.foregroundColor]
}
func (s Style) SelectedColor() tcell.Color {
return themes[s.Theme][s.selectedColor]
}
func (s Style) PrefixColor() tcell.Color {
return themes[s.Theme][s.prefixColor]
}
func (s Style) LabelColor() tcell.Color {
return themes[s.Theme][s.labelColor]
}
func (s Style) PressColor() tcell.Color {
return themes[s.Theme][s.pressColor]
}
func (s Style) HighLightColor() tcell.Color {
return themes[s.Theme][s.highLightColor]
}
func (s Style) SrcBorderColor() tcell.Color {
return themes[s.Theme][s.src.borderColor]
}
func (s Style) DstBorderColor() tcell.Color {
return themes[s.Theme][s.dst.borderColor]
}
func (s Style) SrcBorderStr() string {
return s.src.borderColor
}
func (s Style) DstBorderStr() string {
return s.dst.borderColor
}
func (s *Style) SetSrcBorderColor(color string) *Style {
s.src.borderColor = color
return s
}
func (s *Style) SetDstBorderColor(color string) *Style {
s.dst.borderColor = color
return s
}

View File

@ -1,4 +1,4 @@
package main
package translate
// https://cloud.google.com/translate/docs/languages
var (

View File

@ -0,0 +1,27 @@
package translate
type Lock struct {
Stop bool
threadCount int8
}
func NewLock() *Lock {
return &Lock{
Stop: true,
threadCount: 0,
}
}
func (l *Lock) Available() bool {
return l.Stop && l.threadCount == 0
}
func (l *Lock) Acquire() {
l.Stop = false
l.threadCount++
}
func (l *Lock) Release() {
l.Stop = true
l.threadCount--
}

View File

@ -1,4 +1,4 @@
package main
package translate
import (
"encoding/json"
@ -17,41 +17,15 @@ const (
soundURL = "https://translate.google.com.vn/translate_tts?ie=UTF-8&q=%s&tl=%s&client=tw-ob"
)
type Lock struct {
stop bool
threadCount int8
}
func NewLock() *Lock {
return &Lock{
stop: true,
threadCount: 0,
}
}
func (l *Lock) Available() bool {
return l.stop && l.threadCount == 0
}
func (l *Lock) Acquire() {
l.stop = false
l.threadCount++
}
func (l *Lock) Release() {
l.stop = true
l.threadCount--
}
type Translator struct {
srcLang string
dstLang string
soundLock *Lock
SrcLang string
DstLang string
SoundLock *Lock
}
func NewTranslator() *Translator {
return &Translator{
soundLock: NewLock(),
SoundLock: NewLock(),
}
}
@ -61,8 +35,8 @@ func (t *Translator) Translate(message string) (string, error) {
urlStr := fmt.Sprintf(
textURL,
LangCode[t.srcLang],
LangCode[t.dstLang],
LangCode[t.SrcLang],
LangCode[t.DstLang],
url.QueryEscape(message),
)
res, err := http.Get(urlStr)
@ -98,35 +72,35 @@ func (t *Translator) PlaySound(lang string, message string) error {
)
res, err := http.Get(urlStr)
if err != nil {
t.soundLock.Release()
t.SoundLock.Release()
return err
}
decoder, err := mp3.NewDecoder(res.Body)
if err != nil {
t.soundLock.Release()
t.SoundLock.Release()
return err
}
otoCtx, readyChan, err := oto.NewContext(decoder.SampleRate(), 2, 2)
if err != nil {
t.soundLock.Release()
t.SoundLock.Release()
return err
}
<-readyChan
player := otoCtx.NewPlayer(decoder)
player.Play()
for player.IsPlaying() {
if t.soundLock.stop {
t.soundLock.Release()
if t.SoundLock.Stop {
t.SoundLock.Release()
return nil
} else {
time.Sleep(time.Millisecond)
}
}
if err = player.Close(); err != nil {
t.soundLock.Release()
t.SoundLock.Release()
return err
}
t.soundLock.Release()
t.SoundLock.Release()
return nil
}

37
internal/ui/cycle.go Normal file
View File

@ -0,0 +1,37 @@
package ui
import (
"github.com/rivo/tview"
)
type UICycle struct {
widget []tview.Primitive
index int
len int
}
func NewUICycle(widgets ...tview.Primitive) *UICycle {
var w []tview.Primitive
for _, widget := range widgets {
w = append(w, widget)
}
return &UICycle{
widget: w,
index: 0,
len: len(w),
}
}
func (ui *UICycle) Increase() {
ui.index = (ui.index + 1) % ui.len
}
func (ui *UICycle) Decrease() {
ui.index = ((ui.index-1)%ui.len + ui.len) % ui.len
}
func (ui *UICycle) GetCurrentUI() tview.Primitive {
return ui.widget[ui.index]
}

14
main.go
View File

@ -3,27 +3,30 @@ package main
import (
"github.com/rivo/tview"
"github.com/spf13/viper"
"gtt/internal/color"
"gtt/internal/translate"
"gtt/internal/ui"
)
var (
// Translate
translator = NewTranslator()
translator = translate.NewTranslator()
// UI
app = tview.NewApplication()
srcInput = tview.NewTextArea()
dstOutput = tview.NewTextView()
srcLangDropDown = tview.NewDropDown()
dstLangDropDown = tview.NewDropDown()
langCycle = NewUICycle(srcLangDropDown, dstLangDropDown)
langCycle = ui.NewUICycle(srcLangDropDown, dstLangDropDown)
themeDropDown = tview.NewDropDown()
transparentDropDown = tview.NewDropDown()
srcBorderDropDown = tview.NewDropDown()
dstBorderDropDown = tview.NewDropDown()
styleCycle = NewUICycle(themeDropDown, transparentDropDown, srcBorderDropDown, dstBorderDropDown)
styleCycle = ui.NewUICycle(themeDropDown, transparentDropDown, srcBorderDropDown, dstBorderDropDown)
keyMapMenu = tview.NewTextView()
langButton = tview.NewButton("(1)Language")
styleButton = tview.NewButton("(2)Style")
keyMapButton = tview.NewButton("(3)KeyMap")
keyMapButton = tview.NewButton("(3)KeyMap")
translateWindow = tview.NewFlex()
langWindow = tview.NewFlex()
styleWindow = tview.NewFlex()
@ -31,7 +34,7 @@ var (
mainPage = tview.NewPages()
// settings
config = viper.New()
style = NewStyle()
style = color.NewStyle()
)
func main() {
@ -49,5 +52,6 @@ func main() {
panic(err)
}
// Check if config need to update
defer updateConfig()
}

130
ui.go
View File

@ -4,41 +4,11 @@ import (
"fmt"
"github.com/gdamore/tcell/v2"
"github.com/rivo/tview"
"gtt/internal/color"
"gtt/internal/translate"
"strconv"
)
type UICycle struct {
widget []tview.Primitive
index int
len int
}
func NewUICycle(widgets ...tview.Primitive) *UICycle {
var w []tview.Primitive
for _, widget := range widgets {
w = append(w, widget)
}
return &UICycle{
widget: w,
index: 0,
len: len(w),
}
}
func (ui *UICycle) Increase() {
ui.index = (ui.index + 1) % ui.len
}
func (ui *UICycle) Decrease() {
ui.index = ((ui.index-1)%ui.len + ui.len) % ui.len
}
func (ui *UICycle) GetCurrentUI() tview.Primitive {
return ui.widget[ui.index]
}
const (
keyMapText string = `[#%[1]s]<C-c>[-]
Exit program.
@ -197,12 +167,12 @@ func updateAllColor() {
// Update title and option
func updateTitle() {
srcInput.SetTitle(translator.srcLang)
dstOutput.SetTitle(translator.dstLang)
srcLangDropDown.SetCurrentOption(IndexOf(translator.srcLang, Lang))
srcLangDropDown.SetTitle(translator.srcLang)
dstLangDropDown.SetCurrentOption(IndexOf(translator.dstLang, Lang))
dstLangDropDown.SetTitle(translator.dstLang)
srcInput.SetTitle(translator.SrcLang)
dstOutput.SetTitle(translator.DstLang)
srcLangDropDown.SetCurrentOption(IndexOf(translator.SrcLang, translate.Lang))
srcLangDropDown.SetTitle(translator.SrcLang)
dstLangDropDown.SetCurrentOption(IndexOf(translator.DstLang, translate.Lang))
dstLangDropDown.SetTitle(translator.DstLang)
}
func attachButton() *tview.Flex {
@ -223,25 +193,25 @@ func uiInit() {
// dropdown
srcLangDropDown.SetBorder(true)
srcLangDropDown.SetOptions(Lang, nil)
srcLangDropDown.SetOptions(translate.Lang, nil)
dstLangDropDown.SetBorder(true)
dstLangDropDown.SetOptions(Lang, nil)
dstLangDropDown.SetOptions(translate.Lang, nil)
themeDropDown.SetLabel("Theme: ").
SetOptions(AllTheme, nil).
SetCurrentOption(IndexOf(style.Theme, AllTheme))
SetOptions(color.AllTheme, nil).
SetCurrentOption(IndexOf(style.Theme, color.AllTheme))
transparentDropDown.SetLabel("Transparent: ").
SetOptions([]string{"true", "false"}, nil).
SetCurrentOption(
IndexOf(strconv.FormatBool(style.Transparent),
[]string{"true", "false"}))
srcBorderDropDown.SetLabel("Border Color: ").
SetOptions(Palette, nil).
SetCurrentOption(IndexOf(style.SrcBorderStr(), Palette))
SetOptions(color.Palette, nil).
SetCurrentOption(IndexOf(style.SrcBorderStr(), color.Palette))
srcBorderDropDown.SetBorder(true).
SetTitle("Source")
dstBorderDropDown.SetLabel("Border Color: ").
SetOptions(Palette, nil).
SetCurrentOption(IndexOf(style.DstBorderStr(), Palette))
SetOptions(color.Palette, nil).
SetCurrentOption(IndexOf(style.DstBorderStr(), color.Palette))
dstBorderDropDown.SetBorder(true).
SetTitle("Destination")
@ -303,19 +273,19 @@ func uiInit() {
// handler
mainPage.SetInputCapture(mainPageHandler)
translateWindow.SetInputCapture(translatePageHandler)
langWindow.SetInputCapture(popOutWindowHandler)
styleWindow.SetInputCapture(popOutWindowHandler)
keyMapWindow.SetInputCapture(popOutWindowHandler)
translateWindow.SetInputCapture(translatePageHandler)
srcLangDropDown.SetDoneFunc(langDropDownHandler).
SetSelectedFunc(func(text string, index int) {
translator.srcLang = text
translator.SrcLang = text
srcInput.SetTitle(text)
srcLangDropDown.SetTitle(text)
})
dstLangDropDown.SetDoneFunc(langDropDownHandler).
SetSelectedFunc(func(text string, index int) {
translator.dstLang = text
translator.DstLang = text
dstOutput.SetTitle(text)
dstLangDropDown.SetTitle(text)
})
@ -380,29 +350,6 @@ func mainPageHandler(event *tcell.EventKey) *tcell.EventKey {
return event
}
func popOutWindowHandler(event *tcell.EventKey) *tcell.EventKey {
ch := event.Rune()
switch ch {
case '1':
mainPage.HidePage("stylePage")
mainPage.HidePage("keyMapPage")
mainPage.ShowPage("langPage")
app.SetFocus(langCycle.GetCurrentUI())
case '2':
mainPage.HidePage("langPage")
mainPage.HidePage("keyMapPage")
mainPage.ShowPage("stylePage")
app.SetFocus(styleCycle.GetCurrentUI())
case '3':
mainPage.HidePage("langPage")
mainPage.HidePage("stylePage")
mainPage.ShowPage("keyMapPage")
}
return event
}
func translatePageHandler(event *tcell.EventKey) *tcell.EventKey {
key := event.Key()
@ -424,7 +371,7 @@ func translatePageHandler(event *tcell.EventKey) *tcell.EventKey {
case tcell.KeyCtrlQ:
srcInput.SetText("", true)
case tcell.KeyCtrlS:
translator.srcLang, translator.dstLang = translator.dstLang, translator.srcLang
translator.SrcLang, translator.DstLang = translator.DstLang, translator.SrcLang
updateTitle()
srcText := srcInput.GetText()
dstText := dstOutput.GetText(false)
@ -437,13 +384,13 @@ func translatePageHandler(event *tcell.EventKey) *tcell.EventKey {
dstOutput.SetText(srcText)
case tcell.KeyCtrlO:
// Play source sound
if translator.soundLock.Available() {
if translator.SoundLock.Available() {
message := srcInput.GetText()
if len(message) > 0 {
// Only play when message exist
translator.soundLock.Acquire()
translator.SoundLock.Acquire()
go func() {
err := translator.PlaySound(translator.srcLang, message)
err := translator.PlaySound(translator.SrcLang, message)
if err != nil {
srcInput.SetText(err.Error(), true)
}
@ -453,13 +400,13 @@ func translatePageHandler(event *tcell.EventKey) *tcell.EventKey {
}
case tcell.KeyCtrlP:
// Play destination sound
if translator.soundLock.Available() {
if translator.SoundLock.Available() {
message := dstOutput.GetText(false)
if len(message) > 0 {
// Only play when message exist
translator.soundLock.Acquire()
translator.SoundLock.Acquire()
go func() {
err := translator.PlaySound(translator.dstLang, message)
err := translator.PlaySound(translator.DstLang, message)
if err != nil {
dstOutput.SetText(err.Error())
}
@ -468,7 +415,30 @@ func translatePageHandler(event *tcell.EventKey) *tcell.EventKey {
}
case tcell.KeyCtrlX:
// Stop play sound
translator.soundLock.stop = true
translator.SoundLock.Stop = true
}
return event
}
func popOutWindowHandler(event *tcell.EventKey) *tcell.EventKey {
ch := event.Rune()
switch ch {
case '1':
mainPage.HidePage("stylePage")
mainPage.HidePage("keyMapPage")
mainPage.ShowPage("langPage")
app.SetFocus(langCycle.GetCurrentUI())
case '2':
mainPage.HidePage("langPage")
mainPage.HidePage("keyMapPage")
mainPage.ShowPage("stylePage")
app.SetFocus(styleCycle.GetCurrentUI())
case '3':
mainPage.HidePage("langPage")
mainPage.HidePage("stylePage")
mainPage.ShowPage("keyMapPage")
}
return event