* Fix warning about deprecated `keepRules.file` API
The proguard files have been moved to `app/proguard` in several directories for `common`, `foss`, and `enterprise` rules and it's those directories that are added through `keepRules.addStaticSourceDirectory(dir)`.
* Use `findPropery` instead of the deprecated `project.properties["key"]` API for `allWarningsAsErrors`
* Remove very legacy .gitignore rule and restore proguard `.keep` rules
* Make PIP react to camera orientation changes in the other participant's device
Adds a `controls.onPipMediaOrientationUpdate` callback for the WebView that will trigger a new `pipParamsBuilder.setAspectRatioFromOrientation(orientation)` method
* Fix warning about `PictureInPictureParams.Builder.setAspectRatio` only being available on API 26+
The fake was declared in RootFlowNodeTest, so other tests could not use
it. Move it to the testutils module, in the node package, and make its
documentation generic.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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>
MatrixSessionCache and SyncOrchestrator were in the di package, which
does not describe what they do. Move them, along with their tests, to a
session package, and extract FakeSyncOrchestratorFactory from
RootFlowNodeTest so that other tests can use it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
RootFlowNodeTest was declaring its own no-op fake, while the oauth test
module already provides one. Use it, and move it out of the customtab
package, since it is not specific to the custom tabs.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The fake was declared in RootFlowNodeTest, so other tests could not use
it. Move it next to the API it fakes, in a package mirroring the one of
the API, and let the result be provided by the caller, so that the case
where the account provider is not allowed can be tested too.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The fake was declared in RootFlowNodeTest, so other tests could not use
it. Move it next to the API it fakes, and let the cleared cache event
flow be provided by the caller, so that a test can emit events.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The fakes were declared in RootFlowNodeTest, so other tests could not use
them. Move each of them next to the API it fakes, following the existing
convention of a createNodeResult lambda defaulting to lambdaError():
- FakeLoginEntryPoint in features/login/test
- FakeBugReportEntryPoint in features/rageshake/test
- FakeSignedOutEntryPoint in features/signedout/test (new module)
- FakeAccountSelectEntryPoint in libraries/accountselect/test (new module)
The login and rageshake test modules did not have Appyx on their
classpath, so add the architecture module to their dependencies.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
At cold start two writers set the root nav target of RootFlowNode: the
intent path (handleIntent -> onLoginLink -> NotLoggedInFlow(params)) and
the first nav state emission (NotLoggedIn -> NotLoggedInFlow(null)).
safeRoot() only dedupes on strict equality, so the two targets do not
cancel each other out and the last writer wins, silently dropping the
login params.
Keep the params coming from the intent as pending state on the node, and
let the nav state observer take them into account, so that the root is
derived from both the logged in state and the pending login params, and
both orderings converge on the same target. The pending params are
cleared when leaving the not logged in flow, so that a later sign out
does not resurrect a stale provisioning link.
Also log when switching to the not logged in flow, since the drop was
silent. The login hint can contain an email address, so only its
presence is logged.
Closes#7482
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Tapping a room alias whose server is down left the resolver screen on a
spinner for as long as the screen stayed open, with no way forward other
than going back.
Bound the resolution with the ten second timeout already used when
joining a room by address, so the retry dialog is shown instead. The fake
client's resolve lambda becomes suspending so a server that never answers
can be simulated.
MainActivity is a singleTask activity that declares the elementx://open deep
link, so tapping a notification makes that deep link the base intent of the
task. When the user later brings the app back from the recents list, the
system replays that base intent with FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY, the
resolver turns it into a navigation again and the user is pushed back into the
room they had already left.
Ignore any intent the system replayed from the history, the same way the
launcher intent is already ignored.
* 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
* Request media audio focus when playing a voice message
Voice message playback asked for audio focus with
USAGE_VOICE_COMMUNICATION, the same bucket as Element Call and voice
message recording, while the player itself renders on the media stream.
Audio policy layers act on the declared usage, so a car head unit
switches to its call audio context and routes the playback away while
the player keeps running.
Declare USAGE_MEDIA (and STREAM_MUSIC on the legacy path) for playback,
which is what the player actually renders. Recording and Element Call
keep asking for voice communication focus.
* Keep playing a voice message through a short sound from another app
A notification, a navigation prompt or any other app taking focus for a
moment sends AUDIOFOCUS_LOSS_TRANSIENT or AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK,
and DefaultMediaPlayer pauses on it. The voice message stops part way
through and the user has to find it again and restart it.
Recording already ignores those two, because the capture path is not
affected by focus. Give voice message playback the same treatment, moving
the requester test into a named function rather than growing the inline
condition. A permanent AUDIOFOCUS_LOSS, a real phone call, still pauses,
and the media viewer is untouched.