Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: new list #64

Merged
merged 12 commits into from
Apr 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/fork-cleaner/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func main() {
return cli.Exit("missing github token", 1)
}

p := tea.NewProgram(ui.NewInitialModel(client, login), tea.WithAltScreen())
p := tea.NewProgram(ui.NewAppModel(client, login), tea.WithAltScreen())
if _, err = p.Run(); err != nil {
return cli.Exit(err.Error(), 1)
}
Expand Down
7 changes: 5 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@ module github.com/caarlos0/fork-cleaner/v2
go 1.20

require (
github.com/caarlos0/timea.go v1.0.2
github.com/charmbracelet/bubbles v0.15.0
github.com/charmbracelet/bubbletea v0.23.2
github.com/charmbracelet/lipgloss v0.7.1
github.com/google/go-github/v50 v50.2.0
github.com/muesli/termenv v0.15.1
github.com/urfave/cli/v2 v2.25.1
golang.org/x/oauth2 v0.6.0
)

require (
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 // indirect
github.com/atotto/clipboard v0.1.4 // indirect
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/charmbracelet/lipgloss v0.7.1 // indirect
github.com/cloudflare/circl v1.1.0 // indirect
github.com/containerd/console v1.0.3 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
Expand All @@ -27,8 +28,10 @@ require (
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/muesli/reflow v0.3.0 // indirect
github.com/muesli/termenv v0.15.1 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sahilm/fuzzy v0.1.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
golang.org/x/crypto v0.7.0 // indirect
golang.org/x/net v0.8.0 // indirect
Expand Down
7 changes: 7 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA=
github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g=
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
github.com/aymanbagabas/go-osc52 v1.0.3/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4=
github.com/aymanbagabas/go-osc52 v1.2.1/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4=
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/caarlos0/timea.go v1.0.2 h1:TTwrLOvn71SnLSq613h9Q9pdujOzrXXxMinNEqmpNso=
github.com/caarlos0/timea.go v1.0.2/go.mod h1:MyDHBpPAvgjxyCJDk1B/LWhBVCWoTrVhyZZ+rjAcxWA=
github.com/charmbracelet/bubbles v0.15.0 h1:c5vZ3woHV5W2b8YZI1q7v4ZNQaPetfHuoHzx+56Z6TI=
github.com/charmbracelet/bubbles v0.15.0/go.mod h1:Y7gSFbBzlMpUDR/XM9MhZI374Q+1p1kluf1uLl8iK74=
github.com/charmbracelet/bubbletea v0.23.1/go.mod h1:JAfGK/3/pPKHTnAS8JIE2u9f61BjWTQY57RbT25aMXU=
Expand All @@ -32,9 +35,12 @@ github.com/google/go-github/v50 v50.2.0 h1:j2FyongEHlO9nxXLc+LP3wuBSVU9mVxfpdYUe
github.com/google/go-github/v50 v50.2.0/go.mod h1:VBY8FB6yPIjrtKhozXv4FQupxKLS6H4m6xFZlT43q8Q=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
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/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE=
github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
Expand Down Expand Up @@ -66,6 +72,7 @@ github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI=
github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
github.com/urfave/cli/v2 v2.25.1 h1:zw8dSP7ghX0Gmm8vugrs6q9Ku0wzweqPyshy+syu9Gw=
github.com/urfave/cli/v2 v2.25.1/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
Expand Down
138 changes: 138 additions & 0 deletions internal/ui/app.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package ui

import (
"log"

"github.com/charmbracelet/bubbles/key"
"github.com/charmbracelet/bubbles/list"
"github.com/charmbracelet/bubbles/spinner"
tea "github.com/charmbracelet/bubbletea"
"github.com/google/go-github/v50/github"
)

// AppModel is the UI when the CLI starts, basically loading the repos.
type AppModel struct {
err error
login string
client *github.Client
list list.Model
}

// NewAppModel creates a new AppModel with required fields.
func NewAppModel(client *github.Client, login string) AppModel {
list := list.New([]list.Item{}, list.NewDefaultDelegate(), 0, 0)
list.Title = "Fork Cleaner"
list.SetSpinner(spinner.MiniDot)
list.AdditionalShortHelpKeys = func() []key.Binding {
return []key.Binding{
keySelectToggle,
keyDeletedSelected,
}
}
list.AdditionalFullHelpKeys = func() []key.Binding {
return []key.Binding{
keySelectAll,
keySelectNone,
}
}

return AppModel{
client: client,
login: login,
list: list,
}
}

func (m AppModel) Init() tea.Cmd {
return tea.Batch(enqueueGetReposCmd, m.list.StartSpinner())
}

func (m AppModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmds []tea.Cmd
var cmd tea.Cmd

switch msg := msg.(type) {
case tea.WindowSizeMsg:
log.Println("tea.WindowSizeMsg")
top, right, bottom, left := listStyle.GetMargin()
m.list.SetSize(msg.Width-left-right, msg.Height-top-bottom)
case errMsg:
log.Println("errMsg")
m.err = msg.error
case getRepoListMsg:
log.Println("getRepoListMsg")
cmds = append(cmds, m.list.StartSpinner(), getReposCmd(m.client, m.login))
case gotRepoListMsg:
log.Println("gotRepoListMsg")
m.list.StopSpinner()
cmds = append(cmds, m.list.SetItems(reposToItems(msg.repos)))
case reposDeletedMsg:
log.Println("reposDeletedMsg")
cmds = append(cmds, m.list.StartSpinner(), enqueueGetReposCmd)
case requestDeleteSelectedReposMsg:
log.Println("requestDeleteSelectedReposMsg")
selected, unselected := splitBySelection(m.list.Items())
cmds = append(
cmds,
m.list.SetItems(reposToItems(unselected)),
deleteReposCmd(m.client, selected),
)

case tea.KeyMsg:
if m.list.SettingFilter() {
break
}

if key.Matches(msg, keySelectAll) {
log.Println("tea.KeyMsg -> selectAll")
cmds = append(cmds, m.changeSelect(true)...)
}

if key.Matches(msg, keySelectNone) {
log.Println("tea.KeyMsg -> selectNone")
cmds = append(cmds, m.changeSelect(false)...)
}

if key.Matches(msg, keySelectToggle) {
log.Println("tea.KeyMsg -> selectToggle")
cmds = append(cmds, m.toggleSelection())
}

if key.Matches(msg, keyDeletedSelected) {
log.Println("tea.KeyMsg -> deleteSelected")
cmds = append(cmds, m.list.StartSpinner(), requestDeleteReposCmd)
}
}

m.list, cmd = m.list.Update(msg)
cmds = append(cmds, cmd)
return m, tea.Batch(cmds...)
}

func (m AppModel) View() string {
if m.err != nil {
return errorStyle.Bold(true).Render("Error gathering the repository list") +
"\n" +
errorStyle.Render(m.err.Error())
}
return m.list.View()
}

func (m AppModel) toggleSelection() tea.Cmd {
idx := m.list.Index()
item := m.list.SelectedItem().(item)
item.selected = !item.selected
m.list.RemoveItem(idx)
return m.list.InsertItem(idx, item)
}

func (m AppModel) changeSelect(selected bool) []tea.Cmd {
var cmds []tea.Cmd
for idx, i := range m.list.Items() {
item := i.(item)
item.selected = selected
m.list.RemoveItem(idx)
cmds = append(cmds, m.list.InsertItem(idx, item))
}
return cmds
}
44 changes: 44 additions & 0 deletions internal/ui/commands.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package ui

import (
"context"
"log"
"strings"

forkcleaner "github.com/caarlos0/fork-cleaner/v2"
tea "github.com/charmbracelet/bubbletea"
"github.com/google/go-github/v50/github"
)

func requestDeleteReposCmd() tea.Msg {
return requestDeleteSelectedReposMsg{}
}

func deleteReposCmd(client *github.Client, repos []*forkcleaner.RepositoryWithDetails) tea.Cmd {
return func() tea.Msg {
var names []string
for _, r := range repos {
names = append(names, r.Name)
}
log.Println("deleteReposCmd", strings.Join(names, ", "))
if err := forkcleaner.Delete(context.Background(), client, repos); err != nil {
return errMsg{err}
}
return reposDeletedMsg{}
}
}

func enqueueGetReposCmd() tea.Msg {
return getRepoListMsg{}
}

func getReposCmd(client *github.Client, login string) tea.Cmd {
return func() tea.Msg {
log.Println("getReposCmd")
repos, err := forkcleaner.FindAllForks(context.Background(), client, login)
if err != nil {
return errMsg{err}
}
return gotRepoListMsg{repos}
}
}
60 changes: 0 additions & 60 deletions internal/ui/common.go

This file was deleted.

54 changes: 0 additions & 54 deletions internal/ui/deleted.go

This file was deleted.

Loading