summaryrefslogtreecommitdiff
path: root/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins')
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/handlers.go27
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/handlers_test.go196
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/install.go69
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/list.go53
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/list_installed.go77
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/search.go74
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/types.go25
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/uninstall.go66
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/update.go64
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/utils.go17
10 files changed, 668 insertions, 0 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/handlers.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/handlers.go
new file mode 100644
index 0000000..33f6564
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/handlers.go
@@ -0,0 +1,27 @@
+package plugins
+
+import (
+ "fmt"
+ "net"
+
+ "github.com/AvengeMedia/DankMaterialShell/core/internal/server/models"
+)
+
+func HandleRequest(conn net.Conn, req models.Request) {
+ switch req.Method {
+ case "plugins.list":
+ HandleList(conn, req)
+ case "plugins.listInstalled":
+ HandleListInstalled(conn, req)
+ case "plugins.install":
+ HandleInstall(conn, req)
+ case "plugins.uninstall":
+ HandleUninstall(conn, req)
+ case "plugins.update":
+ HandleUpdate(conn, req)
+ case "plugins.search":
+ HandleSearch(conn, req)
+ default:
+ models.RespondError(conn, req.ID, fmt.Sprintf("unknown method: %s", req.Method))
+ }
+}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/handlers_test.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/handlers_test.go
new file mode 100644
index 0000000..70202e3
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/handlers_test.go
@@ -0,0 +1,196 @@
+package plugins
+
+import (
+ "encoding/json"
+ "testing"
+
+ "github.com/AvengeMedia/DankMaterialShell/core/internal/mocks/net"
+ "github.com/AvengeMedia/DankMaterialShell/core/internal/server/models"
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/mock"
+)
+
+func TestHandleList(t *testing.T) {
+ conn := net.NewMockConn(t)
+ conn.EXPECT().Write(mock.Anything).Return(0, nil).Maybe()
+
+ req := models.Request{
+ ID: 123,
+ Method: "plugins.list",
+ Params: map[string]any{},
+ }
+
+ HandleList(conn, req)
+}
+
+func TestHandleListInstalled(t *testing.T) {
+ conn := net.NewMockConn(t)
+ conn.EXPECT().Write(mock.Anything).Return(0, nil).Maybe()
+
+ req := models.Request{
+ ID: 123,
+ Method: "plugins.listInstalled",
+ Params: map[string]any{},
+ }
+
+ HandleListInstalled(conn, req)
+}
+
+func TestHandleInstallMissingName(t *testing.T) {
+ conn := net.NewMockConn(t)
+ var written []byte
+ conn.EXPECT().Write(mock.Anything).RunAndReturn(func(b []byte) (int, error) {
+ written = b
+ return len(b), nil
+ }).Maybe()
+
+ req := models.Request{
+ ID: 123,
+ Method: "plugins.install",
+ Params: map[string]any{},
+ }
+
+ HandleInstall(conn, req)
+
+ var resp models.Response[SuccessResult]
+ err := json.Unmarshal(written, &resp)
+ assert.NoError(t, err)
+ assert.NotEmpty(t, resp.Error)
+ assert.Contains(t, resp.Error, "missing or invalid 'name' parameter")
+}
+
+func TestHandleInstallInvalidName(t *testing.T) {
+ conn := net.NewMockConn(t)
+ var written []byte
+ conn.EXPECT().Write(mock.Anything).RunAndReturn(func(b []byte) (int, error) {
+ written = b
+ return len(b), nil
+ }).Maybe()
+
+ req := models.Request{
+ ID: 123,
+ Method: "plugins.install",
+ Params: map[string]any{
+ "name": 123,
+ },
+ }
+
+ HandleInstall(conn, req)
+
+ var resp models.Response[SuccessResult]
+ err := json.Unmarshal(written, &resp)
+ assert.NoError(t, err)
+ assert.NotEmpty(t, resp.Error)
+}
+
+func TestHandleUninstallMissingName(t *testing.T) {
+ conn := net.NewMockConn(t)
+ var written []byte
+ conn.EXPECT().Write(mock.Anything).RunAndReturn(func(b []byte) (int, error) {
+ written = b
+ return len(b), nil
+ }).Maybe()
+
+ req := models.Request{
+ ID: 123,
+ Method: "plugins.uninstall",
+ Params: map[string]any{},
+ }
+
+ HandleUninstall(conn, req)
+
+ var resp models.Response[SuccessResult]
+ err := json.Unmarshal(written, &resp)
+ assert.NoError(t, err)
+ assert.NotEmpty(t, resp.Error)
+}
+
+func TestHandleUpdateMissingName(t *testing.T) {
+ conn := net.NewMockConn(t)
+ var written []byte
+ conn.EXPECT().Write(mock.Anything).RunAndReturn(func(b []byte) (int, error) {
+ written = b
+ return len(b), nil
+ }).Maybe()
+
+ req := models.Request{
+ ID: 123,
+ Method: "plugins.update",
+ Params: map[string]any{},
+ }
+
+ HandleUpdate(conn, req)
+
+ var resp models.Response[SuccessResult]
+ err := json.Unmarshal(written, &resp)
+ assert.NoError(t, err)
+ assert.NotEmpty(t, resp.Error)
+}
+
+func TestHandleSearchMissingQuery(t *testing.T) {
+ conn := net.NewMockConn(t)
+ var written []byte
+ conn.EXPECT().Write(mock.Anything).RunAndReturn(func(b []byte) (int, error) {
+ written = b
+ return len(b), nil
+ }).Maybe()
+
+ req := models.Request{
+ ID: 123,
+ Method: "plugins.search",
+ Params: map[string]any{},
+ }
+
+ HandleSearch(conn, req)
+
+ var resp models.Response[[]PluginInfo]
+ err := json.Unmarshal(written, &resp)
+ assert.NoError(t, err)
+ assert.NotEmpty(t, resp.Error)
+}
+
+func TestSortPluginInfoByFirstParty(t *testing.T) {
+ plugins := []PluginInfo{
+ {Name: "third-party", Repo: "https://github.com/other/test"},
+ {Name: "first-party", Repo: "https://github.com/AvengeMedia/test"},
+ }
+
+ SortPluginInfoByFirstParty(plugins)
+
+ assert.Equal(t, "first-party", plugins[0].Name)
+ assert.Equal(t, "third-party", plugins[1].Name)
+}
+
+func TestPluginInfoJSON(t *testing.T) {
+ info := PluginInfo{
+ Name: "test",
+ Description: "test description",
+ Installed: true,
+ FirstParty: true,
+ }
+
+ data, err := json.Marshal(info)
+ assert.NoError(t, err)
+
+ var unmarshaled PluginInfo
+ err = json.Unmarshal(data, &unmarshaled)
+ assert.NoError(t, err)
+ assert.Equal(t, info.Name, unmarshaled.Name)
+ assert.Equal(t, info.Installed, unmarshaled.Installed)
+}
+
+func TestSuccessResult(t *testing.T) {
+ result := SuccessResult{
+ Success: true,
+ Message: "test message",
+ }
+
+ data, err := json.Marshal(result)
+ assert.NoError(t, err)
+
+ var unmarshaled SuccessResult
+ err = json.Unmarshal(data, &unmarshaled)
+ assert.NoError(t, err)
+ assert.True(t, unmarshaled.Success)
+ assert.Equal(t, "test message", unmarshaled.Message)
+}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/install.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/install.go
new file mode 100644
index 0000000..2c13a0e
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/install.go
@@ -0,0 +1,69 @@
+package plugins
+
+import (
+ "fmt"
+ "net"
+
+ "github.com/AvengeMedia/DankMaterialShell/core/internal/plugins"
+ "github.com/AvengeMedia/DankMaterialShell/core/internal/server/models"
+)
+
+func HandleInstall(conn net.Conn, req models.Request) {
+ idOrName, ok := models.Get[string](req, "name")
+ if !ok {
+ models.RespondError(conn, req.ID, "missing or invalid 'name' parameter")
+ return
+ }
+
+ registry, err := plugins.NewRegistry()
+ if err != nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("failed to create registry: %v", err))
+ return
+ }
+
+ pluginList, err := registry.List()
+ if err != nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("failed to list plugins: %v", err))
+ return
+ }
+
+ // First, try to find by ID (preferred method)
+ var plugin *plugins.Plugin
+ for _, p := range pluginList {
+ if p.ID == idOrName {
+ plugin = &p
+ break
+ }
+ }
+
+ // Fallback to name for backward compatibility
+ if plugin == nil {
+ for _, p := range pluginList {
+ if p.Name == idOrName {
+ plugin = &p
+ break
+ }
+ }
+ }
+
+ if plugin == nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("plugin not found: %s", idOrName))
+ return
+ }
+
+ manager, err := plugins.NewManager()
+ if err != nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("failed to create manager: %v", err))
+ return
+ }
+
+ if err := manager.Install(*plugin); err != nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("failed to install plugin: %v", err))
+ return
+ }
+
+ models.Respond(conn, req.ID, SuccessResult{
+ Success: true,
+ Message: fmt.Sprintf("plugin installed: %s", plugin.Name),
+ })
+}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/list.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/list.go
new file mode 100644
index 0000000..e44d034
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/list.go
@@ -0,0 +1,53 @@
+package plugins
+
+import (
+ "fmt"
+ "net"
+ "strings"
+
+ "github.com/AvengeMedia/DankMaterialShell/core/internal/plugins"
+ "github.com/AvengeMedia/DankMaterialShell/core/internal/server/models"
+)
+
+func HandleList(conn net.Conn, req models.Request) {
+ registry, err := plugins.NewRegistry()
+ if err != nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("failed to create registry: %v", err))
+ return
+ }
+
+ pluginList, err := registry.List()
+ if err != nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("failed to list plugins: %v", err))
+ return
+ }
+
+ manager, err := plugins.NewManager()
+ if err != nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("failed to create manager: %v", err))
+ return
+ }
+
+ result := make([]PluginInfo, len(pluginList))
+ for i, p := range pluginList {
+ installed, _ := manager.IsInstalled(p)
+ result[i] = PluginInfo{
+ ID: p.ID,
+ Name: p.Name,
+ Category: p.Category,
+ Author: p.Author,
+ Description: p.Description,
+ Repo: p.Repo,
+ Path: p.Path,
+ Capabilities: p.Capabilities,
+ Compositors: p.Compositors,
+ Dependencies: p.Dependencies,
+ Installed: installed,
+ FirstParty: strings.HasPrefix(p.Repo, "https://github.com/AvengeMedia"),
+ Featured: p.Featured,
+ RequiresDMS: p.RequiresDMS,
+ }
+ }
+
+ models.Respond(conn, req.ID, result)
+}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/list_installed.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/list_installed.go
new file mode 100644
index 0000000..b771b0e
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/list_installed.go
@@ -0,0 +1,77 @@
+package plugins
+
+import (
+ "fmt"
+ "net"
+ "strings"
+
+ "github.com/AvengeMedia/DankMaterialShell/core/internal/plugins"
+ "github.com/AvengeMedia/DankMaterialShell/core/internal/server/models"
+)
+
+func HandleListInstalled(conn net.Conn, req models.Request) {
+ manager, err := plugins.NewManager()
+ if err != nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("failed to create manager: %v", err))
+ return
+ }
+
+ installedNames, err := manager.ListInstalled()
+ if err != nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("failed to list installed plugins: %v", err))
+ return
+ }
+
+ registry, err := plugins.NewRegistry()
+ if err != nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("failed to create registry: %v", err))
+ return
+ }
+
+ allPlugins, err := registry.List()
+ if err != nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("failed to list plugins: %v", err))
+ return
+ }
+
+ pluginMap := make(map[string]plugins.Plugin)
+ for _, p := range allPlugins {
+ pluginMap[p.ID] = p
+ }
+
+ result := make([]PluginInfo, 0, len(installedNames))
+ for _, id := range installedNames {
+ if plugin, ok := pluginMap[id]; ok {
+ hasUpdate := false
+ if hasUpdates, err := manager.HasUpdates(id, plugin); err == nil {
+ hasUpdate = hasUpdates
+ }
+
+ result = append(result, PluginInfo{
+ ID: plugin.ID,
+ Name: plugin.Name,
+ Category: plugin.Category,
+ Author: plugin.Author,
+ Description: plugin.Description,
+ Repo: plugin.Repo,
+ Path: plugin.Path,
+ Capabilities: plugin.Capabilities,
+ Compositors: plugin.Compositors,
+ Dependencies: plugin.Dependencies,
+ FirstParty: strings.HasPrefix(plugin.Repo, "https://github.com/AvengeMedia"),
+ HasUpdate: hasUpdate,
+ RequiresDMS: plugin.RequiresDMS,
+ })
+ } else {
+ result = append(result, PluginInfo{
+ ID: id,
+ Name: id,
+ Note: "not in registry",
+ })
+ }
+ }
+
+ SortPluginInfoByFirstParty(result)
+
+ models.Respond(conn, req.ID, result)
+}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/search.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/search.go
new file mode 100644
index 0000000..9dbea6d
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/search.go
@@ -0,0 +1,74 @@
+package plugins
+
+import (
+ "fmt"
+ "net"
+ "strings"
+
+ "github.com/AvengeMedia/DankMaterialShell/core/internal/plugins"
+ "github.com/AvengeMedia/DankMaterialShell/core/internal/server/models"
+)
+
+func HandleSearch(conn net.Conn, req models.Request) {
+ query, ok := models.Get[string](req, "query")
+ if !ok {
+ models.RespondError(conn, req.ID, "missing or invalid 'query' parameter")
+ return
+ }
+
+ registry, err := plugins.NewRegistry()
+ if err != nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("failed to create registry: %v", err))
+ return
+ }
+
+ pluginList, err := registry.List()
+ if err != nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("failed to list plugins: %v", err))
+ return
+ }
+
+ searchResults := plugins.FuzzySearch(query, pluginList)
+
+ if category := models.GetOr(req, "category", ""); category != "" {
+ searchResults = plugins.FilterByCategory(category, searchResults)
+ }
+
+ if compositor := models.GetOr(req, "compositor", ""); compositor != "" {
+ searchResults = plugins.FilterByCompositor(compositor, searchResults)
+ }
+
+ if capability := models.GetOr(req, "capability", ""); capability != "" {
+ searchResults = plugins.FilterByCapability(capability, searchResults)
+ }
+
+ searchResults = plugins.SortByFirstParty(searchResults)
+
+ manager, err := plugins.NewManager()
+ if err != nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("failed to create manager: %v", err))
+ return
+ }
+
+ result := make([]PluginInfo, len(searchResults))
+ for i, p := range searchResults {
+ installed, _ := manager.IsInstalled(p)
+ result[i] = PluginInfo{
+ ID: p.ID,
+ Name: p.Name,
+ Category: p.Category,
+ Author: p.Author,
+ Description: p.Description,
+ Repo: p.Repo,
+ Path: p.Path,
+ Capabilities: p.Capabilities,
+ Compositors: p.Compositors,
+ Dependencies: p.Dependencies,
+ Installed: installed,
+ FirstParty: strings.HasPrefix(p.Repo, "https://github.com/AvengeMedia"),
+ RequiresDMS: p.RequiresDMS,
+ }
+ }
+
+ models.Respond(conn, req.ID, result)
+}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/types.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/types.go
new file mode 100644
index 0000000..8290f72
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/types.go
@@ -0,0 +1,25 @@
+package plugins
+
+type PluginInfo struct {
+ ID string `json:"id"`
+ Name string `json:"name"`
+ Category string `json:"category,omitempty"`
+ Author string `json:"author,omitempty"`
+ Description string `json:"description,omitempty"`
+ Repo string `json:"repo,omitempty"`
+ Path string `json:"path,omitempty"`
+ Capabilities []string `json:"capabilities,omitempty"`
+ Compositors []string `json:"compositors,omitempty"`
+ Dependencies []string `json:"dependencies,omitempty"`
+ Installed bool `json:"installed,omitempty"`
+ FirstParty bool `json:"firstParty,omitempty"`
+ Featured bool `json:"featured,omitempty"`
+ Note string `json:"note,omitempty"`
+ HasUpdate bool `json:"hasUpdate,omitempty"`
+ RequiresDMS string `json:"requires_dms,omitempty"`
+}
+
+type SuccessResult struct {
+ Success bool `json:"success"`
+ Message string `json:"message"`
+}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/uninstall.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/uninstall.go
new file mode 100644
index 0000000..7a3d698
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/uninstall.go
@@ -0,0 +1,66 @@
+package plugins
+
+import (
+ "fmt"
+ "net"
+
+ "github.com/AvengeMedia/DankMaterialShell/core/internal/plugins"
+ "github.com/AvengeMedia/DankMaterialShell/core/internal/server/models"
+)
+
+func HandleUninstall(conn net.Conn, req models.Request) {
+ name, ok := models.Get[string](req, "name")
+ if !ok {
+ models.RespondError(conn, req.ID, "missing or invalid 'name' parameter")
+ return
+ }
+
+ manager, err := plugins.NewManager()
+ if err != nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("failed to create manager: %v", err))
+ return
+ }
+
+ // First try to find in registry (by name or ID)
+ registry, err := plugins.NewRegistry()
+ if err != nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("failed to create registry: %v", err))
+ return
+ }
+
+ pluginList, _ := registry.List()
+ plugin := plugins.FindByIDOrName(name, pluginList)
+
+ // If found in registry, use that
+ if plugin != nil {
+ installed, err := manager.IsInstalled(*plugin)
+ if err != nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("failed to check if plugin is installed: %v", err))
+ return
+ }
+ if !installed {
+ models.RespondError(conn, req.ID, fmt.Sprintf("plugin not installed: %s", name))
+ return
+ }
+ if err := manager.Uninstall(*plugin); err != nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("failed to uninstall plugin: %v", err))
+ return
+ }
+ models.Respond(conn, req.ID, SuccessResult{
+ Success: true,
+ Message: fmt.Sprintf("plugin uninstalled: %s", plugin.Name),
+ })
+ return
+ }
+
+ // Not in registry - try to find and uninstall from installed plugins directly
+ if err := manager.UninstallByIDOrName(name); err != nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("plugin not found: %s", name))
+ return
+ }
+
+ models.Respond(conn, req.ID, SuccessResult{
+ Success: true,
+ Message: fmt.Sprintf("plugin uninstalled: %s", name),
+ })
+}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/update.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/update.go
new file mode 100644
index 0000000..4ea762a
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/update.go
@@ -0,0 +1,64 @@
+package plugins
+
+import (
+ "fmt"
+ "net"
+
+ "github.com/AvengeMedia/DankMaterialShell/core/internal/plugins"
+ "github.com/AvengeMedia/DankMaterialShell/core/internal/server/models"
+)
+
+func HandleUpdate(conn net.Conn, req models.Request) {
+ name, ok := models.Get[string](req, "name")
+ if !ok {
+ models.RespondError(conn, req.ID, "missing or invalid 'name' parameter")
+ return
+ }
+
+ manager, err := plugins.NewManager()
+ if err != nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("failed to create manager: %v", err))
+ return
+ }
+
+ registry, err := plugins.NewRegistry()
+ if err != nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("failed to create registry: %v", err))
+ return
+ }
+
+ pluginList, _ := registry.List()
+ plugin := plugins.FindByIDOrName(name, pluginList)
+
+ if plugin != nil {
+ installed, err := manager.IsInstalled(*plugin)
+ if err != nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("failed to check if plugin is installed: %v", err))
+ return
+ }
+ if !installed {
+ models.RespondError(conn, req.ID, fmt.Sprintf("plugin not installed: %s", name))
+ return
+ }
+ if err := manager.Update(*plugin); err != nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("failed to update plugin: %v", err))
+ return
+ }
+ models.Respond(conn, req.ID, SuccessResult{
+ Success: true,
+ Message: fmt.Sprintf("plugin updated: %s", plugin.Name),
+ })
+ return
+ }
+
+ // Not in registry - try to update from installed plugins directly
+ if err := manager.UpdateByIDOrName(name); err != nil {
+ models.RespondError(conn, req.ID, fmt.Sprintf("plugin not found: %s", name))
+ return
+ }
+
+ models.Respond(conn, req.ID, SuccessResult{
+ Success: true,
+ Message: fmt.Sprintf("plugin updated: %s", name),
+ })
+}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/utils.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/utils.go
new file mode 100644
index 0000000..8b89f44
--- /dev/null
+++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/server/plugins/utils.go
@@ -0,0 +1,17 @@
+package plugins
+
+import (
+ "sort"
+ "strings"
+)
+
+func SortPluginInfoByFirstParty(pluginInfos []PluginInfo) {
+ sort.SliceStable(pluginInfos, func(i, j int) bool {
+ isFirstPartyI := strings.HasPrefix(pluginInfos[i].Repo, "https://github.com/AvengeMedia")
+ isFirstPartyJ := strings.HasPrefix(pluginInfos[j].Repo, "https://github.com/AvengeMedia")
+ if isFirstPartyI != isFirstPartyJ {
+ return isFirstPartyI
+ }
+ return false
+ })
+}