commits
Turn off React Query's structural sharing for now-playings so new arrays
are treated as changes. Also pass values directly to setQueryData for
now-playings and scrobblesChart instead of updater functions.
Make the client update now-playings by assigning a fresh array and
disable redundant invalidations. Adjust the websocket message shape so
the fields arrive at the top level for the client to consume.
Add publish_user that sends user JSON over NATS and call it after
committing user-related transactions. Thread an async_nats::Client
through save_scrobble and the websocket handler. Change save_user to
return the user's xata_id and remove the per-publish NATS connection
spawn in favor of a shared client created in the subscriber.
Add an outer try/catch around MusicBrainz hydrate requests, log
failures, and only assign mbId/artists when the lookup succeeds to avoid
throwing on lookup errors
Wrap /hydrate request in try/catch and set mbTrack to null on failure
Fetch all-time top track and fall back to it when the 7-day query is
empty. Wait for both queries to finish before rendering and use the
first available track for title, artist and album art.
Wire startDate/endDate through lexicons, PKL defs, TypeScript types, and
xrpc handlers to allow date-range filtering for actor albums, artists,
and songs.
Fix lexicon index mappings: swap artist getArtist/getArtistAlbums
entries, add feed.getFeed method, and reorder imports. Minor formatting
tweaks (scrobble likes filter, PKL whitespace).
Bind optional start_date/end_date as Option<&str> so None becomes SQL
NULL and use CAST(? AS TIMESTAMP) to filter ranges. Return
MAX(s.created_at) as created_at (last played) and fix
play_count/unique_listeners column indexes. Use i64 pagination values
and duckdb::params! for parameter binding; place LIMIT before OFFSET in
queries.
Introduce start_user_thread helper to spawn per-user threads with
automatic retries, exponential backoff, and NATS publish after max
retries for external restart. Replace direct thread spawns with the
helper. Improve progress tracker by adding an inner recovery loop,
fixing cache update logic, and handling Redis errors gracefully.
Call extractPdsFromDid(repo) to obtain the PDS base URL and pass it to
AtpAgent instead of using the hardcoded https://bsky.social. Compute the
repo once from trackWithUri.uri and reuse it for getRecord.
Import and and not from drizzle-orm and require lovedTracks.uri to be
non-null so only valid loved tracks are returned
Show @handle next to display name, remove underline styling, and call
scrollToTop when opening profiles (imported helper). ReplyModal no
longer closes the modal on profile link click.
Add null checks and early returns in Handle to avoid using an undefined
profile.did. Add profile.data?.did to effect deps and use "" fallbacks
when checking Set membership. Fix useActorCompatibilityQuery type
(undefined) and remove unused LabelMedium import. Use empty-string
fallback when calling useFollowersInfiniteQuery.
Implement compatibility API client and add Compatibility type and
Profile type. Add useActorCompatibilityQuery hook and a new
Compatibility component included in the profile Overview. Also add
Authorization header for the compatibility request, update API client
typings, and apply small UI and null-safety fixes (Stats label markup,
profile follow handling, and follower query typing).
Implement XRPC handler, lexicon and PKL definitions, and generated TS
types. Add analytics compatibility types and register the handler. Apply
small web UI fixes (replace anchor with Link, adjust z-index).
Add apps/web/src/lib/scrollToTop.ts and import it in profile pages.
Replace duplicated inline scroll logic with scrollToTop(), call it when
navigating to profile links. Convert external <a> to internal Link and
narrow route prop types from any to string
Add an id to the main container and a scrollToTop helper that
smooth-scrolls #app-container to top. Call it alongside setActiveKey on
profile Links and replace the external anchor with an internal Link.
Update SignInModal copy and classes for the handle prompt and link. Add
z-index and dialog/background overrides to the ApiKeys modal and adjust
the Close color. Set input backgrounds, borders, text and caret colors
and restyle Cancel/Create buttons (colors, hover and shape).
Introduce neighbourViewBasic schema and
app.rocksky.actor.getActorNeighbours lexicon. Implement XRPC handler,
wire into TS lexicon index and types, and add analytics types/handler
support for neighbour data
Prepopulate whereConditions with arrayContains(...) for each genre.
Remove redundant arrayContains from innerJoin and simplify the join to
match only artistId, always applying where(and(...whereConditions)).
Remove prepopulated arrayContains genre filters from algorithm handlers
and use an empty whereConditions array. Move the genre filter into the
join and guard the .where call when there are no conditions.
Add API getScrobbles and hooks for paginated scrobbles Introduce
followingFeed atom and wire it into Feed to switch between generator
feed and following scrobbles and handle infinite scrolling, loading
state, and empty state Add "following" category to FeedGenerators
(hidden when not logged in)
When following=true and a viewer DID is provided, retrieve the viewer's
followed subject DIDs and restrict scrobbles to those actors. Return an
empty array if the viewer follows no one. Update lexicon and type defs
and import inArray for the DB query.
Add optional "dids" query param to getFollows lexicon and server logic;
use inArray only when dids are provided and parse cursor via
Number(cursor). Wire frontend to pass dids and sanitize limit. Replace
followsAtom with a Set for efficient membership checks, add Followers
and Follows pages with infinite scroll, add activeTab atom, and add
SignInModal follow support. Also minor style tweak to default button
color.
Support optional "dids" array query param in lexicon/schema and server
handler (use inArray) to filter followers. Add web client endpoints,
React hooks, follows atom, and follow/unfollow mutations plus a Follow
button in the profile UI.
Order follow queries by follows.createdAt DESC and apply a limit
(default 50). Use a createdAt timestamp cursor (lt) and return the next
cursor in responses.
Add publish_user that sends user JSON over NATS and call it after
committing user-related transactions. Thread an async_nats::Client
through save_scrobble and the websocket handler. Change save_user to
return the user's xata_id and remove the per-publish NATS connection
spawn in favor of a shared client created in the subscriber.
Wire startDate/endDate through lexicons, PKL defs, TypeScript types, and
xrpc handlers to allow date-range filtering for actor albums, artists,
and songs.
Fix lexicon index mappings: swap artist getArtist/getArtistAlbums
entries, add feed.getFeed method, and reorder imports. Minor formatting
tweaks (scrobble likes filter, PKL whitespace).
Bind optional start_date/end_date as Option<&str> so None becomes SQL
NULL and use CAST(? AS TIMESTAMP) to filter ranges. Return
MAX(s.created_at) as created_at (last played) and fix
play_count/unique_listeners column indexes. Use i64 pagination values
and duckdb::params! for parameter binding; place LIMIT before OFFSET in
queries.
Introduce start_user_thread helper to spawn per-user threads with
automatic retries, exponential backoff, and NATS publish after max
retries for external restart. Replace direct thread spawns with the
helper. Improve progress tracker by adding an inner recovery loop,
fixing cache update logic, and handling Redis errors gracefully.
Add null checks and early returns in Handle to avoid using an undefined
profile.did. Add profile.data?.did to effect deps and use "" fallbacks
when checking Set membership. Fix useActorCompatibilityQuery type
(undefined) and remove unused LabelMedium import. Use empty-string
fallback when calling useFollowersInfiniteQuery.
Implement compatibility API client and add Compatibility type and
Profile type. Add useActorCompatibilityQuery hook and a new
Compatibility component included in the profile Overview. Also add
Authorization header for the compatibility request, update API client
typings, and apply small UI and null-safety fixes (Stats label markup,
profile follow handling, and follower query typing).
Add optional "dids" query param to getFollows lexicon and server logic;
use inArray only when dids are provided and parse cursor via
Number(cursor). Wire frontend to pass dids and sanitize limit. Replace
followsAtom with a Set for efficient membership checks, add Followers
and Follows pages with infinite scroll, add activeTab atom, and add
SignInModal follow support. Also minor style tweak to default button
color.