1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-05 21:15:38 -05:00
Files
DankMaterialShell/core/internal/keybinds/providers/jsonfile.go
2025-11-30 00:12:45 -05:00

132 lines
3.0 KiB
Go

package providers
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/AvengeMedia/DankMaterialShell/core/internal/keybinds"
)
type JSONFileProvider struct {
filePath string
name string
}
func NewJSONFileProvider(filePath string) (*JSONFileProvider, error) {
if filePath == "" {
return nil, fmt.Errorf("file path cannot be empty")
}
expandedPath, err := expandPath(filePath)
if err != nil {
return nil, fmt.Errorf("failed to expand path: %w", err)
}
name := filepath.Base(expandedPath)
name = name[:len(name)-len(filepath.Ext(name))]
return &JSONFileProvider{
filePath: expandedPath,
name: name,
}, nil
}
func (j *JSONFileProvider) Name() string {
return j.name
}
func (j *JSONFileProvider) GetCheatSheet() (*keybinds.CheatSheet, error) {
data, err := os.ReadFile(j.filePath)
if err != nil {
return nil, fmt.Errorf("failed to read file: %w", err)
}
var rawData map[string]interface{}
if err := json.Unmarshal(data, &rawData); err != nil {
return nil, fmt.Errorf("failed to parse JSON: %w", err)
}
title, _ := rawData["title"].(string)
provider, _ := rawData["provider"].(string)
if provider == "" {
provider = j.name
}
categorizedBinds := make(map[string][]keybinds.Keybind)
bindsRaw, ok := rawData["binds"]
if !ok {
return nil, fmt.Errorf("missing 'binds' field")
}
switch binds := bindsRaw.(type) {
case map[string]interface{}:
for category, categoryBindsRaw := range binds {
categoryBindsList, ok := categoryBindsRaw.([]interface{})
if !ok {
continue
}
var keybindsList []keybinds.Keybind
categoryBindsJSON, _ := json.Marshal(categoryBindsList)
if err := json.Unmarshal(categoryBindsJSON, &keybindsList); err != nil {
continue
}
categorizedBinds[category] = keybindsList
}
case []interface{}:
flatBindsJSON, _ := json.Marshal(binds)
var flatBinds []struct {
Key string `json:"key"`
Description string `json:"desc"`
Category string `json:"cat,omitempty"`
Subcategory string `json:"subcat,omitempty"`
}
if err := json.Unmarshal(flatBindsJSON, &flatBinds); err != nil {
return nil, fmt.Errorf("failed to parse flat binds array: %w", err)
}
for _, bind := range flatBinds {
category := bind.Category
if category == "" {
category = "Other"
}
kb := keybinds.Keybind{
Key: bind.Key,
Description: bind.Description,
Subcategory: bind.Subcategory,
}
categorizedBinds[category] = append(categorizedBinds[category], kb)
}
default:
return nil, fmt.Errorf("'binds' must be either an object (categorized) or array (flat)")
}
return &keybinds.CheatSheet{
Title: title,
Provider: provider,
Binds: categorizedBinds,
}, nil
}
func expandPath(path string) (string, error) {
expandedPath := os.ExpandEnv(path)
if strings.HasPrefix(expandedPath, "~") {
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
expandedPath = filepath.Join(home, expandedPath[1:])
}
return filepath.Clean(expandedPath), nil
}