diff --git a/handlers/infos.go b/handlers/infos.go index 0f6bcd8..a26b72d 100644 --- a/handlers/infos.go +++ b/handlers/infos.go @@ -47,7 +47,7 @@ func InfoHandler(w http.ResponseWriter, r *http.Request) { data := map[string]string{ "ip": GetLocalIP(), "port": port, - "speed": speed, + "speed": GetInterval(), } json.NewEncoder(w).Encode(data) } diff --git a/handlers/scheduler.go b/handlers/scheduler.go deleted file mode 100644 index df0e106..0000000 --- a/handlers/scheduler.go +++ /dev/null @@ -1,42 +0,0 @@ -package handlers - -import ( - "encoding/json" - "net/http" - "os" - "slideshowApp/utils" -) - -var scheduleFile = "./data/schedule.json" - -type Schedule map[string]any - -func SaveSchedule(w http.ResponseWriter, r *http.Request) { - var s Schedule - if err := json.NewDecoder(r.Body).Decode(&s); err != nil { - utils.SendJSONError(w, "Invalid input", http.StatusBadRequest) - return - } - - data, err := json.MarshalIndent(s, "", " ") - if err != nil { - utils.SendJSONError(w, "Encoding failed", http.StatusInternalServerError) - return - } - - err = os.WriteFile(scheduleFile, data, 0644) - if err != nil { - utils.SendJSONError(w, "write file failed", http.StatusInternalServerError) - return - } - w.WriteHeader(http.StatusOK) -} - -func GetSchedule(w http.ResponseWriter, r *http.Request) { - data, err := os.ReadFile(scheduleFile) - if err != nil { - json.NewEncoder(w).Encode(Schedule{}) - return - } - w.Write(data) -} diff --git a/handlers/settings.go b/handlers/settings.go new file mode 100644 index 0000000..57ef537 --- /dev/null +++ b/handlers/settings.go @@ -0,0 +1,81 @@ +package handlers + +import ( + "encoding/json" + "fmt" + "net/http" + "os" + "path/filepath" + "runtime" + "slideshowApp/env" + "slideshowApp/utils" +) + +var settingsFile = "settings.json" + +type Settings map[string]any + +func SaveSettings(w http.ResponseWriter, r *http.Request) { + var s Settings + if err := json.NewDecoder(r.Body).Decode(&s); err != nil { + fmt.Println(12, err) + utils.SendJSONError(w, "Invalid input", http.StatusBadRequest) + return + } + + data, err := json.MarshalIndent(s, "", " ") + if err != nil { + fmt.Println(13, err) + + utils.SendJSONError(w, "Encoding failed", http.StatusInternalServerError) + return + } + + err = os.WriteFile(getFilePath(), data, 0644) + if err != nil { + fmt.Println(14, err) + + utils.SendJSONError(w, "write file failed", http.StatusInternalServerError) + return + } + w.WriteHeader(http.StatusOK) +} + +func GetSettings(w http.ResponseWriter, r *http.Request) { + data, err := os.ReadFile(getFilePath()) + if err != nil { + json.NewEncoder(w).Encode(Settings{"default_interval": GetInterval()}) + return + } + w.Write(data) +} + +func GetInterval() string { + data, err := os.ReadFile(getFilePath()) + if err != nil { + interval := env.IntervalDefault.GetValue() + if interval == "" { + interval = "10" + } + return interval + } + var settings Settings + err = json.Unmarshal(data, &settings) + if err != nil { + return "10" + } + + if interval, ok := settings["default_interval"]; ok { + return interval.(string) + } + return "10" +} + +func getFilePath() string { + switch runtime.GOOS { + case "linux": + return filepath.Join(".", "data", settingsFile) + default: + return settingsFile + } +} diff --git a/main.go b/main.go index e056832..2bb6941 100644 --- a/main.go +++ b/main.go @@ -50,8 +50,8 @@ func main() { r.HandleFunc("/ws", handlers.Websocket) r.HandleFunc("/upload", handlers.UploadHandler).Methods("POST") r.HandleFunc("/settings", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, staticFolder+"settings.html") }) - r.HandleFunc("/api/save-schedule", handlers.SaveSchedule).Methods("POST") - r.HandleFunc("/api/get-schedule", handlers.GetSchedule).Methods("GET") + r.HandleFunc("/api/save-settings", handlers.SaveSettings).Methods("POST") + r.HandleFunc("/api/get-settings", handlers.GetSettings).Methods("GET") r.HandleFunc("/api/delete", handlers.DeleteHandler).Methods("POST") r.HandleFunc("/manage", func(w http.ResponseWriter, r *http.Request) { diff --git a/web/static/frame.html b/web/static/frame.html index 6c8f893..ebac530 100644 --- a/web/static/frame.html +++ b/web/static/frame.html @@ -33,7 +33,7 @@ @@ -58,6 +58,18 @@ const speedInput = document.getElementById('speed'); const shuffleStatus = document.getElementById('shuffleStatus'); + async function initializeSlideshow() { + // 1. Get the default interval from API + const defaultInterval = await checkDefaultInterval(); + speedInput.value = defaultInterval; + + // 2. Setup QR Code + setupQRCode(); + + // 3. Load Images (which eventually calls start()) + loadImages(); + } + // Fisher-Yates Shuffle Algorithm function shuffleArray(array) { for (let i = array.length - 1; i > 0; i--) { @@ -75,10 +87,23 @@ index = 0; } - async function checkSchedule() { + async function checkDefaultInterval() { try { - const res = await fetch('/api/get-schedule'); - const schedule = await res.json(); + const res = await fetch('/api/get-settings'); + const settings = await res.json(); + + // Return the saved interval, or fallback to 10 if it's missing + return settings.default_interval || "120"; + } catch (err) { + console.error("Failed to fetch default interval:", err); + return "120"; + } + } + + async function checkSettings() { + try { + const res = await fetch('/api/get-settings'); + const settings = await res.json(); const now = new Date(); const day = now.toLocaleDateString('en-US', { weekday: 'long' }); @@ -86,9 +111,9 @@ const currentTime = now.getHours().toString().padStart(2, '0') + ":" + now.getMinutes().toString().padStart(2, '0'); - const isActive = schedule[day + "_active"]; - const start = schedule[day + "_start"]; - const end = schedule[day + "_end"]; + const isActive = settings[day + "_active"]; + const start = settings[day + "_start"]; + const end = settings[day + "_end"]; // Check if we should be "OFF" if (isActive && (currentTime < start || currentTime > end)) { @@ -131,7 +156,7 @@ async function showNext() { if (playlist.length === 0) return; - const isRunning = await checkSchedule(); + const isRunning = await checkSettings(); if (!isRunning) return; viewer.classList.replace('fade-in', 'fade-out'); @@ -205,8 +230,7 @@ speedInput.addEventListener('change', start); // Initial setup - setupQRCode(); - loadImages(); + initializeSlideshow(); \ No newline at end of file diff --git a/web/static/settings.html b/web/static/settings.html index b5280d6..210307b 100644 --- a/web/static/settings.html +++ b/web/static/settings.html @@ -8,24 +8,41 @@
-

Weekly Scheduler

+

Slideshow Settings

Back
-
- - - - - - - - - - - -
DayEnabledStart TimeEnd Time
- + +
+

General Settings

+
+ + +
+
+ +
+ +
+

Weekly Scheduler

+ + + + + + + + + + + +
DayEnabledStart TimeEnd Time
+
+ +
@@ -47,32 +64,57 @@ // Load existing settings async function loadSettings() { - const res = await fetch('/api/get-schedule'); - const data = await res.json(); - Object.keys(data).forEach(key => { - const el = document.querySelector(`[name="${key}"]`); - if(el.type === 'checkbox') el.checked = data[key]; - else el.value = data[key]; - }); + try { + const res = await fetch('/api/get-settings'); + const data = await res.json(); + + Object.keys(data).forEach(key => { + const el = document.querySelector(`[name="${key}"]`); + if (el) { + if (el.type === 'checkbox') el.checked = data[key]; + else el.value = data[key]; + } + }); + } catch (err) { + console.error("Failed to load settings:", err); + } } document.getElementById('scheduleForm').onsubmit = async (e) => { e.preventDefault(); const formData = new FormData(e.target); const obj = {}; - formData.forEach((value, key) => { - // Handle checkbox value manually - if (key.includes('_active')) obj[key] = true; - else obj[key] = value; - }); - // Ensure unchecked boxes are false - days.forEach(day => { if(!obj[day+'_active']) obj[day+'_active'] = false; }); - await fetch('/api/save-schedule', { + formData.forEach((value, key) => { + // Convert number fields to integers + if (key === 'default_interval') { + obj[key] = parseInt(value); + } + // Handle checkbox presence + else if (key.includes('_active')) { + obj[key] = true; + } + else { + obj[key] = value; + } + }); + + // Ensure unchecked boxes are sent as false + days.forEach(day => { + if (!obj[day + '_active']) obj[day + '_active'] = false; + }); + + const res = await fetch('/api/save-settings', { method: 'POST', + headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(obj) }); - alert("Schedule Saved!"); + + if (res.ok) { + alert("Settings Saved Successfully!"); + } else { + alert("Error saving settings."); + } }; loadSettings();