package main import ( "fmt" "os" "time" "github.com/charmbracelet/bubbles/table" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" "code.gitea.io/sdk/gitea" ) // getTimeLogs gets every single time log possible. func getTimeLogs(since time.Time, on_process_repo func(repo gitea.Repository, took time.Duration)) []gitea.TrackedTime { var times []gitea.TrackedTime for _, client := range Servers { page := 1 user, _, err := client.GetMyUserInfo() if err != nil { panic(err) } for { repos, _, err := client.ListMyRepos( gitea.ListReposOptions{ ListOptions: gitea.ListOptions{ Page: page, PageSize: 10, }, }, ) if err != nil { panic(err) } else if len(repos) == 0 { break } for _, repo := range repos { if repo.Fork { continue } duration_start := time.Now() repo_times, _, _ := client.ListRepoTrackedTimes( repo.Owner.UserName, repo.Name, gitea.ListTrackedTimesOptions{ User: user.UserName, Since: since, }, ) for _, t := range repo_times { times = append(times, *t) } on_process_repo(*repo, time.Now().Sub(duration_start)) } page++ } } return times } var textStyle = lipgloss.NewStyle().Foreground(colors.surface[2]) type timesviewer struct { table table.Model length int total_time time.Duration } func (m timesviewer) Init() tea.Cmd { return nil } func (m timesviewer) Update(msg tea.Msg) (tea.Model, tea.Cmd) { var cmd tea.Cmd switch msg := msg.(type) { case tea.KeyMsg: switch msg.String() { case "esc": if m.table.Focused() { m.table.Blur() } else { m.table.Focus() } case "q", "ctrl+c": return m, tea.Quit } } m.table, cmd = m.table.Update(msg) return m, cmd } func (m timesviewer) View() string { var totalTextStyle = lipgloss.NewStyle(). Foreground(colors.overlay[0]). Bold(true) return m.table.View() + textStyle.Render("\nUse Up and Down arrows to navigate") + totalTextStyle.Render(fmt.Sprintf("\nTotal - %s\n", m.total_time.String())) } func times() { p := tea.NewProgram(initialIndicator("Fetching time logs...")) go func() { if _, err := p.Run(); err != nil { fmt.Println(err) os.Exit(1) } }() since := time.Now().AddDate(0, 0, -7) times := getTimeLogs(since, func(repo gitea.Repository, took time.Duration) { p.Send(IndicatorInfo{ info: fmt.Sprintf("%s / %s", repo.Owner.UserName, repo.Name), duration: took, }) }) p.Send(IndicatorInfo{ info: "Done!", quitting: true, }) p.Quit() var total_time time.Duration columns := []table.Column{ {Title: "User", Width: 10}, {Title: "Time", Width: 8}, {Title: "Created at", Width: 15}, } rows := []table.Row{} for _, t := range times { dur, err := time.ParseDuration(fmt.Sprint(t.Time) + "s") if err != nil { panic(err) } rows = append(rows, table.Row{ t.UserName, dur.String(), t.Created.String(), }) total_time += dur } tv := timesviewer{ total_time: total_time, length: 50, } tab := table.New( table.WithColumns(columns), table.WithRows(rows), table.WithFocused(true), table.WithHeight(10), table.WithWidth(tv.length), ) s := table.DefaultStyles() s.Header = s.Header. Foreground(colors.overlay[0]). BorderStyle(lipgloss.DoubleBorder()). BorderForeground(colors.green). BorderBottom(true). Bold(false) s.Selected = s.Selected. Foreground(colors.surface[1]). Background(colors.green). Bold(false) tab.SetStyles(s) tv.table = tab if _, err := tea.NewProgram(tv).Run(); err != nil { fmt.Println("Error running program:", err) os.Exit(1) } }