chore: land the merged #155, #156 and #157 commits on master - #166
Merged
Merged
Conversation
…en (#155) * chore(i18n): add strings for admin and rooms load failures Nine admin failures and one for the rooms dashboard, in the source locale and all nine translations, so lint's MissingTranslation stays green once the call sites start using them. The wording follows the newer "Couldn't …" convention rather than the older "Failed to …", and each string names the action that failed, so the message says which part of the screen is empty rather than that something went wrong. * fix(admin): report a refused request instead of showing an empty screen Every AdminApi method returns Response<T>, so Retrofit throws only on IO: a 401, 403 or 500 arrives as an ordinary response with isSuccessful false and a null body. All ten hand-rolled try/catch blocks here were therefore unreachable for HTTP errors, and a refused request showed an empty Users tab, an empty Rooms tab and zeroed stat cards without a word. The catch fired only when the network itself failed, and then it printed the exception's own message. Each call now goes through apiBody / apiAction, which surfaces the server's own explanation when it sends one, falls back to the localized message when it does not, and classifies a thrown failure by type rather than showing its text. Two behaviours change with it. Local state is written only after a 2xx, so a rejected ban stops flipping the row and a refused settings toggle stops sitting on screen as though it had been accepted. And a tab holds its message until its spinner clears, because showSnackbar suspends until the message is dismissed. The overview's 30-second online-count poll keeps its silent catch: a background refresh that reported itself would put a snackbar on screen every 30 seconds for as long as the connection is down. * fix(dashboard): say why the room list failed, in the reader's language fetchRooms answered a non-2xx with the English literal "Failed to load rooms", discarding whatever the server had said, and answered a thrown failure with the exception's own message — so a lost connection reported itself as "Unable to resolve host \"bedrud.xyz\": No address associated with hostname", in every one of the nine locales. It now runs through apiBody like the room actions beside it: the server's explanation first, the localized message when there is none, and toUserMessage for a thrown failure. Cancellation still rethrows rather than being recorded as a network failure, which would put the refresh loop on its fast retry cadence. * docs: record how a failed API call must be reported The rule this change establishes app-wide, in the section that already describes the networking layer: screens call through apiBody / apiAction rather than hand-rolling try/catch, because an API method returning Response<T> makes a catch block unreachable for HTTP errors — the trap that left the admin screens silent. Also records the two rules that travel with the helpers (local state changes only on success; a load holds its message until its spinner clears) and the one deliberate exception, the admin overview's background poll.
Three screens still hosted the raw Material SnackbarHost, so a message on the meeting screen, the admin tabs or Add Server drew with the default 4dp corners while the same message on the dashboard, settings and the auth screens drew with the app's rounded token. The two styles were visible side by side in #152's own before/after images. All six scaffolds now go through BedrudSnackbarHost, which keeps the standard Material snackbar — its theme-aware inverse colours, action button and dismiss handling — and only replaces the shape.
* fix(instance): let the picker continue on a server already added The official-server card was disabled whenever the default instance was already stored, so a user signed out of it and backing out of the sign-in hub landed on a screen with nothing selectable, Continue permanently greyed, and no way forward but typing a different server or force-quitting. The disable was written for one entry point — "Add Server" from the instance list, where it kept the screen meaning "add a *new* one". The same screen also answers "which server am I signing in to?", and there the server being already stored is not a reason to refuse it: submit() has always routed an existing URL through switchTo(existing.id), so continuing on it switches and hands off to sign-in, which is what the user came for. The Added badge still says which one is already stored. The initial choice follows: it was CUSTOM whenever the default was added, which opened the screen with an empty field, a disabled Continue and the keyboard already up — presenting "type your own server" to someone who had chosen nothing. It is now always the official server. With no caller left disabling a card, ServerChoiceCard's enabled parameter and its dimming go too. * fix(nav): keep the sign-in hub behind the server picker The hub's back button navigated to the picker with popUpTo(0), clearing the whole stack. The picker became the only entry, so system back had nowhere to return to and the user was stuck there — the second half of the same dead end. It is pushed on top of the hub now, so back goes back. Landing after Continue follows the chosen server's own auth state rather than always being the hub. That mattered once the picker could continue on a server already stored: a user signed in to it would have been sent to sign in again, and the auth router does not rescue them, because none of its keys change when the instance switches to itself.
|
Dev build ready for this PR — installs alongside the real app (package id
Each downloads as a |
narseh-ir
approved these changes
Sep 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this lands
The three commits GitHub produced when #155, #156 and #157 were squash-merged, replayed onto
master:fix(admin): report a refused request instead of showing an empty screen (#155)fix(ui): give every snackbar the same corners (#156)fix(instance): let the picker continue on a server already added (#157)No new work. Every line here was already reviewed on those three pull requests.
Why it is needed
Those three pull requests were stacked: #155 targeted
fix/join-failure-silent, #156 targetedfix/localize-failure-messages, #157 targetedfix/unify-snackbar-hosts. GitHub retargets a stacked pull request to the parent's base only when the parent's head branch is deleted, and this repository keeps merged branches. So each one merged into its parent branch as written, and only #152 reachedmaster. The three changes were sitting onfix/unify-snackbar-hostsrather than on the default branch.Cherry-picking the squash commits keeps the history the repository already uses: one linear commit per pull request, each carrying its own number, instead of collapsing three reviewed changes into a single commit.
Verification
masterwithout conflict.git diff HEAD origin/fix/unify-snackbar-hostsis empty, so the resulting tree is identical to the branch that holds the merged work../gradlew lint testDebugUnitTest :app:assembleDevpasses on a tree carrying these three commits alongside the rest of the open pull requests.