Skip to content

Commit

Permalink
Merge branch 'release/0.7.5' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
ganfra committed Dec 6, 2024
2 parents e567776 + 8f074d3 commit 9961852
Show file tree
Hide file tree
Showing 761 changed files with 7,124 additions and 3,327 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/maestro.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ jobs:
uses: actions/download-artifact@v4
with:
name: elementx-apk-maestro
- uses: mobile-dev-inc/action-maestro-cloud@v1.9.6
- uses: mobile-dev-inc/action-maestro-cloud@v1.9.7
if: (github.event_name == 'pull_request' && github.event.pull_request.fork == null) || github.event_name == 'workflow_dispatch'
with:
api-key: ${{ secrets.MAESTRO_CLOUD_API_KEY }}
Expand Down
50 changes: 50 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,53 @@
Changes in Element X v0.7.4 (2024-11-20)
========================================

## What's Changed
### 🙌 Improvements
* Update the strings for unsupported calls by @bmarty in https://github.com/element-hq/element-x-android/pull/3857
### 🐛 Bugfixes
* Stop incoming call ringing if answered on another device. by @bmarty in https://github.com/element-hq/element-x-android/pull/3842
* Use formatted captions for images and video by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3864
* Fix unified push unregister by @bmarty in https://github.com/element-hq/element-x-android/pull/3877
* Hide the keyboard when navigating from the chat room screen by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3878
* Fix long click not working for media timeline items by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3879
* Instantiate the verification controller ASAP by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3893
* fix : display security banner for room list empty state by @ganfra in https://github.com/element-hq/element-x-android/pull/3892
### 🗣 Translations
* Sync Strings by @ElementBot in https://github.com/element-hq/element-x-android/pull/3852
* Sync Strings - add translations to Finnish by @ElementBot in https://github.com/element-hq/element-x-android/pull/3883
### 🚧 In development 🚧
* Create room : improve handling of room address by @ganfra in https://github.com/element-hq/element-x-android/pull/3868
### Dependency upgrades
* Update anvil to v0.4.0 by @renovate in https://github.com/element-hq/element-x-android/pull/3792
* Update kotlin to v2.0.21-1.0.27 by @renovate in https://github.com/element-hq/element-x-android/pull/3836
* Update dependency org.maplibre.gl:android-sdk to v11.6.1 by @renovate in https://github.com/element-hq/element-x-android/pull/3793
* Update android.gradle.plugin to v8.7.2 by @renovate in https://github.com/element-hq/element-x-android/pull/3785
* Update lifecycle to v2.8.7 by @renovate in https://github.com/element-hq/element-x-android/pull/3763
* Update plugin dependencycheck to v11 by @renovate in https://github.com/element-hq/element-x-android/pull/3723
* Update dependency org.matrix.rustcomponents:sdk-android to v0.2.61 by @renovate in https://github.com/element-hq/element-x-android/pull/3841
* Update mobile-dev-inc/action-maestro-cloud action to v1.9.6 by @renovate in https://github.com/element-hq/element-x-android/pull/3846
* Update dependency com.posthog:posthog-android to v3.9.1 by @renovate in https://github.com/element-hq/element-x-android/pull/3856
* Update core to v1.15.0 by @renovate in https://github.com/element-hq/element-x-android/pull/3766
* Update dependency com.android.tools:desugar_jdk_libs to v2.1.3 by @renovate in https://github.com/element-hq/element-x-android/pull/3825
* Update dependency io.nlopez.compose.rules:detekt to v0.4.18 by @renovate in https://github.com/element-hq/element-x-android/pull/3860
* Update dependency com.posthog:posthog-android to v3.9.2 by @renovate in https://github.com/element-hq/element-x-android/pull/3861
* Update dependency io.sentry:sentry-android to v7.17.0 by @renovate in https://github.com/element-hq/element-x-android/pull/3862
* Update dependency androidx.compose:compose-bom to v2024.11.00 by @renovate in https://github.com/element-hq/element-x-android/pull/3869
* Update telephoto to v0.14.0 by @renovate in https://github.com/element-hq/element-x-android/pull/3870
* Update SDK bindings version to `0.2.62` and fix `SendHandle` usages by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3876
* Update codecov/codecov-action action to v5 by @renovate in https://github.com/element-hq/element-x-android/pull/3874
* Update dependency com.google.firebase:firebase-bom to v33.6.0 by @renovate in https://github.com/element-hq/element-x-android/pull/3880
* Update kotlin to v2.0.21-1.0.28 by @renovate in https://github.com/element-hq/element-x-android/pull/3881
* Update dependency org.robolectric:robolectric to v4.14 by @renovate in https://github.com/element-hq/element-x-android/pull/3882
* Update appyx to v1.5.1 by @renovate in https://github.com/element-hq/element-x-android/pull/3889
* Update dependency io.nlopez.compose.rules:detekt to v0.4.19 by @renovate in https://github.com/element-hq/element-x-android/pull/3900
* Update dependency org.matrix.rustcomponents:sdk-android to v0.2.63 by @renovate in https://github.com/element-hq/element-x-android/pull/3898
### Others
* Design system : implement new TextField by @ganfra in https://github.com/element-hq/element-x-android/pull/3834
* Remove :samples:minimal module by @bmarty in https://github.com/element-hq/element-x-android/pull/3871
* Replace `textPlaceholder` color usages with `textSecondary` by @jmartinesp in https://github.com/element-hq/element-x-android/pull/3873
* Room Preview API changes by @ganfra in https://github.com/element-hq/element-x-android/pull/3875

Changes in Element X v0.7.3 (2024-11-08)
========================================

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ object ElementCallConfig {
/**
* The default duration of a ringing call in seconds before it's automatically dismissed.
*/
const val RINGING_CALL_DURATION_SECONDS = 15
const val RINGING_CALL_DURATION_SECONDS = 90
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,20 @@ import android.graphics.Color
import androidx.annotation.ColorInt

object NotificationConfig {
// TODO EAx Implement and set to true at some point
const val SUPPORT_MARK_AS_READ_ACTION = false
/**
* If set to true, the notification will have a "Mark as read" action.
*/
const val SHOW_MARK_AS_READ_ACTION = true

// TODO EAx Implement and set to true at some point
const val SUPPORT_JOIN_DECLINE_INVITE = false
/**
* If set to true, the notification for invitation will have two actions to accept or decline the invite.
*/
const val SHOW_ACCEPT_AND_DECLINE_INVITE_ACTIONS = true

// TODO EAx Implement and set to true at some point
const val SUPPORT_QUICK_REPLY_ACTION = false
/**
* If set to true, the notification will have a "Quick reply" action, allow to compose and send a message to the room.
*/
const val SHOW_QUICK_REPLY_ACTION = true

@ColorInt
val NOTIFICATION_ACCENT_COLOR: Int = Color.parseColor("#FF0DBD8B")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,20 @@ import androidx.lifecycle.repeatOnLifecycle
import com.bumble.appyx.core.composable.PermanentChild
import com.bumble.appyx.core.lifecycle.subscribe
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.navigation.NavElements
import com.bumble.appyx.core.navigation.NavKey
import com.bumble.appyx.core.navigation.model.permanent.PermanentNavModel
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import com.bumble.appyx.core.plugin.plugins
import com.bumble.appyx.navmodel.backstack.BackStack
import com.bumble.appyx.navmodel.backstack.BackStack.State.ACTIVE
import com.bumble.appyx.navmodel.backstack.BackStack.State.CREATED
import com.bumble.appyx.navmodel.backstack.BackStack.State.STASHED
import com.bumble.appyx.navmodel.backstack.BackStackElement
import com.bumble.appyx.navmodel.backstack.BackStackElements
import com.bumble.appyx.navmodel.backstack.operation.BackStackOperation
import com.bumble.appyx.navmodel.backstack.operation.Push
import com.bumble.appyx.navmodel.backstack.operation.pop
import com.bumble.appyx.navmodel.backstack.operation.push
import com.bumble.appyx.navmodel.backstack.operation.replace
Expand Down Expand Up @@ -312,7 +321,7 @@ class LoggedInFlowNode @AssistedInject constructor(
}

override fun onForwardedToSingleRoom(roomId: RoomId) {
coroutineScope.launch { attachRoom(roomId.toRoomIdOrAlias()) }
coroutineScope.launch { attachRoom(roomId.toRoomIdOrAlias(), clearBackstack = false) }
}

override fun onPermalinkClick(data: PermalinkData, pushToBackstack: Boolean) {
Expand Down Expand Up @@ -400,6 +409,11 @@ class LoggedInFlowNode @AssistedInject constructor(
is NavTarget.SecureBackup -> {
secureBackupEntryPoint.nodeBuilder(this, buildContext)
.params(SecureBackupEntryPoint.Params(initialElement = navTarget.initialElement))
.callback(object : SecureBackupEntryPoint.Callback {
override fun onDone() {
backstack.pop()
}
})
.build()
}
NavTarget.Ftue -> {
Expand Down Expand Up @@ -467,21 +481,21 @@ class LoggedInFlowNode @AssistedInject constructor(
serverNames: List<String> = emptyList(),
trigger: JoinedRoom.Trigger? = null,
eventId: EventId? = null,
clearBackstack: Boolean,
) {
waitForNavTargetAttached { navTarget ->
navTarget is NavTarget.RoomList
}
attachChild<RoomFlowNode> {
backstack.push(
NavTarget.Room(
roomIdOrAlias = roomIdOrAlias,
serverNames = serverNames,
trigger = trigger,
initialElement = RoomNavigationTarget.Messages(
focusedEventId = eventId
)
val roomNavTarget = NavTarget.Room(
roomIdOrAlias = roomIdOrAlias,
serverNames = serverNames,
trigger = trigger,
initialElement = RoomNavigationTarget.Messages(
focusedEventId = eventId
)
)
backstack.accept(AttachRoomOperation(roomNavTarget, clearBackstack))
}
}

Expand Down Expand Up @@ -526,3 +540,31 @@ class LoggedInFlowNode @AssistedInject constructor(
@Assisted plugins: List<Plugin>,
) : Node(buildContext, plugins = plugins)
}

@Parcelize
private class AttachRoomOperation(
val roomTarget: LoggedInFlowNode.NavTarget.Room,
val clearBackstack: Boolean,
) : BackStackOperation<LoggedInFlowNode.NavTarget> {
override fun isApplicable(elements: NavElements<LoggedInFlowNode.NavTarget, BackStack.State>) = true

override fun invoke(elements: BackStackElements<LoggedInFlowNode.NavTarget>): BackStackElements<LoggedInFlowNode.NavTarget> {
return if (clearBackstack) {
// Makes sure the room list target is alone in the backstack and stashed
elements.mapNotNull { element ->
if (element.key.navTarget == LoggedInFlowNode.NavTarget.RoomList) {
element.transitionTo(STASHED, this)
} else {
null
}
} + BackStackElement(
key = NavKey(roomTarget),
fromState = CREATED,
targetState = ACTIVE,
operation = this
)
} else {
Push<LoggedInFlowNode.NavTarget>(roomTarget).invoke(elements)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ class RootFlowNode @AssistedInject constructor(
trigger = JoinedRoom.Trigger.MobilePermalink,
serverNames = permalinkData.viaParameters,
eventId = permalinkData.eventId,
clearBackstack = true
)
}
is PermalinkData.UserLink -> {
Expand All @@ -318,7 +319,7 @@ class RootFlowNode @AssistedInject constructor(
.apply {
when (deeplinkData) {
is DeeplinkData.Root -> Unit // The room list will always be shown, observing FtueState
is DeeplinkData.Room -> attachRoom(deeplinkData.roomId.toRoomIdOrAlias())
is DeeplinkData.Room -> attachRoom(deeplinkData.roomId.toRoomIdOrAlias(), clearBackstack = true)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.encryption.RecoveryState
import io.element.android.libraries.matrix.api.roomlist.RoomListService
import io.element.android.libraries.matrix.api.sync.SlidingSyncVersion
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
import io.element.android.libraries.preferences.api.store.EnableNativeSlidingSyncUseCase
Expand Down Expand Up @@ -102,10 +103,7 @@ class LoggedInPresenter @Inject constructor(
}
}
LoggedInEvents.CheckSlidingSyncProxyAvailability -> coroutineScope.launch {
// Force the user to log out if they were using the proxy sliding sync and it's no longer available, but native sliding sync is.
forceNativeSlidingSyncMigration = !matrixClient.isUsingNativeSlidingSync() &&
matrixClient.isNativeSlidingSyncSupported() &&
!matrixClient.isSlidingSyncProxySupported()
forceNativeSlidingSyncMigration = matrixClient.forceNativeSlidingSyncMigration().getOrDefault(false)
}
LoggedInEvents.LogoutAndMigrateToNativeSlidingSync -> coroutineScope.launch {
// Enable native sliding sync if it wasn't already the case
Expand All @@ -125,6 +123,18 @@ class LoggedInPresenter @Inject constructor(
)
}

// Force the user to log out if they were using the proxy sliding sync and it's no longer available, but native sliding sync is.
private suspend fun MatrixClient.forceNativeSlidingSyncMigration(): Result<Boolean> = runCatching {
val currentSlidingSyncVersion = currentSlidingSyncVersion().getOrThrow()
if (currentSlidingSyncVersion == SlidingSyncVersion.Proxy) {
val availableSlidingSyncVersions = availableSlidingSyncVersions().getOrThrow()
availableSlidingSyncVersions.contains(SlidingSyncVersion.Native) &&
!availableSlidingSyncVersions.contains(SlidingSyncVersion.Proxy)
} else {
false
}
}

private suspend fun ensurePusherIsRegistered(pusherRegistrationState: MutableState<AsyncData<Unit>>) {
Timber.tag(pusherTag.value).d("Ensure pusher is registered")
val currentPushProvider = pushService.getCurrentPushProvider()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,11 @@ import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
import io.element.android.libraries.matrix.api.core.toRoomIdOrAlias
import io.element.android.libraries.matrix.api.getRoomInfoFlow
import io.element.android.libraries.matrix.api.room.CurrentUserMembership
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
import io.element.android.libraries.matrix.api.room.alias.ResolvedRoomAlias
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
Expand All @@ -67,6 +69,7 @@ class RoomFlowNode @AssistedInject constructor(
private val joinRoomEntryPoint: JoinRoomEntryPoint,
private val roomAliasResolverEntryPoint: RoomAliasResolverEntryPoint,
private val networkMonitor: NetworkMonitor,
private val membershipObserver: RoomMembershipObserver,
) : BaseFlowNode<RoomFlowNode.NavTarget>(
backstack = BackStack(
initialElement = NavTarget.Loading,
Expand Down Expand Up @@ -145,10 +148,6 @@ class RoomFlowNode @AssistedInject constructor(
backstack.newRoot(NavTarget.JoinedRoom(roomId))
}
}
CurrentUserMembership.LEFT -> {
// Left the room, navigate out of this flow
navigateUp()
}
else -> {
// Was invited or the room is not known, display the join room screen
backstack.newRoot(
Expand All @@ -161,6 +160,15 @@ class RoomFlowNode @AssistedInject constructor(
}
}
}.launchIn(lifecycleScope)

// If the user leaves the room from this client, close the room flow.
lifecycleScope.launch {
membershipObserver.updates
.first { it.roomId == roomId && !it.isUserInRoom }
.run {
navigateUp()
}
}
}

override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.encryption.EncryptionService
import io.element.android.libraries.matrix.api.encryption.RecoveryState
import io.element.android.libraries.matrix.api.roomlist.RoomListService
import io.element.android.libraries.matrix.api.sync.SlidingSyncVersion
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
import io.element.android.libraries.matrix.test.AN_EXCEPTION
Expand Down Expand Up @@ -501,9 +502,8 @@ class LoggedInPresenterTest {
// - The sliding sync proxy is no longer supported
// - The native sliding sync is supported
val matrixClient = FakeMatrixClient(
isUsingNativeSlidingSyncLambda = { false },
isSlidingSyncProxySupportedLambda = { false },
isNativeSlidingSyncSupportedLambda = { true },
currentSlidingSyncVersionLambda = { Result.success(SlidingSyncVersion.Proxy) },
availableSlidingSyncVersionsLambda = { Result.success(listOf(SlidingSyncVersion.Native)) },
)
val presenter = createLoggedInPresenter(matrixClient = matrixClient)
moleculeFlow(RecompositionMode.Immediate) {
Expand All @@ -521,9 +521,8 @@ class LoggedInPresenterTest {
@Test
fun `present - CheckSlidingSyncProxyAvailability will not force the migration if native sliding sync is not supported too`() = runTest {
val matrixClient = FakeMatrixClient(
isUsingNativeSlidingSyncLambda = { false },
isSlidingSyncProxySupportedLambda = { false },
isNativeSlidingSyncSupportedLambda = { false },
currentSlidingSyncVersionLambda = { Result.success(SlidingSyncVersion.Proxy) },
availableSlidingSyncVersionsLambda = { Result.success(emptyList()) },
)
val presenter = createLoggedInPresenter(matrixClient = matrixClient)
moleculeFlow(RecompositionMode.Immediate) {
Expand Down
5 changes: 5 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ allprojects {
detektPlugins("io.nlopez.compose.rules:detekt:0.4.19")
}

tasks.withType<io.gitlab.arturbosch.detekt.Detekt>().configureEach {
exclude("io/element/android/tests/konsist/failures/**")
}

// KtLint
apply {
plugin("org.jlleitschuh.gradle.ktlint")
Expand All @@ -75,6 +79,7 @@ allprojects {
val generatedPath = "${layout.buildDirectory.asFile.get()}/generated/"
filter {
exclude { element -> element.file.path.contains(generatedPath) }
exclude("io/element/android/tests/konsist/failures/**")
}
}
// Dependency check
Expand Down
2 changes: 2 additions & 0 deletions fastlane/metadata/android/en-US/changelogs/40007050.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Main changes in this version: bug fixes and improvements.
Full changelog: https://github.com/element-hq/element-x-android/releases
Loading

0 comments on commit 9961852

Please sign in to comment.