marky

Lightweight bookmarking + plaintext archive
Log | Files | Refs | README | LICENSE

commit 8a7e253126aa473b0c63bbd3b16a61832be1e546
parent 629ef0c8e8937b5719a4e6c2e9eaba5d94303da2
Author: David Eisinger <[email protected]>
Date:   Thu,  9 Oct 2025 13:48:49 -0400

Remove initial API call

Diffstat:
Minternal/api.go | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Minternal/web/app.js | 8+++++++-
2 files changed, 77 insertions(+), 28 deletions(-)

diff --git a/internal/api.go b/internal/api.go @@ -1,6 +1,7 @@ package internal import ( + "bytes" "context" "encoding/json" "encoding/xml" @@ -378,22 +379,43 @@ func NewHandlerWithConfig(db *DB, cfg HandlerConfig) (http.Handler, error) { return } // New user page route: /u:{username} - if strings.HasPrefix(p, "u:") { - uname := strings.TrimPrefix(p, "u:") - if uname == "" || strings.Contains(uname, "/") { - http.NotFound(w, r) - return - } - if u, err := db.GetUserByUsername(r.Context(), uname); err == nil && u != nil { - if html, err := RenderPage("user.html", cfg); err == nil { - w.Header().Set("Content-Type", "text/html; charset=utf-8") - _, _ = w.Write(html) - return - } - } - http.NotFound(w, r) - return - } + if strings.HasPrefix(p, "u:") { + uname := strings.TrimPrefix(p, "u:") + if uname == "" || strings.Contains(uname, "/") { + http.NotFound(w, r) + return + } + if u, err := db.GetUserByUsername(r.Context(), uname); err == nil && u != nil { + if html, err := RenderPage("user.html", cfg); err == nil { + // If owner viewing own page, embed initial bookmarks to avoid client fetch + if isOwnerAuthorized(r, u, db) { + items, err := db.ListBookmarks(r.Context(), u.ID, 50, 0) + if err == nil { + resp := make([]bookmarkResponse, 0, len(items)) + for i := range items { + resp = append(resp, toRespWithArchive(r.Context(), db, &items[i])) + } + if b, err := json.Marshal(resp); err == nil { + inject := []byte("<script>window.MARKY_INITIAL={view:'self',user:" + strconv.Quote(u.Username) + ",results:" + string(b) + "}</script>\n") + marker := []byte("<script src=\"/app.js\"></script>") + if i := bytes.Index(html, marker); i >= 0 { + out := make([]byte, 0, len(html)+len(inject)) + out = append(out, html[:i]...) + out = append(out, inject...) + out = append(out, html[i:]...) + html = out + } + } + } + } + w.Header().Set("Content-Type", "text/html; charset=utf-8") + _, _ = w.Write(html) + return + } + } + http.NotFound(w, r) + return + } if strings.HasSuffix(p, ".json") || strings.HasSuffix(p, ".rss") { // Extract username and format format := "json" @@ -436,17 +458,38 @@ func NewHandlerWithConfig(db *DB, cfg HandlerConfig) (http.Handler, error) { } } // Legacy username route: "/{username}" → serve user page when user exists - if !strings.Contains(p, "/") && !strings.Contains(p, ".") { - if u, err := db.GetUserByUsername(r.Context(), p); err == nil && u != nil { - if html, err := RenderPage("user.html", cfg); err == nil { - w.Header().Set("Content-Type", "text/html; charset=utf-8") - _, _ = w.Write(html) - return - } - } - http.NotFound(w, r) - return - } + if !strings.Contains(p, "/") && !strings.Contains(p, ".") { + if u, err := db.GetUserByUsername(r.Context(), p); err == nil && u != nil { + if html, err := RenderPage("user.html", cfg); err == nil { + // Owner initial embed for legacy route + if isOwnerAuthorized(r, u, db) { + items, err := db.ListBookmarks(r.Context(), u.ID, 50, 0) + if err == nil { + resp := make([]bookmarkResponse, 0, len(items)) + for i := range items { + resp = append(resp, toRespWithArchive(r.Context(), db, &items[i])) + } + if b, err := json.Marshal(resp); err == nil { + inject := []byte("<script>window.MARKY_INITIAL={view:'self',user:" + strconv.Quote(u.Username) + ",results:" + string(b) + "}</script>\n") + marker := []byte("<script src=\"/app.js\"></script>") + if i := bytes.Index(html, marker); i >= 0 { + out := make([]byte, 0, len(html)+len(inject)) + out = append(out, html[:i]...) + out = append(out, inject...) + out = append(out, html[i:]...) + html = out + } + } + } + } + w.Header().Set("Content-Type", "text/html; charset=utf-8") + _, _ = w.Write(html) + return + } + } + http.NotFound(w, r) + return + } } static.ServeHTTP(w, r) }) diff --git a/internal/web/app.js b/internal/web/app.js @@ -59,7 +59,13 @@ createApp({ if (this.me && this.me.username === this.viewUser) { this.view = 'self'; this.fetchApiPresence(); - this.search(); + // Initialize from server-embedded data when available + try { + if (window.MARKY_INITIAL && window.MARKY_INITIAL.view === 'self' && window.MARKY_INITIAL.user === this.me.username) { + this.results = Array.isArray(window.MARKY_INITIAL.results) ? window.MARKY_INITIAL.results : []; + } + } catch {} + // Do not auto-fetch all bookmarks on initial load } else { this.view = 'public'; this.loadPublic();