Conversation
saveWorkspaceVersionTS used to look only for [workspaces.<tomlKey>].
When tomlKey fell back to the raw team ID it appended a second block
next to the slug-keyed one, and Load then refused to start ("both
reference team_id").
Merge leftover team-ID-keyed prefs into the slug block, drop the
duplicate key, and write subsequent saves into the existing slug
section (or a matching team_id field).
users.conversations IM objects sometimes omit `user`, so the sidebar row was blank and the unresolved-DM sweep had nothing to fetch. Overlay counterparties from userBoot's ims[], seed display names from edge before the first paint, and patch wctx.Channels so a workspace switch keeps the resolved name. DMNameResolvedMsg now carries TeamID so a late resolution from an inactive workspace cannot rename the active sidebar.
DMs are the daily-driver conversations; they belong under Threads, not at the bottom of the rail after custom sections. Config-mode order is now DMs, custom sections, Apps, Channels. Slack-mode keeps the provider linked list but lifts direct_messages to the top.
Add an Activity view backed by the unofficial activity.feed / activity.views endpoints and client.counts activity_v2. A synthetic Activity row sits above Threads with an unread badge; the pane supports filter/sort/unread-only, compact and detailed density, and jump-to-message. Prefs live in [activity] in config.toml. This is unofficial Slack protocol, same class as the rest of slk — it can change without notice.
|
@agustif — thank you for this, it's a lot of careful work and several parts of it are genuinely better than what I'm merging. I'm going with #109 though, and I want to be straight with you about why rather than leave you guessing. 1. Row content. #109 hydrates message bodies via 2. All bot DMs are silently dropped. 3. Process. #109 was open a month, went through two rounds of my review, and I'd already told the author it was ready to merge. I'm not going to leapfrog that. Also, for the record: Three things in here I want, and will happily take as standalone PRs against main, credited to you:
Two pieces of process feedback, offered constructively: Please stop stacking feature PRs. This is 45 files because it carries #166, #167 and #168 underneath it. Even measured against #168 it's still 38 files / +3220. Reviewing it means reviewing four PRs at once, and that's a large part of why it sat. I'm reviewing those three separately on their own merits. And per CONTRIBUTING, open an issue first for something this size. #12 was the right place — and doing that would have surfaced #109 before you built this, which would have saved you a lot of work. That's the actual purpose of the rule, not bureaucracy. If you want to fix Closing as superseded. I'd genuinely like those three follow-ups. |
…ed PRs TestBackgroundFetchRetriesAfterBackoffExpiry used two barriers that do not actually gate the state it asserts on, so it failed intermittently in CI on PRs that do not touch this package (gammons#163, gammons#166, gammons#169). Both barriers were false: - fakeMemberAPI records a call on *entry*, but backgroundFetch writes lastFailed only after the API call returns. Backdating lastFailed after waitForCallCount(1) therefore raced the manager's own write and got clobbered, leaving the backoff live so the retry never fired: "timed out waiting for 2 API calls". - EnsureFresh calls pushSnapshot synchronously on the caller's goroutine, so waitForPush(sink, 2) was satisfied by the test's own second EnsureFresh rather than by the background fetch. The lastFailed assertion then ran while that fetch was still in flight: "lastFailed not cleared by a successful fetch". Replace both with waitUntil, which polls the manager state under its own lock. Add an optional post-call delay to fakeMemberAPI and use it here, so the slow-API interleaving that used to be a rare race is now the test's default path. Verified: with the 50ms delay the old test failed 5/5; the new one passes 20/20 under -race, and still fails as intended when `delete(m.lastFailed, channelID)` is removed from manager.go.
Why
Slack's Activity inbox (mentions, DMs, reactions, …) is the other half of "what needs my attention" next to Threads. slk had no view for it.
What
activity.feed/activity.viewsclient (unofficial Slack protocol, same class as the rest of slk — it can change without notice).activity_v2unread badge fromclient.counts.[activity]in config.toml.Test plan
go test ./internal/config/ ./internal/slack/ ./internal/bootstrap/ ./internal/ui/ ./internal/ui/sidebar/ ./internal/ui/activityview/ ./cmd/slk/client.counts.Merge after #168 (stack 4/4). Contains the full stack. Testdata is sanitized API JSON (no tokens).