package web import ( "encoding/json" "net/http" "gitgud.io/mike/mpv-manager/pkg/constants" "gitgud.io/mike/mpv-manager/pkg/log" "gitgud.io/mike/mpv-manager/pkg/modernzconf" "gitgud.io/mike/mpv-manager/pkg/uiconfig" ) // detectInstalledUI delegates to the shared detector so Web and TUI represent // the same on-disk state, including the unsafe two-script condition. func detectInstalledUI() string { return uiconfig.DetectInstalledUI() } // handleModernZConfigAPI returns all known ModernZ options with their // effective values and whether each is explicitly set in modernz.conf. // GET /api/modernz func (s *Server) handleModernZConfigAPI(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodGet { sendJSONError(w, http.StatusMethodNotAllowed, "Method not allowed") return } confPath, err := modernzconf.GetModernZConfPath() if err != nil { log.Error(constants.LogPrefixAPI + "Failed to determine modernz.conf path: " + err.Error()) sendJSONError(w, http.StatusInternalServerError, "Failed to determine modernz.conf path: "+err.Error()) return } conf, err := modernzconf.ParseModernZConf(confPath) if err != nil { log.Error(constants.LogPrefixAPI + "Failed to parse modernz.conf: " + err.Error()) sendJSONError(w, http.StatusInternalServerError, "Failed to parse modernz.conf: "+err.Error()) return } options := modernzconf.KnownOptions() values := make(map[string]string, len(options)) isSet := make(map[string]bool, len(options)) for _, opt := range options { values[opt.Key] = conf.GetValue(opt.Key) isSet[opt.Key] = conf.IsSet(opt.Key) } w.Header().Set("Content-Type", constants.ContentTypeJSON) json.NewEncoder(w).Encode(map[string]interface{}{ "options": options, "values": values, "is_set": isSet, "path": confPath, }) } // handleModernZSetAPI validates and sets a single ModernZ option value. // POST /api/modernz/set func (s *Server) handleModernZSetAPI(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { sendJSONError(w, http.StatusMethodNotAllowed, "Method not allowed") return } var req struct { Key string `json:"key"` Value string `json:"value"` } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { sendJSONError(w, http.StatusBadRequest, "Invalid request body") return } if err := modernzconf.ValidateValue(req.Key, req.Value); err != nil { sendJSONError(w, http.StatusBadRequest, err.Error()) return } confPath, err := modernzconf.GetModernZConfPath() if err != nil { log.Error(constants.LogPrefixAPI + "Failed to determine modernz.conf path: " + err.Error()) sendJSONError(w, http.StatusInternalServerError, "Failed to determine modernz.conf path: "+err.Error()) return } if err := modernzconf.SetValueFile(confPath, req.Key, req.Value); err != nil { log.Error(constants.LogPrefixAPI + "Failed to write modernz.conf: " + err.Error()) sendJSONError(w, http.StatusInternalServerError, "Failed to write modernz.conf: "+err.Error()) return } log.Info(constants.LogPrefixAPI + "Set ModernZ option: " + req.Key) w.Header().Set("Content-Type", constants.ContentTypeJSON) json.NewEncoder(w).Encode(map[string]interface{}{ "success": true, }) } // handleModernZResetAPI resets a single ModernZ option to its default value. // POST /api/modernz/reset func (s *Server) handleModernZResetAPI(w http.ResponseWriter, r *http.Request) { if r.Method != http.MethodPost { sendJSONError(w, http.StatusMethodNotAllowed, "Method not allowed") return } var req struct { Key string `json:"key"` } if err := json.NewDecoder(r.Body).Decode(&req); err != nil { sendJSONError(w, http.StatusBadRequest, "Invalid request body") return } if !isKnownModernZOption(req.Key) { sendJSONError(w, http.StatusBadRequest, "Unknown ModernZ option: "+req.Key) return } confPath, err := modernzconf.GetModernZConfPath() if err != nil { log.Error(constants.LogPrefixAPI + "Failed to determine modernz.conf path: " + err.Error()) sendJSONError(w, http.StatusInternalServerError, "Failed to determine modernz.conf path: "+err.Error()) return } if err := modernzconf.ResetValueFile(confPath, req.Key); err != nil { log.Error(constants.LogPrefixAPI + "Failed to write modernz.conf: " + err.Error()) sendJSONError(w, http.StatusInternalServerError, "Failed to write modernz.conf: "+err.Error()) return } log.Info(constants.LogPrefixAPI + "Reset ModernZ option: " + req.Key) w.Header().Set("Content-Type", constants.ContentTypeJSON) json.NewEncoder(w).Encode(map[string]interface{}{ "success": true, }) } // isKnownModernZOption reports whether key is a known ModernZ option. func isKnownModernZOption(key string) bool { for _, opt := range modernzconf.KnownOptions() { if opt.Key == key { return true } } return false }