mirror of
https://github.com/IllusionMan1212/ffui.git
synced 2026-10-24 18:12:35 +00:00
fix: UI for filtering config options
Also added vim-like movement (hjkl, g, shift+g) h -> left j -> down k -> up l -> right g -> Go to first config shift+g -> Go to last config
This commit is contained in:
@@ -41,7 +41,8 @@ type model struct {
|
||||
Quitting bool
|
||||
Cancelled bool
|
||||
Screen Screen
|
||||
Config map[int]Config
|
||||
Config []Config
|
||||
VisibleConfig []Config
|
||||
FocusIndex int
|
||||
ParsedConfig ParsedConfig
|
||||
DryRun bool
|
||||
@@ -54,12 +55,6 @@ func initialModel(fileInfo os.FileInfo, absolutePath string) *model {
|
||||
s.Spinner = spinner.Dot
|
||||
s.Style = lipgloss.NewStyle().Foreground(lipgloss.Color("205"))
|
||||
|
||||
cfg := make(map[int]Config)
|
||||
|
||||
for i := 0; i < len(Configs); i++ {
|
||||
cfg[i] = Configs[i]
|
||||
}
|
||||
|
||||
return &model{
|
||||
IsDirectory: fileInfo.IsDir(),
|
||||
CurrentFileName: fileInfo.Name(),
|
||||
@@ -72,12 +67,23 @@ func initialModel(fileInfo os.FileInfo, absolutePath string) *model {
|
||||
TotalProgressBar: progress.New(progress.WithDefaultGradient()),
|
||||
TotalProgress: 0.0,
|
||||
Quitting: false,
|
||||
Config: cfg,
|
||||
Config: Configs,
|
||||
VisibleConfig: getVisibleConfigs(Configs),
|
||||
ErrQuit: false,
|
||||
ErrQuitMessage: "",
|
||||
}
|
||||
}
|
||||
|
||||
func (m model) updateConfigFocusedOptions() {
|
||||
for _, visCfg := range m.VisibleConfig {
|
||||
for i := range m.Config {
|
||||
if m.Config[i].Name == visCfg.Name {
|
||||
m.Config[i].FocusedOption = visCfg.FocusedOption
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (m model) Init() tea.Cmd {
|
||||
return tea.Batch(m.Spinner.Tick, initCfg)
|
||||
}
|
||||
@@ -102,28 +108,34 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
return m, tea.Quit
|
||||
case "enter", " ":
|
||||
// parse config and switch to main screen if we're focused on the start button
|
||||
if m.FocusIndex == len(Configs) {
|
||||
if m.FocusIndex == len(m.VisibleConfig) {
|
||||
return m, m.parseConfig(false)
|
||||
}
|
||||
// parse config, print it and exit
|
||||
if m.FocusIndex == len(Configs)+1 {
|
||||
if m.FocusIndex == len(m.VisibleConfig)+1 {
|
||||
return m, m.parseConfig(true)
|
||||
}
|
||||
case "tab", "shift+tab", "up", "down":
|
||||
if key == "up" || key == "shift+tab" {
|
||||
case "g":
|
||||
m.FocusIndex = 0
|
||||
case "G":
|
||||
m.FocusIndex = len(m.VisibleConfig) + 1
|
||||
case "tab", "shift+tab", "up", "down", "j", "k":
|
||||
if key == "up" || key == "shift+tab" || key == "k" {
|
||||
m.FocusIndex--
|
||||
} else {
|
||||
m.FocusIndex++
|
||||
}
|
||||
|
||||
if m.FocusIndex >= len(Configs)+2 {
|
||||
if m.FocusIndex >= len(m.VisibleConfig)+2 {
|
||||
m.FocusIndex = 0
|
||||
} else if m.FocusIndex < 0 {
|
||||
m.FocusIndex = len(Configs) + 1
|
||||
m.FocusIndex = len(m.VisibleConfig) + 1
|
||||
}
|
||||
case "left", "right":
|
||||
if cfg, ok := m.Config[m.FocusIndex]; ok {
|
||||
if key == "right" {
|
||||
case "left", "right", "h", "l":
|
||||
// If we're not hovering a button
|
||||
if m.FocusIndex < len(m.VisibleConfig) {
|
||||
cfg := &m.VisibleConfig[m.FocusIndex]
|
||||
if key == "right" || key == "l" {
|
||||
cfg.FocusedOption++
|
||||
} else {
|
||||
cfg.FocusedOption--
|
||||
@@ -135,7 +147,8 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
cfg.FocusedOption = len(cfg.Opts) - 1
|
||||
}
|
||||
|
||||
m.Config[m.FocusIndex] = cfg
|
||||
m.updateConfigFocusedOptions()
|
||||
m.VisibleConfig = getVisibleConfigs(m.Config)
|
||||
}
|
||||
}
|
||||
case quitMsg:
|
||||
@@ -224,7 +237,7 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||
return m, cmd
|
||||
}
|
||||
|
||||
func parseConfig(cfg map[int]Config) ParsedConfig {
|
||||
func parseConfig(cfg []Config) ParsedConfig {
|
||||
vEncoder := find(cfg, "Video Encoder")
|
||||
aEncoder := find(cfg, "Audio Encoder")
|
||||
preset := find(cfg, "Preset")
|
||||
@@ -243,24 +256,11 @@ func parseConfig(cfg map[int]Config) ParsedConfig {
|
||||
func CfgScreenView(m model) string {
|
||||
view := ""
|
||||
|
||||
config := parseConfig(m.Config)
|
||||
|
||||
for i, cfg := range Configs {
|
||||
switch config.VideoEncoder {
|
||||
case "copy", "librav1e":
|
||||
if cfg.Name == "Preset" || cfg.Name == "Constant Rate Factor (CRF)" {
|
||||
continue
|
||||
}
|
||||
case "libvpx-vp9", "libsvtav1":
|
||||
if cfg.Name == "Preset" {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
for i, cfg := range m.VisibleConfig {
|
||||
opts := ""
|
||||
|
||||
for j, opt := range cfg.Opts {
|
||||
if m.Config[i].FocusedOption == j {
|
||||
if m.VisibleConfig[i].FocusedOption == j {
|
||||
opts += FocusedOption.Render(opt)
|
||||
} else {
|
||||
opts += BlurredOption.Render(opt)
|
||||
@@ -278,13 +278,13 @@ func CfgScreenView(m model) string {
|
||||
}
|
||||
}
|
||||
|
||||
if m.FocusIndex == len(Configs) {
|
||||
if m.FocusIndex == len(m.VisibleConfig) {
|
||||
view += FocusedStartButton
|
||||
} else {
|
||||
view += BlurredStartButton
|
||||
}
|
||||
|
||||
if m.FocusIndex == len(Configs)+1 {
|
||||
if m.FocusIndex == len(m.VisibleConfig)+1 {
|
||||
view += FocusedDryRunButton
|
||||
} else {
|
||||
view += BlurredDryRunButton
|
||||
|
||||
@@ -26,7 +26,7 @@ type ParsedConfig struct {
|
||||
CRF string
|
||||
}
|
||||
|
||||
func find(cfgs map[int]Config, name string) Config {
|
||||
func find(cfgs []Config, name string) Config {
|
||||
for _, cfg := range cfgs {
|
||||
if cfg.Name == name {
|
||||
return cfg
|
||||
@@ -36,3 +36,33 @@ func find(cfgs map[int]Config, name string) Config {
|
||||
err := fmt.Sprintf("Couldn't find requested cfg: %s", name)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
func filter(cfgs []Config, names ...string) []Config {
|
||||
filtered := make([]Config, 0)
|
||||
|
||||
cfgloop:
|
||||
for _, cfg := range cfgs {
|
||||
for _, name := range names {
|
||||
if cfg.Name == name {
|
||||
continue cfgloop
|
||||
}
|
||||
}
|
||||
|
||||
filtered = append(filtered, cfg)
|
||||
}
|
||||
|
||||
return filtered
|
||||
}
|
||||
|
||||
func getVisibleConfigs(cfgs []Config) []Config {
|
||||
parsed := parseConfig(cfgs)
|
||||
|
||||
switch parsed.VideoEncoder {
|
||||
case "copy", "librav1e":
|
||||
return filter(cfgs, "Preset", "Constant Rate Factor (CRF)")
|
||||
case "libvpx-vp9", "libsvtav1":
|
||||
return filter(cfgs, "Preset")
|
||||
}
|
||||
|
||||
return cfgs
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
package main
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestFilterConfigs(t *testing.T) {
|
||||
cfgs := filter(Configs, "Preset", "Constant Rate Factor (CRF)")
|
||||
|
||||
for _, cfg := range cfgs {
|
||||
if cfg.Name == "Preset" {
|
||||
t.Fatalf("Failed to filter out config \"Preset\"")
|
||||
} else if cfg.Name == "Constant Rate Factor (CRF)" {
|
||||
t.Fatalf("Failed to filter out config \"Constant Rate Factor (CRF)\"")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetVisibleConfigs(t *testing.T) {
|
||||
cfgs := getVisibleConfigs(Configs)
|
||||
|
||||
if len(cfgs) == len(Configs) {
|
||||
t.Fatalf("Failed to get the correct visible configs. Expected VisibleConfigs len: %v. Got %v", 4, len(cfgs))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user