feat: share post to other apps
This commit is contained in:
@@ -59,9 +59,36 @@ func (h *PostHandler) Create(w http.ResponseWriter, r *http.Request) {
|
||||
response.JSON(w, http.StatusCreated, p)
|
||||
}
|
||||
|
||||
// Reshare records the caller as having reshared the post identified
|
||||
// by {id}. Idempotent. Returns 204 on success; conflict for the
|
||||
// "reshare your own post" case surfaces as 400 via mapSocialErr's
|
||||
// fallthrough (errors.New wrapper in the service).
|
||||
func (h *PostHandler) Reshare(w http.ResponseWriter, r *http.Request) {
|
||||
uid := middleware.UserID(r.Context())
|
||||
id := chi.URLParam(r, "id")
|
||||
if err := h.svc.Reshare(r.Context(), id, uid); err != nil {
|
||||
mapSocialErr(w, err)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
// Unreshare removes a previously recorded reshare. Idempotent.
|
||||
func (h *PostHandler) Unreshare(w http.ResponseWriter, r *http.Request) {
|
||||
uid := middleware.UserID(r.Context())
|
||||
id := chi.URLParam(r, "id")
|
||||
if err := h.svc.Unreshare(r.Context(), id, uid); err != nil {
|
||||
mapSocialErr(w, err)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func (h *PostHandler) Get(w http.ResponseWriter, r *http.Request) {
|
||||
id := chi.URLParam(r, "id")
|
||||
p, err := h.svc.Get(r.Context(), id)
|
||||
// viewerID is "" for anonymous viewers — the service treats that as
|
||||
// "no reshare hydration" so the public-cache shape is unchanged.
|
||||
p, err := h.svc.Get(r.Context(), id, middleware.UserID(r.Context()))
|
||||
if err != nil {
|
||||
mapSocialErr(w, err)
|
||||
return
|
||||
@@ -420,7 +447,10 @@ func (h *ProfileHandler) Get(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
// Feed returns posts for the public feed. Same payload as ListMine but
|
||||
// looked up by handle so it's reachable anonymously.
|
||||
// looked up by handle so it's reachable anonymously. When an
|
||||
// authenticated viewer hits this route (via OptionalAuth) each post
|
||||
// carries `viewer_has_reshared` so the action footer renders the right
|
||||
// button. Anonymous viewers get `false` for every post at zero cost.
|
||||
func (h *ProfileHandler) Feed(w http.ResponseWriter, r *http.Request) {
|
||||
handle := chi.URLParam(r, "handle")
|
||||
limit, offset := parseLimitOffset(r)
|
||||
@@ -429,6 +459,29 @@ func (h *ProfileHandler) Feed(w http.ResponseWriter, r *http.Request) {
|
||||
mapSocialErr(w, err)
|
||||
return
|
||||
}
|
||||
viewerID := middleware.UserID(r.Context())
|
||||
if viewerID != "" && len(posts) > 0 {
|
||||
ids := make([]string, 0, len(posts))
|
||||
for i := range posts {
|
||||
// Skip own posts — can't reshare yourself, and the swap
|
||||
// already triggers on isOwner.
|
||||
if posts[i].UserID != viewerID {
|
||||
ids = append(ids, posts[i].ID)
|
||||
}
|
||||
}
|
||||
if len(ids) > 0 {
|
||||
states, err := h.posts.ReshareStatesFor(r.Context(), viewerID, ids)
|
||||
if err != nil {
|
||||
mapSocialErr(w, err)
|
||||
return
|
||||
}
|
||||
for i := range posts {
|
||||
if states[posts[i].ID] {
|
||||
posts[i].ViewerHasReshared = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
response.JSONWithMeta(w, http.StatusOK, posts, paginationMeta(total, limit, offset))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user