1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-25 05:52:50 -05:00

themes: incorporate theme registry, browser, dms URI scheme handling

This commit is contained in:
bbedward
2025-12-21 22:03:48 -05:00
parent 67ee74ac20
commit b4f83d09d4
28 changed files with 1924 additions and 58 deletions

View File

@@ -18,6 +18,7 @@ import (
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/models"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/network"
serverPlugins "github.com/AvengeMedia/DankMaterialShell/core/internal/server/plugins"
serverThemes "github.com/AvengeMedia/DankMaterialShell/core/internal/server/themes"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/wayland"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/wlroutput"
)
@@ -37,6 +38,11 @@ func RouteRequest(conn net.Conn, req models.Request) {
return
}
if strings.HasPrefix(req.Method, "themes.") {
serverThemes.HandleRequest(conn, req)
return
}
if strings.HasPrefix(req.Method, "loginctl.") {
if loginctlManager == nil {
models.RespondError(conn, req.ID, "loginctl manager not initialized")

View File

@@ -0,0 +1,27 @@
package themes
import (
"fmt"
"net"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/models"
)
func HandleRequest(conn net.Conn, req models.Request) {
switch req.Method {
case "themes.list":
HandleList(conn, req)
case "themes.listInstalled":
HandleListInstalled(conn, req)
case "themes.install":
HandleInstall(conn, req)
case "themes.uninstall":
HandleUninstall(conn, req)
case "themes.update":
HandleUpdate(conn, req)
case "themes.search":
HandleSearch(conn, req)
default:
models.RespondError(conn, req.ID, fmt.Sprintf("unknown method: %s", req.Method))
}
}

View File

@@ -0,0 +1,52 @@
package themes
import (
"fmt"
"net"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/models"
"github.com/AvengeMedia/DankMaterialShell/core/internal/themes"
)
func HandleInstall(conn net.Conn, req models.Request) {
idOrName, ok := req.Params["name"].(string)
if !ok {
models.RespondError(conn, req.ID, "missing or invalid 'name' parameter")
return
}
registry, err := themes.NewRegistry()
if err != nil {
models.RespondError(conn, req.ID, fmt.Sprintf("failed to create registry: %v", err))
return
}
themeList, err := registry.List()
if err != nil {
models.RespondError(conn, req.ID, fmt.Sprintf("failed to list themes: %v", err))
return
}
theme := themes.FindByIDOrName(idOrName, themeList)
if theme == nil {
models.RespondError(conn, req.ID, fmt.Sprintf("theme not found: %s", idOrName))
return
}
manager, err := themes.NewManager()
if err != nil {
models.RespondError(conn, req.ID, fmt.Sprintf("failed to create manager: %v", err))
return
}
registryThemeDir := registry.GetThemeDir(theme.SourceDir)
if err := manager.Install(*theme, registryThemeDir); err != nil {
models.RespondError(conn, req.ID, fmt.Sprintf("failed to install theme: %v", err))
return
}
models.Respond(conn, req.ID, models.SuccessResult{
Success: true,
Message: fmt.Sprintf("theme installed: %s", theme.Name),
})
}

View File

@@ -0,0 +1,52 @@
package themes
import (
"fmt"
"net"
"strings"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/models"
"github.com/AvengeMedia/DankMaterialShell/core/internal/themes"
)
func HandleList(conn net.Conn, req models.Request) {
registry, err := themes.NewRegistry()
if err != nil {
models.RespondError(conn, req.ID, fmt.Sprintf("failed to create registry: %v", err))
return
}
themeList, err := registry.List()
if err != nil {
models.RespondError(conn, req.ID, fmt.Sprintf("failed to list themes: %v", err))
return
}
manager, err := themes.NewManager()
if err != nil {
models.RespondError(conn, req.ID, fmt.Sprintf("failed to create manager: %v", err))
return
}
result := make([]ThemeInfo, len(themeList))
for i, t := range themeList {
installed, _ := manager.IsInstalled(t)
result[i] = ThemeInfo{
ID: t.ID,
Name: t.Name,
Version: t.Version,
Author: t.Author,
Description: t.Description,
PreviewPath: t.PreviewPath,
SourceDir: t.SourceDir,
Installed: installed,
FirstParty: isFirstParty(t.Author),
}
}
models.Respond(conn, req.ID, result)
}
func isFirstParty(author string) bool {
return strings.EqualFold(author, "Avenge Media") || strings.EqualFold(author, "AvengeMedia")
}

View File

@@ -0,0 +1,82 @@
package themes
import (
"fmt"
"net"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/models"
"github.com/AvengeMedia/DankMaterialShell/core/internal/themes"
)
func HandleListInstalled(conn net.Conn, req models.Request) {
manager, err := themes.NewManager()
if err != nil {
models.RespondError(conn, req.ID, fmt.Sprintf("failed to create manager: %v", err))
return
}
installedIDs, err := manager.ListInstalled()
if err != nil {
models.RespondError(conn, req.ID, fmt.Sprintf("failed to list installed themes: %v", err))
return
}
registry, err := themes.NewRegistry()
if err != nil {
models.RespondError(conn, req.ID, fmt.Sprintf("failed to create registry: %v", err))
return
}
allThemes, err := registry.List()
if err != nil {
models.RespondError(conn, req.ID, fmt.Sprintf("failed to list themes: %v", err))
return
}
themeMap := make(map[string]themes.Theme)
for _, t := range allThemes {
themeMap[t.ID] = t
}
result := make([]ThemeInfo, 0, len(installedIDs))
for _, id := range installedIDs {
if theme, ok := themeMap[id]; ok {
hasUpdate := false
if hasUpdates, err := manager.HasUpdates(id, theme); err == nil {
hasUpdate = hasUpdates
}
result = append(result, ThemeInfo{
ID: theme.ID,
Name: theme.Name,
Version: theme.Version,
Author: theme.Author,
Description: theme.Description,
SourceDir: id,
FirstParty: isFirstParty(theme.Author),
HasUpdate: hasUpdate,
})
} else {
installed, err := manager.GetInstalledTheme(id)
if err != nil {
result = append(result, ThemeInfo{
ID: id,
Name: id,
SourceDir: id,
})
continue
}
result = append(result, ThemeInfo{
ID: installed.ID,
Name: installed.Name,
Version: installed.Version,
Author: installed.Author,
Description: installed.Description,
SourceDir: id,
FirstParty: isFirstParty(installed.Author),
})
}
}
models.Respond(conn, req.ID, result)
}

View File

@@ -0,0 +1,53 @@
package themes
import (
"fmt"
"net"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/models"
"github.com/AvengeMedia/DankMaterialShell/core/internal/themes"
)
func HandleSearch(conn net.Conn, req models.Request) {
query, ok := req.Params["query"].(string)
if !ok {
models.RespondError(conn, req.ID, "missing or invalid 'query' parameter")
return
}
registry, err := themes.NewRegistry()
if err != nil {
models.RespondError(conn, req.ID, fmt.Sprintf("failed to create registry: %v", err))
return
}
themeList, err := registry.List()
if err != nil {
models.RespondError(conn, req.ID, fmt.Sprintf("failed to list themes: %v", err))
return
}
searchResults := themes.FuzzySearch(query, themeList)
manager, err := themes.NewManager()
if err != nil {
models.RespondError(conn, req.ID, fmt.Sprintf("failed to create manager: %v", err))
return
}
result := make([]ThemeInfo, len(searchResults))
for i, t := range searchResults {
installed, _ := manager.IsInstalled(t)
result[i] = ThemeInfo{
ID: t.ID,
Name: t.Name,
Version: t.Version,
Author: t.Author,
Description: t.Description,
Installed: installed,
FirstParty: isFirstParty(t.Author),
}
}
models.Respond(conn, req.ID, result)
}

View File

@@ -0,0 +1,14 @@
package themes
type ThemeInfo struct {
ID string `json:"id"`
Name string `json:"name"`
Version string `json:"version"`
Author string `json:"author,omitempty"`
Description string `json:"description,omitempty"`
PreviewPath string `json:"previewPath,omitempty"`
SourceDir string `json:"sourceDir,omitempty"`
Installed bool `json:"installed,omitempty"`
FirstParty bool `json:"firstParty,omitempty"`
HasUpdate bool `json:"hasUpdate,omitempty"`
}

View File

@@ -0,0 +1,63 @@
package themes
import (
"fmt"
"net"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/models"
"github.com/AvengeMedia/DankMaterialShell/core/internal/themes"
)
func HandleUninstall(conn net.Conn, req models.Request) {
idOrName, ok := req.Params["name"].(string)
if !ok {
models.RespondError(conn, req.ID, "missing or invalid 'name' parameter")
return
}
manager, err := themes.NewManager()
if err != nil {
models.RespondError(conn, req.ID, fmt.Sprintf("failed to create manager: %v", err))
return
}
registry, err := themes.NewRegistry()
if err != nil {
models.RespondError(conn, req.ID, fmt.Sprintf("failed to create registry: %v", err))
return
}
themeList, _ := registry.List()
theme := themes.FindByIDOrName(idOrName, themeList)
if theme != nil {
installed, err := manager.IsInstalled(*theme)
if err != nil {
models.RespondError(conn, req.ID, fmt.Sprintf("failed to check if theme is installed: %v", err))
return
}
if !installed {
models.RespondError(conn, req.ID, fmt.Sprintf("theme not installed: %s", idOrName))
return
}
if err := manager.Uninstall(*theme); err != nil {
models.RespondError(conn, req.ID, fmt.Sprintf("failed to uninstall theme: %v", err))
return
}
models.Respond(conn, req.ID, models.SuccessResult{
Success: true,
Message: fmt.Sprintf("theme uninstalled: %s", theme.Name),
})
return
}
if err := manager.UninstallByID(idOrName); err != nil {
models.RespondError(conn, req.ID, fmt.Sprintf("theme not found: %s", idOrName))
return
}
models.Respond(conn, req.ID, models.SuccessResult{
Success: true,
Message: fmt.Sprintf("theme uninstalled: %s", idOrName),
})
}

View File

@@ -0,0 +1,57 @@
package themes
import (
"fmt"
"net"
"github.com/AvengeMedia/DankMaterialShell/core/internal/server/models"
"github.com/AvengeMedia/DankMaterialShell/core/internal/themes"
)
func HandleUpdate(conn net.Conn, req models.Request) {
idOrName, ok := req.Params["name"].(string)
if !ok {
models.RespondError(conn, req.ID, "missing or invalid 'name' parameter")
return
}
manager, err := themes.NewManager()
if err != nil {
models.RespondError(conn, req.ID, fmt.Sprintf("failed to create manager: %v", err))
return
}
registry, err := themes.NewRegistry()
if err != nil {
models.RespondError(conn, req.ID, fmt.Sprintf("failed to create registry: %v", err))
return
}
themeList, _ := registry.List()
theme := themes.FindByIDOrName(idOrName, themeList)
if theme == nil {
models.RespondError(conn, req.ID, fmt.Sprintf("theme not found in registry: %s", idOrName))
return
}
installed, err := manager.IsInstalled(*theme)
if err != nil {
models.RespondError(conn, req.ID, fmt.Sprintf("failed to check if theme is installed: %v", err))
return
}
if !installed {
models.RespondError(conn, req.ID, fmt.Sprintf("theme not installed: %s", idOrName))
return
}
if err := manager.Update(*theme); err != nil {
models.RespondError(conn, req.ID, fmt.Sprintf("failed to update theme: %v", err))
return
}
models.Respond(conn, req.ID, models.SuccessResult{
Success: true,
Message: fmt.Sprintf("theme updated: %s", theme.Name),
})
}