Add Zukitchi widget with animated terminal pet and update README for new features

This commit is contained in:
Arindy 2025-12-30 23:51:54 +01:00
parent dfbc6066c9
commit 7a846ee660
5 changed files with 150 additions and 1 deletions

View File

@ -11,6 +11,9 @@ ArinDash is a customizable terminal dashboard (TUI) written in Go, powered by [`
- **HTTP Prober**: Check the availability and status codes of your favorite websites. - **HTTP Prober**: Check the availability and status codes of your favorite websites.
- **Network Device Monitoring**: Track which devices are online in your local network. - **Network Device Monitoring**: Track which devices are online in your local network.
- **WiFi QR Code**: Display a QR code for easy WiFi connection sharing. - **WiFi QR Code**: Display a QR code for easy WiFi connection sharing.
- **NINA Warnings**: Stay informed about emergency warnings in Germany via the NINA-Service.
- **News**: Get the latest news headlines from various sources via News API.
- **Zukitchi**: A cute animated terminal pet/sprite to keep you company.
- **Interactive TUI**: Built with `termdash` for a responsive and visually appealing terminal interface. - **Interactive TUI**: Built with `termdash` for a responsive and visually appealing terminal interface.
## Prerequisites ## Prerequisites
@ -45,6 +48,8 @@ ArinDash uses a `config.toml` file for its settings. A template is provided as `
- **Pi-hole**: Set your host and API password. - **Pi-hole**: Set your host and API password.
- **WiFi**: Configure your SSID and password for the QR code widget. - **WiFi**: Configure your SSID and password for the QR code widget.
- **Weather**: Provide your OpenWeatherMap API key and Location ID. You can find your Location ID in the `city.list.json.gz` from [OpenWeatherMap bulk data](http://bulk.openweathermap.org/sample/). - **Weather**: Provide your OpenWeatherMap API key and Location ID. You can find your Location ID in the `city.list.json.gz` from [OpenWeatherMap bulk data](http://bulk.openweathermap.org/sample/).
- **NINA Warnings**: Set your `gebietsCode` for the area you want to monitor.
- **News**: Provide your News API key and preferred sources.
3. Customize widgets: 3. Customize widgets:
- **Websites**: Copy `websites_template.json` to `websites.json` and update it with the URLs and icons you want to monitor. - **Websites**: Copy `websites_template.json` to `websites.json` and update it with the URLs and icons you want to monitor.
@ -60,6 +65,7 @@ go run main.go
### Controls ### Controls
- **Esc / Ctrl+C**: Exit the application. - **Esc / Ctrl+C**: Exit the application.
- **Left / Right Arrow Keys**: Navigate through news articles (in the News widget).
## Project Structure ## Project Structure

View File

@ -46,6 +46,7 @@ func initWidgets(ctx context.Context, term *tcell.Terminal) {
widgets.New("PiHoleBlocked", widgets.PiholeBlocked()), widgets.New("PiHoleBlocked", widgets.PiholeBlocked()),
widgets.New("NinaWarnings", widgets.NinaWarnings()), widgets.New("NinaWarnings", widgets.NinaWarnings()),
widgets.New("News", widgets.News()), widgets.New("News", widgets.News()),
widgets.New("Zukitchi", widgets.Zukitchi()),
) )
} }
@ -168,9 +169,11 @@ func layout() []container.Option {
grid.ColWidthPerc(35, grid.ColWidthPerc(35,
grid.RowHeightFixed(20, grid.RowHeightFixed(20,
grid.Widget(widgets.Get["empty"], grid.Widget(widgets.Get["Zukitchi"],
container.Border(linestyle.Light), container.Border(linestyle.Light),
container.BorderColor(cell.ColorWhite), container.BorderColor(cell.ColorWhite),
container.PaddingTop(1),
container.PaddingLeft(1),
), ),
), ),
grid.RowHeightFixed(24, grid.RowHeightFixed(24,

60
widgets/zukitchi.go Normal file
View File

@ -0,0 +1,60 @@
package widgets
import (
"ArinDash/util"
"ArinDash/widgets/zukitchi"
"context"
"time"
"github.com/mum4k/termdash/cell"
"github.com/mum4k/termdash/terminal/terminalapi"
"github.com/mum4k/termdash/widgetapi"
"github.com/mum4k/termdash/widgets/text"
)
type ZukitchiOptions struct {
}
func Zukitchi() ZukitchiOptions {
widgetOptions["ZukitchiOptions"] = createZukitchi
return ZukitchiOptions{}
}
var mood = make([]string, 0)
var frames = 1
var frame = 0
var lastFrame = time.Now()
func createZukitchi(ctx context.Context, _ terminalapi.Terminal, _ interface{}) widgetapi.Widget {
widget := util.PanicOnErrorWithResult(text.New())
changeMood("sleep")
go util.Periodic(ctx, util.RedrawInterval, func() error {
return draw(widget)
})
return widget
}
func changeMood(moodToChangeTo string) {
switch moodToChangeTo {
case "sleep":
mood = zukitchi.Sleep(0)
break
}
frames = len(mood)
frame = 0
}
func draw(widget *text.Text) error {
if time.Since(lastFrame) < 1*time.Second {
return nil
}
widget.Reset()
if err := widget.Write(mood[frame], text.WriteCellOpts(cell.FgColor(cell.ColorWhite))); err != nil {
return err
}
frame = (frame + 1) % frames
lastFrame = time.Now()
return nil
}

View File

@ -0,0 +1,79 @@
package zukitchi
import "strings"
func Sleep(position int) []string {
return compileFrames(position, sleep0, sleep1)
}
func compileFrames(position int, idle ...string) []string {
var result = make([]string, len(idle))
for i, frame := range idle {
result[i] = cutFirstAndListLineAndMove(frame, position)
}
return result
}
func cutFirstAndListLineAndMove(frame string, position int) string {
position = position + 17
if position < 0 {
position = 0
}
if position > 35 {
position = 35
}
lines := strings.Split(frame, "\n")
result := make([]string, 0, len(lines))
for _, line := range lines {
result = append(result, strings.Repeat(" ", position)+line)
}
return strings.Join(result[1:len(result)-1], "\n")
}
//<editor-fold desc="Sprites">
// j
// k ▄
// i ▀
// l █
const sleep0 = `
`
const sleep1 = `
`
//</editor-fold>

1
widgets/zukitchi/main.go Normal file
View File

@ -0,0 +1 @@
package zukitchi