feat: tags.pub global hashtag discovery integration (v3.8.0)

- Add setGlobalFollow/removeGlobalFollow/getFollowedTagsWithState to
  followed-tags storage; unfollowTag now preserves global follow state
- Add followTagGloballyController/unfollowTagGloballyController that
  send AP Follow/Undo via Fedify to tags.pub actor URLs
- Register POST /admin/reader/follow-tag-global and unfollow-tag-global
  routes with plugin reference for Fedify access
- Tag timeline controller passes isGloballyFollowed + error query param
- Tag timeline template adds global follow/unfollow buttons with globe
  indicator and inline error display
- Wire GET /api/v1/followed_tags to return real data with globalFollow state
- Add i18n keys: followGlobally, unfollowGlobally, globallyFollowing,
  globalFollowError
This commit is contained in:
Ricardo
2026-03-22 00:22:47 +01:00
committed by svemagie
parent 97a902bda1
commit a84c6f1abd
8 changed files with 237 additions and 11 deletions

View File

@@ -79,7 +79,12 @@ import {
instanceCheckApiController,
popularAccountsApiController,
} from "./lib/controllers/explore.js";
import { followTagController, unfollowTagController } from "./lib/controllers/follow-tag.js";
import {
followTagController,
unfollowTagController,
followTagGloballyController,
unfollowTagGloballyController,
} from "./lib/controllers/follow-tag.js";
import {
listTabsController,
addTabController,
@@ -392,6 +397,8 @@ export default class ActivityPubEndpoint {
router.patch("/admin/reader/api/tabs/reorder", reorderTabsController(mp));
router.post("/admin/reader/follow-tag", followTagController(mp));
router.post("/admin/reader/unfollow-tag", unfollowTagController(mp));
router.post("/admin/reader/follow-tag-global", followTagGloballyController(mp, this));
router.post("/admin/reader/unfollow-tag-global", unfollowTagGloballyController(mp, this));
router.get("/admin/reader/notifications", notificationsController(mp));
router.post("/admin/reader/notifications/mark-read", markAllNotificationsReadController(mp));
router.post("/admin/reader/notifications/clear", clearAllNotificationsController(mp));