Enhance API and frontend components for character management and map visibility
- Updated API documentation to include `ownedByMe` field in character responses, indicating if a character was last updated by the current user's tokens. - Modified MapView component to track and display the live status based on user-owned characters. - Enhanced map data handling to exclude hidden maps for non-admin users and improved character icon representation on the map. - Refactored character data structures to support new properties and ensure accurate rendering in the frontend.
This commit is contained in:
@@ -170,6 +170,9 @@ type Session struct {
|
||||
TempAdmin bool
|
||||
}
|
||||
|
||||
// ClientUsernameKey is the context key for the username that owns a client token (set by client handlers).
|
||||
var ClientUsernameKey = &struct{ key string }{key: "clientUsername"}
|
||||
|
||||
// Character represents a game character on the map.
|
||||
type Character struct {
|
||||
Name string `json:"name"`
|
||||
@@ -178,6 +181,7 @@ type Character struct {
|
||||
Position Position `json:"position"`
|
||||
Type string `json:"type"`
|
||||
Updated time.Time
|
||||
Username string `json:"-"` // owner of the token that last updated this character; not sent to API
|
||||
}
|
||||
|
||||
// Marker represents a map marker stored per grid.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"log/slog"
|
||||
@@ -26,7 +27,8 @@ func (h *Handlers) ClientRouter(rw http.ResponseWriter, req *http.Request) {
|
||||
rw.WriteHeader(http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
_ = username
|
||||
ctx = context.WithValue(ctx, app.ClientUsernameKey, username)
|
||||
req = req.WithContext(ctx)
|
||||
|
||||
switch matches[2] {
|
||||
case "locate":
|
||||
|
||||
@@ -2,6 +2,7 @@ package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/andyleap/hnh-map/internal/app"
|
||||
)
|
||||
@@ -22,6 +23,17 @@ func (h *Handlers) APIConfig(rw http.ResponseWriter, req *http.Request) {
|
||||
JSON(rw, http.StatusOK, config)
|
||||
}
|
||||
|
||||
// CharacterResponse is the API shape for a character, including ownedByMe for the current session.
|
||||
type CharacterResponse struct {
|
||||
Name string `json:"name"`
|
||||
ID int `json:"id"`
|
||||
Map int `json:"map"`
|
||||
Position app.Position `json:"position"`
|
||||
Type string `json:"type"`
|
||||
Updated time.Time `json:"updated,omitempty"`
|
||||
OwnedByMe bool `json:"ownedByMe"`
|
||||
}
|
||||
|
||||
// APIGetChars handles GET /map/api/v1/characters.
|
||||
func (h *Handlers) APIGetChars(rw http.ResponseWriter, req *http.Request) {
|
||||
ctx := req.Context()
|
||||
@@ -35,7 +47,19 @@ func (h *Handlers) APIGetChars(rw http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
chars := h.Map.GetCharacters()
|
||||
JSON(rw, http.StatusOK, chars)
|
||||
out := make([]CharacterResponse, 0, len(chars))
|
||||
for _, c := range chars {
|
||||
out = append(out, CharacterResponse{
|
||||
Name: c.Name,
|
||||
ID: c.ID,
|
||||
Map: c.Map,
|
||||
Position: c.Position,
|
||||
Type: c.Type,
|
||||
Updated: c.Updated.UTC(),
|
||||
OwnedByMe: c.Username == s.Username,
|
||||
})
|
||||
}
|
||||
JSON(rw, http.StatusOK, out)
|
||||
}
|
||||
|
||||
// APIGetMarkers handles GET /map/api/v1/markers.
|
||||
|
||||
@@ -374,6 +374,8 @@ func (s *ClientService) UpdatePositions(ctx context.Context, data []byte) error
|
||||
return nil
|
||||
})
|
||||
|
||||
username, _ := ctx.Value(app.ClientUsernameKey).(string)
|
||||
|
||||
s.withChars(func(chars map[string]app.Character) {
|
||||
for id, craw := range craws {
|
||||
gd, ok := gridDataByID[craw.GridID]
|
||||
@@ -389,8 +391,9 @@ func (s *ClientService) UpdatePositions(ctx context.Context, data []byte) error
|
||||
X: craw.Coords.X + (gd.Coord.X * app.GridSize),
|
||||
Y: craw.Coords.Y + (gd.Coord.Y * app.GridSize),
|
||||
},
|
||||
Type: craw.Type,
|
||||
Updated: time.Now(),
|
||||
Type: craw.Type,
|
||||
Updated: time.Now(),
|
||||
Username: username,
|
||||
}
|
||||
old, ok := chars[id]
|
||||
if !ok {
|
||||
@@ -401,6 +404,7 @@ func (s *ClientService) UpdatePositions(ctx context.Context, data []byte) error
|
||||
chars[id] = c
|
||||
} else {
|
||||
old.Position = c.Position
|
||||
old.Username = username
|
||||
chars[id] = old
|
||||
}
|
||||
} else if old.Type != "unknown" {
|
||||
@@ -408,6 +412,7 @@ func (s *ClientService) UpdatePositions(ctx context.Context, data []byte) error
|
||||
chars[id] = c
|
||||
} else {
|
||||
old.Position = c.Position
|
||||
old.Username = username
|
||||
chars[id] = old
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user