The fake was declared in RootFlowNodeTest, so other tests could not use
it. Move it to the testutils module, in a new node package.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The fake presenter was declared in RootFlowNodeTest, so other tests could
not use it. Move it to the testutils module, in a new presenter package,
along with MutablePresenter.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* Keep the send button when the composer is emptied while editing
rememberEndButtonParams checked whether the composer had sendable text
before it checked whether the user was editing a message, so clearing
the text of a message being edited replaced the send button with the
voice recorder button. Starting a recording from there abandons the
edit.
Check the editing branch first, as the formatting composer already does,
and let it render a disabled send button when there is nothing to send.
* Update screenshots
* Give the room name in the timeline top bar a 48dp tap target
The row carrying the room avatar and name is the control that opens the
room details, but it is only as tall as its content, which is under the
48dp minimum recommended for a touch target. Constrain it to a minimum
height of 48dp. The children stay centred inside the app bar, so nothing
moves visually.
* Update screenshots
The accessibility snapshot of the timeline is the only one the change
affects: the node which opens the room details now reports a 48dp tall
bounding box. The room name, the avatar and the icons stay where they
were.
* Show a Message not found placeholder when a replied to message cannot be loaded
When the replied to event could not be fetched, the reply preview rendered the
raw SDK error string in critical styling, and tapping it emitted a focus
request that could never succeed, so the user got a dead end dialog.
Render the localised error_message_not_found string in the neutral italic style
already used for redacted and undecryptable replies, and drop the click handler
for that case. The existing key is reused rather than adding a new one; a "you
do not have access" wording was rejected because this state covers any failure
to load the event, not only a permission problem.
* Update screenshots
* Trigger CI after recording screenshots
---------
Co-authored-by: ElementBot <android@element.io>
It's sadly faster that way:
Every time we run a test class in parallel a new JVM is started, and the `KoScope` contents can't be shared between them.
This scope can take a few minutes to load, so having several instances of this happening at the same time is a terrible idea.
It's actually faster to run the tests sequentially, at least locally.
* Fix insets in several screens
UI components in the room list, room member list, etc. now have better insets based on `WindowInsets.safeDrawing`
* Update screenshots
---------
Co-authored-by: ElementBot <android@element.io>
* Make settings section separators visible in black theme
In the Black (OLED) theme the canvas is forced to pure black while the
section-separator divider keeps its standard-dark colour (outlineVariant,
~10% alpha white), leaving dividers in Settings and related screens almost
invisible. Add an OLED-aware listSectionDivider alias that lightens the
divider only when the black theme is active, and use it for the
ListSectionHeader divider. Light and standard-dark themes are unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
* Set separatorSecondary for Black theme instead of a custom divider alias
Following review feedback: now that the global HorizontalDivider uses
separatorSecondary (#7054), give the Black/OLED theme a visible
separatorSecondary value in ElementTheme instead of carrying a bespoke
listSectionDivider alias. This fixes all separators on pure black, not
just section headers. The exact color is pending design confirmation.
* chore(theme): remove in-code design discussion comment
Move design discussion out of the code per review; the divider color
decision lives in the PR thread.
* Update screenshots
Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
---------
Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: ElementBot <android@element.io>
Co-authored-by: Jorge Martin Espinosa <jorgem@element.io>
* Try making `HeaderFooterView` more robust
Create `HeaderFooterLayout` to properly calculate the content size when the component is scrollable so it's at least the size of the available space.
* Make `DesktopNoticeView` scrollable
For this, `NumberedListOrganism` can't be a `LazyColumn`, since that's a lazy layout with no intrinsic height and Compose doesn't know how to size it.
* Fix the case where no header or content composables are supplied
* Fix insets in non-scrollable UI
* Remove `movableContentOf`, suppress the warning instead since the `isScrollable` parameter should never toggle this behavior
* Update screenshots
---------
Co-authored-by: ElementBot <android@element.io>
* Use the right insets in the home screen UI
That's `WindowInsets.statusBar` for the `Scaffold` component, then `WindowInsets.navigationBar` for the `LazyColum.contentPadding`
* Apply it to other screens with long lists of items too
* Apply the insets to `PreferencePage` too
* Apply inset changes to other screens with scrollable content
* Add helper insets/padding values based on review suggestions.
* Use the newly added insets/padding values in several scaffold and scrollable columns
---------
Co-authored-by: ElementBot <android@element.io>
* When no URL is provided to `ContentValidationState.collectMediaState`, assume it's valid
That way we can do:
`if (validationState.isValid() && state.collectMediaState(possiblyNullUrl).isValid()) ...`
* Remove the `eventId` param from `ContentScannerService.scan`
It's not really used, since we then provide a state that can be mutated, and fetching that is what the previous parameter was used for
* Make sure to always validate the medias in the viewer, both the actual media and the thumbnail
* Update screenshots
---------
Co-authored-by: ElementBot <android@element.io>
* Remove no longer temporary string
These are now in localazy and the sync strings CI flow was failing because we have 2 conflicting values in `temporary.xml` and `localazy.xml`
* Use the right placeholder value in `screen_local_network_opt_in_subtitle`
* Localazy: improve search, parallelize checks
The search for XML files has been narrowed down and it's several times faster now, and processing the files is now done in parallel
* Improve script to also find and delete previous files
Also add the option of having a `-v|--verbose` flag to print which files we're modifying
* Use `LocalBuildMeta` to get the app name inside `LocalNetworkPermissionDialogView`
* Allow finding all the forbidden terms in the strings and translations and then return an error exit code instead of a success one
---------
Co-authored-by: ElementBot <android@element.io>
* Remove no longer temporary string
These are now in localazy and the sync strings CI flow was failing because we have 2 conflicting values in `temporary.xml` and `localazy.xml`
* Use the right placeholder value in `screen_local_network_opt_in_subtitle`
* Update screenshots
---------
Co-authored-by: ElementBot <android@element.io>