summaryrefslogtreecommitdiff
path: root/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/themes
diff options
context:
space:
mode:
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/themes')
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/themes/manager.go258
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/themes/registry.go309
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/themes/search.go40
3 files changed, 0 insertions, 607 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/themes/manager.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/themes/manager.go
deleted file mode 100644
index 2ebe7ae..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/themes/manager.go
+++ /dev/null
@@ -1,258 +0,0 @@
-package themes
-
-import (
- "encoding/json"
- "fmt"
- "os"
- "path/filepath"
- "strings"
-
- "github.com/AvengeMedia/DankMaterialShell/core/internal/log"
- "github.com/spf13/afero"
-)
-
-type Manager struct {
- fs afero.Fs
- themesDir string
-}
-
-func NewManager() (*Manager, error) {
- return NewManagerWithFs(afero.NewOsFs())
-}
-
-func NewManagerWithFs(fs afero.Fs) (*Manager, error) {
- themesDir := getThemesDir()
- return &Manager{
- fs: fs,
- themesDir: themesDir,
- }, nil
-}
-
-func getThemesDir() string {
- configDir, err := os.UserConfigDir()
- if err != nil {
- log.Error("failed to get user config dir", "err", err)
- return ""
- }
- return filepath.Join(configDir, "DankMaterialShell", "themes")
-}
-
-func (m *Manager) IsInstalled(theme Theme) (bool, error) {
- path := m.getInstalledPath(theme.ID)
- exists, err := afero.Exists(m.fs, path)
- if err != nil {
- return false, err
- }
- return exists, nil
-}
-
-func (m *Manager) getInstalledDir(themeID string) string {
- return filepath.Join(m.themesDir, themeID)
-}
-
-func (m *Manager) getInstalledPath(themeID string) string {
- return filepath.Join(m.getInstalledDir(themeID), "theme.json")
-}
-
-func (m *Manager) Install(theme Theme, registryThemeDir string) error {
- themeDir := m.getInstalledDir(theme.ID)
-
- exists, err := afero.DirExists(m.fs, themeDir)
- if err != nil {
- return fmt.Errorf("failed to check if theme exists: %w", err)
- }
-
- if exists {
- return fmt.Errorf("theme already installed: %s", theme.Name)
- }
-
- if err := m.fs.MkdirAll(themeDir, 0o755); err != nil {
- return fmt.Errorf("failed to create theme directory: %w", err)
- }
-
- data, err := json.MarshalIndent(theme, "", " ")
- if err != nil {
- return fmt.Errorf("failed to marshal theme: %w", err)
- }
-
- themePath := filepath.Join(themeDir, "theme.json")
- if err := afero.WriteFile(m.fs, themePath, data, 0o644); err != nil {
- return fmt.Errorf("failed to write theme file: %w", err)
- }
-
- m.copyPreviewFiles(registryThemeDir, themeDir, theme)
- return nil
-}
-
-func (m *Manager) copyPreviewFiles(srcDir, dstDir string, theme Theme) {
- previews := []string{"preview-dark.svg", "preview-light.svg"}
-
- if theme.Variants != nil {
- for _, v := range theme.Variants.Options {
- previews = append(previews,
- fmt.Sprintf("preview-%s.svg", v.ID),
- fmt.Sprintf("preview-%s-dark.svg", v.ID),
- fmt.Sprintf("preview-%s-light.svg", v.ID),
- )
- }
- }
-
- for _, preview := range previews {
- srcPath := filepath.Join(srcDir, preview)
- if exists, _ := afero.Exists(m.fs, srcPath); !exists {
- continue
- }
- data, err := afero.ReadFile(m.fs, srcPath)
- if err != nil {
- continue
- }
- dstPath := filepath.Join(dstDir, preview)
- _ = afero.WriteFile(m.fs, dstPath, data, 0o644)
- }
-}
-
-func (m *Manager) InstallFromRegistry(registry *Registry, themeID string) error {
- theme, err := registry.Get(themeID)
- if err != nil {
- return err
- }
-
- registryThemeDir := registry.GetThemeDir(theme.SourceDir)
- return m.Install(*theme, registryThemeDir)
-}
-
-func (m *Manager) Update(theme Theme) error {
- themePath := m.getInstalledPath(theme.ID)
-
- exists, err := afero.Exists(m.fs, themePath)
- if err != nil {
- return fmt.Errorf("failed to check if theme exists: %w", err)
- }
-
- if !exists {
- return fmt.Errorf("theme not installed: %s", theme.Name)
- }
-
- data, err := json.MarshalIndent(theme, "", " ")
- if err != nil {
- return fmt.Errorf("failed to marshal theme: %w", err)
- }
-
- if err := afero.WriteFile(m.fs, themePath, data, 0o644); err != nil {
- return fmt.Errorf("failed to write theme file: %w", err)
- }
-
- return nil
-}
-
-func (m *Manager) Uninstall(theme Theme) error {
- return m.UninstallByID(theme.ID)
-}
-
-func (m *Manager) UninstallByID(themeID string) error {
- themeDir := m.getInstalledDir(themeID)
-
- exists, err := afero.DirExists(m.fs, themeDir)
- if err != nil {
- return fmt.Errorf("failed to check if theme exists: %w", err)
- }
-
- if !exists {
- return fmt.Errorf("theme not installed: %s", themeID)
- }
-
- if err := m.fs.RemoveAll(themeDir); err != nil {
- return fmt.Errorf("failed to remove theme: %w", err)
- }
-
- return nil
-}
-
-func (m *Manager) ListInstalled() ([]string, error) {
- exists, err := afero.DirExists(m.fs, m.themesDir)
- if err != nil {
- return nil, err
- }
-
- if !exists {
- return []string{}, nil
- }
-
- entries, err := afero.ReadDir(m.fs, m.themesDir)
- if err != nil {
- return nil, fmt.Errorf("failed to read themes directory: %w", err)
- }
-
- var installed []string
- for _, entry := range entries {
- if !entry.IsDir() {
- continue
- }
-
- themeID := entry.Name()
- themePath := filepath.Join(m.themesDir, themeID, "theme.json")
- if exists, _ := afero.Exists(m.fs, themePath); exists {
- installed = append(installed, themeID)
- }
- }
-
- return installed, nil
-}
-
-func (m *Manager) GetInstalledTheme(themeID string) (*Theme, error) {
- themePath := m.getInstalledPath(themeID)
-
- data, err := afero.ReadFile(m.fs, themePath)
- if err != nil {
- return nil, fmt.Errorf("failed to read theme file: %w", err)
- }
-
- var theme Theme
- if err := json.Unmarshal(data, &theme); err != nil {
- return nil, fmt.Errorf("failed to parse theme file: %w", err)
- }
-
- return &theme, nil
-}
-
-func (m *Manager) HasUpdates(themeID string, registryTheme Theme) (bool, error) {
- installed, err := m.GetInstalledTheme(themeID)
- if err != nil {
- return false, err
- }
-
- return compareVersions(installed.Version, registryTheme.Version) < 0, nil
-}
-
-func compareVersions(installed, registry string) int {
- installedParts := strings.Split(installed, ".")
- registryParts := strings.Split(registry, ".")
-
- maxLen := len(installedParts)
- if len(registryParts) > maxLen {
- maxLen = len(registryParts)
- }
-
- for i := 0; i < maxLen; i++ {
- var installedNum, registryNum int
- if i < len(installedParts) {
- fmt.Sscanf(installedParts[i], "%d", &installedNum)
- }
- if i < len(registryParts) {
- fmt.Sscanf(registryParts[i], "%d", &registryNum)
- }
-
- if installedNum < registryNum {
- return -1
- }
- if installedNum > registryNum {
- return 1
- }
- }
-
- return 0
-}
-
-func (m *Manager) GetThemesDir() string {
- return m.themesDir
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/themes/registry.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/themes/registry.go
deleted file mode 100644
index 5a39913..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/themes/registry.go
+++ /dev/null
@@ -1,309 +0,0 @@
-package themes
-
-import (
- "encoding/json"
- "errors"
- "fmt"
- "os"
- "path/filepath"
-
- "github.com/go-git/go-git/v6"
- "github.com/spf13/afero"
-)
-
-const registryRepo = "https://github.com/AvengeMedia/dms-plugin-registry.git"
-
-type ColorScheme struct {
- Primary string `json:"primary,omitempty"`
- PrimaryText string `json:"primaryText,omitempty"`
- PrimaryContainer string `json:"primaryContainer,omitempty"`
- Secondary string `json:"secondary,omitempty"`
- Surface string `json:"surface,omitempty"`
- SurfaceText string `json:"surfaceText,omitempty"`
- SurfaceVariant string `json:"surfaceVariant,omitempty"`
- SurfaceVariantText string `json:"surfaceVariantText,omitempty"`
- SurfaceTint string `json:"surfaceTint,omitempty"`
- Background string `json:"background,omitempty"`
- BackgroundText string `json:"backgroundText,omitempty"`
- Outline string `json:"outline,omitempty"`
- SurfaceContainer string `json:"surfaceContainer,omitempty"`
- SurfaceContainerHigh string `json:"surfaceContainerHigh,omitempty"`
- SurfaceContainerHighest string `json:"surfaceContainerHighest,omitempty"`
- Error string `json:"error,omitempty"`
- Warning string `json:"warning,omitempty"`
- Info string `json:"info,omitempty"`
-}
-
-type ThemeVariant struct {
- ID string `json:"id"`
- Name string `json:"name"`
- Dark ColorScheme `json:"dark,omitempty"`
- Light ColorScheme `json:"light,omitempty"`
-}
-
-type ThemeFlavor struct {
- ID string `json:"id"`
- Name string `json:"name"`
- Dark ColorScheme `json:"dark,omitempty"`
- Light ColorScheme `json:"light,omitempty"`
-}
-
-type ThemeAccent struct {
- ID string `json:"id"`
- Name string `json:"name"`
- FlavorColors map[string]ColorScheme `json:"-"`
-}
-
-func (a *ThemeAccent) UnmarshalJSON(data []byte) error {
- var raw map[string]json.RawMessage
- if err := json.Unmarshal(data, &raw); err != nil {
- return err
- }
- a.FlavorColors = make(map[string]ColorScheme)
- var mErr error
- for key, value := range raw {
- switch key {
- case "id":
- mErr = errors.Join(mErr, json.Unmarshal(value, &a.ID))
- case "name":
- mErr = errors.Join(mErr, json.Unmarshal(value, &a.Name))
- default:
- var colors ColorScheme
- if err := json.Unmarshal(value, &colors); err == nil {
- a.FlavorColors[key] = colors
- } else {
- mErr = errors.Join(mErr, fmt.Errorf("failed to unmarshal flavor colors for key %s: %w", key, err))
- }
- }
- }
- return mErr
-}
-
-func (a ThemeAccent) MarshalJSON() ([]byte, error) {
- m := map[string]any{
- "id": a.ID,
- "name": a.Name,
- }
- for k, v := range a.FlavorColors {
- m[k] = v
- }
- return json.Marshal(m)
-}
-
-type MultiVariantDefaults struct {
- Dark map[string]string `json:"dark,omitempty"`
- Light map[string]string `json:"light,omitempty"`
-}
-
-type ThemeVariants struct {
- Type string `json:"type,omitempty"`
- Default string `json:"default,omitempty"`
- Defaults *MultiVariantDefaults `json:"defaults,omitempty"`
- Options []ThemeVariant `json:"options,omitempty"`
- Flavors []ThemeFlavor `json:"flavors,omitempty"`
- Accents []ThemeAccent `json:"accents,omitempty"`
-}
-
-type Theme struct {
- ID string `json:"id"`
- Name string `json:"name"`
- Version string `json:"version"`
- Author string `json:"author"`
- Description string `json:"description"`
- Dark ColorScheme `json:"dark"`
- Light ColorScheme `json:"light"`
- Variants *ThemeVariants `json:"variants,omitempty"`
- PreviewPath string `json:"-"`
- SourceDir string `json:"sourceDir,omitempty"`
-}
-
-type GitClient interface {
- PlainClone(path string, url string) error
- Pull(path string) error
-}
-
-type realGitClient struct{}
-
-func (g *realGitClient) PlainClone(path string, url string) error {
- _, err := git.PlainClone(path, &git.CloneOptions{
- URL: url,
- Progress: os.Stdout,
- })
- return err
-}
-
-func (g *realGitClient) Pull(path string) error {
- repo, err := git.PlainOpen(path)
- if err != nil {
- return err
- }
-
- worktree, err := repo.Worktree()
- if err != nil {
- return err
- }
-
- err = worktree.Pull(&git.PullOptions{})
- if err != nil && err.Error() != "already up-to-date" {
- return err
- }
-
- return nil
-}
-
-type Registry struct {
- fs afero.Fs
- cacheDir string
- themes []Theme
- git GitClient
-}
-
-func NewRegistry() (*Registry, error) {
- return NewRegistryWithFs(afero.NewOsFs())
-}
-
-func NewRegistryWithFs(fs afero.Fs) (*Registry, error) {
- cacheDir := getCacheDir()
- return &Registry{
- fs: fs,
- cacheDir: cacheDir,
- git: &realGitClient{},
- }, nil
-}
-
-func getCacheDir() string {
- return filepath.Join(os.TempDir(), "dankdots-plugin-registry")
-}
-
-func (r *Registry) Update() error {
- exists, err := afero.DirExists(r.fs, r.cacheDir)
- if err != nil {
- return fmt.Errorf("failed to check cache directory: %w", err)
- }
-
- if !exists {
- if err := r.fs.MkdirAll(filepath.Dir(r.cacheDir), 0o755); err != nil {
- return fmt.Errorf("failed to create cache directory: %w", err)
- }
-
- if err := r.git.PlainClone(r.cacheDir, registryRepo); err != nil {
- return fmt.Errorf("failed to clone registry: %w", err)
- }
- } else {
- if err := r.git.Pull(r.cacheDir); err != nil {
- if err := r.fs.RemoveAll(r.cacheDir); err != nil {
- return fmt.Errorf("failed to remove corrupted registry: %w", err)
- }
-
- if err := r.fs.MkdirAll(filepath.Dir(r.cacheDir), 0o755); err != nil {
- return fmt.Errorf("failed to create cache directory: %w", err)
- }
-
- if err := r.git.PlainClone(r.cacheDir, registryRepo); err != nil {
- return fmt.Errorf("failed to re-clone registry: %w", err)
- }
- }
- }
-
- return r.loadThemes()
-}
-
-func (r *Registry) loadThemes() error {
- themesDir := filepath.Join(r.cacheDir, "themes")
-
- entries, err := afero.ReadDir(r.fs, themesDir)
- if err != nil {
- return fmt.Errorf("failed to read themes directory: %w", err)
- }
-
- r.themes = []Theme{}
-
- for _, entry := range entries {
- if !entry.IsDir() {
- continue
- }
-
- themeDir := filepath.Join(themesDir, entry.Name())
- themeFile := filepath.Join(themeDir, "theme.json")
-
- data, err := afero.ReadFile(r.fs, themeFile)
- if err != nil {
- continue
- }
-
- var theme Theme
- if err := json.Unmarshal(data, &theme); err != nil {
- continue
- }
-
- if theme.ID == "" {
- theme.ID = entry.Name()
- }
- theme.SourceDir = entry.Name()
-
- previewPath := filepath.Join(themeDir, "preview.svg")
- if exists, _ := afero.Exists(r.fs, previewPath); exists {
- theme.PreviewPath = previewPath
- }
-
- r.themes = append(r.themes, theme)
- }
-
- return nil
-}
-
-func (r *Registry) List() ([]Theme, error) {
- if len(r.themes) == 0 {
- if err := r.Update(); err != nil {
- return nil, err
- }
- }
-
- return SortByFirstParty(r.themes), nil
-}
-
-func (r *Registry) Search(query string) ([]Theme, error) {
- allThemes, err := r.List()
- if err != nil {
- return nil, err
- }
-
- if query == "" {
- return allThemes, nil
- }
-
- return SortByFirstParty(FuzzySearch(query, allThemes)), nil
-}
-
-func (r *Registry) Get(idOrName string) (*Theme, error) {
- themes, err := r.List()
- if err != nil {
- return nil, err
- }
-
- for _, t := range themes {
- if t.ID == idOrName {
- return &t, nil
- }
- }
-
- for _, t := range themes {
- if t.Name == idOrName {
- return &t, nil
- }
- }
-
- return nil, fmt.Errorf("theme not found: %s", idOrName)
-}
-
-func (r *Registry) GetThemeSourcePath(themeID string) string {
- return filepath.Join(r.cacheDir, "themes", themeID, "theme.json")
-}
-
-func (r *Registry) GetThemeDir(themeID string) string {
- return filepath.Join(r.cacheDir, "themes", themeID)
-}
-
-func SortByFirstParty(themes []Theme) []Theme {
- return themes
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/themes/search.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/themes/search.go
deleted file mode 100644
index 347f791..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/themes/search.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package themes
-
-import (
- "strings"
-
- "github.com/AvengeMedia/DankMaterialShell/core/internal/utils"
-)
-
-func FuzzySearch(query string, themes []Theme) []Theme {
- if query == "" {
- return themes
- }
-
- queryLower := strings.ToLower(query)
- return utils.Filter(themes, func(t Theme) bool {
- return fuzzyMatch(queryLower, strings.ToLower(t.Name)) ||
- fuzzyMatch(queryLower, strings.ToLower(t.Description)) ||
- fuzzyMatch(queryLower, strings.ToLower(t.Author))
- })
-}
-
-func fuzzyMatch(query, text string) bool {
- queryIdx := 0
- for _, char := range text {
- if queryIdx < len(query) && char == rune(query[queryIdx]) {
- queryIdx++
- }
- }
- return queryIdx == len(query)
-}
-
-func FindByIDOrName(idOrName string, themes []Theme) *Theme {
- if t, found := utils.Find(themes, func(t Theme) bool { return t.ID == idOrName }); found {
- return &t
- }
- if t, found := utils.Find(themes, func(t Theme) bool { return t.Name == idOrName }); found {
- return &t
- }
- return nil
-}