Files
2026-11-01 22:01:32 -05:00

174 lines
4.7 KiB
Go

// Copyright (c) 2026 Storm Dragon
// SPDX-License-Identifier: GPL-3.0-or-later
package preferences
/*
#include <stdlib.h>
#include "native.h"
*/
import "C"
import (
"reflect"
"strings"
"unsafe"
"git.stormux.org/storm/cthulhu/internal/tentacle"
)
type tentacleRow struct {
key string
status tentacle.EntryStatus
installed bool
}
type tentaclePage struct {
snapshot *tentacle.Snapshot
rows []tentacleRow
origins []string
selectedKey string
}
func tentacle_rows(snapshot *tentacle.Snapshot, origin string) []tentacleRow {
if snapshot == nil {
return nil
}
var rows []tentacleRow
seen := make(map[string]bool)
repositoryIDs := make(map[string]string)
for _, repository := range snapshot.Repositories {
repositoryIDs[repository.URL] = repository.ID
}
for _, status := range snapshot.Entries {
entry := status.Entry
localID := entry.LocalID
if localID == "" {
localID = entry.ID
}
key := entry.Repository + "\x00" + entry.RepositoryID + "\x00" + localID
seen[key] = true
if origin == "" || entry.Repository == origin && entry.RepositoryID == repositoryIDs[origin] {
rows = append(rows, tentacleRow{key: key, status: status, installed: true})
}
}
for _, repository := range snapshot.Repositories {
if origin != "" && repository.URL != origin {
continue
}
for _, manifest := range repository.Tentacles {
key := repository.URL + "\x00" + repository.ID + "\x00" + manifest.ID
if seen[key] {
continue
}
status := tentacle.EntryStatus{
Entry: tentacle.Entry{ID: manifest.ID, LocalID: manifest.ID, Name: manifest.Name, Version: manifest.Version, Repository: repository.URL, RepositoryID: repository.ID},
State: "Available",
Message: manifest.Description,
}
rows = append(rows, tentacleRow{key: key, status: status})
}
}
return rows
}
func (page *tentaclePage) selected() *tentacleRow {
row := int(C.prefs_tentacle_selected())
if row < 0 || row >= len(page.rows) {
return nil
}
return &page.rows[row]
}
func (page *tentaclePage) origin() string {
index := int(C.prefs_tentacle_repository_selected()) - 1
if index < 0 || index >= len(page.origins) {
return ""
}
return page.origins[index]
}
func (page *tentaclePage) controls() {
selected := page.selected()
installed, enabled := false, false
if selected != nil {
installed, enabled = selected.installed, selected.status.Entry.Enabled
}
available := page.snapshot != nil && !page.snapshot.Suppressed && page.snapshot.Message == ""
C.prefs_tentacle_controls(boolean(available), boolean(installed), boolean(enabled), boolean(page.origin() != ""))
}
func (page *tentaclePage) render() {
page.rows = tentacle_rows(page.snapshot, page.origin())
C.prefs_tentacles_clear()
selectedRow := -1
for index, row := range page.rows {
entry := row.status.Entry
name := entry.Name
if name == "" {
name = entry.ID
}
repository := tentacle.RepositoryLabel(entry.Repository)
if entry.Repository == "" {
repository = "Local development"
}
texts := []*C.char{C.CString(name), C.CString(row.status.State), C.CString(entry.Version), C.CString(repository), C.CString(row.status.Message), C.CString(strings.Join(row.status.Shortcuts, "; "))}
C.prefs_tentacle_append(boolean(entry.Enabled), texts[0], texts[1], texts[2], texts[3], texts[4], texts[5])
for _, text := range texts {
C.free(unsafe.Pointer(text))
}
if row.key == page.selectedKey {
selectedRow = index
}
}
C.prefs_tentacle_select(C.int(selectedRow))
page.controls()
}
func (page *tentaclePage) populate(snapshot *tentacle.Snapshot) {
if selected := page.selected(); selected != nil {
page.selectedKey = selected.key
}
origin := page.origin()
var origins []string
if snapshot != nil {
for _, repository := range snapshot.Repositories {
origins = append(origins, repository.URL)
}
}
if !reflect.DeepEqual(page.origins, origins) {
C.prefs_tentacle_repositories_clear()
selectedPage := 0
labels := make(map[string]int)
for _, value := range origins {
labels[tentacle.RepositoryLabel(value)]++
}
for index, value := range origins {
label := tentacle.RepositoryLabel(value)
if labels[label] > 1 {
label = value
}
text := C.CString(label)
C.prefs_tentacle_repository_append(text)
C.free(unsafe.Pointer(text))
if value == origin {
selectedPage = index + 1
}
}
page.origins = origins
C.prefs_tentacle_repository_select(C.int(selectedPage))
}
page.snapshot = snapshot
page.render()
}
func (page *tentaclePage) accepted(request *tentacle.ManagementRequest) {
if request.Action == "repository-add" {
id, empty := C.CString("tentacleRepositoryURL"), C.CString("")
C.prefs_entry_set(id, empty)
C.free(unsafe.Pointer(id))
C.free(unsafe.Pointer(empty))
}
page.controls()
}