Remove :samples:minimal module
5
.github/workflows/build.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
variant: [debug, release, nightly, samples]
|
variant: [debug, release, nightly]
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
# Allow all jobs on develop. Just one per PR.
|
# Allow all jobs on develop. Just one per PR.
|
||||||
concurrency:
|
concurrency:
|
||||||
@@ -82,6 +82,3 @@ jobs:
|
|||||||
- name: Compile nightly sources
|
- name: Compile nightly sources
|
||||||
if: ${{ matrix.variant == 'nightly' }}
|
if: ${{ matrix.variant == 'nightly' }}
|
||||||
run: ./gradlew compileGplayNightlySources -PallWarningsAsErrors=true $CI_GRADLE_ARG_PROPERTIES
|
run: ./gradlew compileGplayNightlySources -PallWarningsAsErrors=true $CI_GRADLE_ARG_PROPERTIES
|
||||||
- name: Compile samples minimal
|
|
||||||
if: ${{ matrix.variant == 'samples' }}
|
|
||||||
run: ./gradlew :samples:minimal:assemble $CI_GRADLE_ARG_PROPERTIES
|
|
||||||
|
|||||||
@@ -49,8 +49,6 @@ Please ensure that you're using the project formatting rules (which are in the p
|
|||||||
|
|
||||||
This project should compile without any special action. Just clone it and open it with Android Studio, or compile from command line using `gradlew`.
|
This project should compile without any special action. Just clone it and open it with Android Studio, or compile from command line using `gradlew`.
|
||||||
|
|
||||||
Note: please make sure that the configuration is `app` and not `samples.minimal`.
|
|
||||||
|
|
||||||
## Strings
|
## Strings
|
||||||
|
|
||||||
The strings of the project are managed externally using [https://localazy.com](https://localazy.com) and shared with Element X iOS.
|
The strings of the project are managed externally using [https://localazy.com](https://localazy.com) and shared with Element X iOS.
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ We want:
|
|||||||
|
|
||||||
The CI checks that:
|
The CI checks that:
|
||||||
|
|
||||||
1. The code is compiling, without any warnings, for all the app build types and variants and for the minimal app
|
1. The code is compiling, without any warnings, for all the app build types and variants
|
||||||
2. The tests are passing
|
2. The tests are passing
|
||||||
3. The code quality is good (detekt, ktlint, lint)
|
3. The code quality is good (detekt, ktlint, lint)
|
||||||
4. The code is running and smoke tests are passing (maestro)
|
4. The code is running and smoke tests are passing (maestro)
|
||||||
|
|||||||
@@ -32,10 +32,8 @@ val localAarProjects = listOf(
|
|||||||
|
|
||||||
val excludedKoverSubProjects = listOf(
|
val excludedKoverSubProjects = listOf(
|
||||||
":app",
|
":app",
|
||||||
":samples",
|
|
||||||
":anvilannotations",
|
":anvilannotations",
|
||||||
":anvilcodegen",
|
":anvilcodegen",
|
||||||
":samples:minimal",
|
|
||||||
":tests:testutils",
|
":tests:testutils",
|
||||||
// Exclude `:libraries:matrix:impl` module, it contains only wrappers to access the Rust Matrix
|
// Exclude `:libraries:matrix:impl` module, it contains only wrappers to access the Rust Matrix
|
||||||
// SDK api, so it is not really relevant to unit test it: there is no logic to test.
|
// SDK api, so it is not really relevant to unit test it: there is no logic to test.
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This will generate the plugin "io.element.android-compose-application" to use by app and samples modules
|
* This will generate the plugin "io.element.android-compose-application" to use by app
|
||||||
*/
|
*/
|
||||||
import extension.androidConfig
|
import extension.androidConfig
|
||||||
import extension.commonDependencies
|
import extension.commonDependencies
|
||||||
|
|||||||
1
samples/minimal/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
/build
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2023, 2024 New Vector Ltd.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
* Please see LICENSE in the repository root for full details.
|
|
||||||
*/
|
|
||||||
plugins {
|
|
||||||
id("io.element.android-compose-application")
|
|
||||||
alias(libs.plugins.kotlin.android)
|
|
||||||
}
|
|
||||||
|
|
||||||
android {
|
|
||||||
namespace = "io.element.android.samples.minimal"
|
|
||||||
|
|
||||||
defaultConfig {
|
|
||||||
applicationId = "io.element.android.samples.minimal"
|
|
||||||
targetSdk = Versions.TARGET_SDK
|
|
||||||
versionCode = Versions.VERSION_CODE
|
|
||||||
versionName = Versions.VERSION_NAME
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
|
||||||
}
|
|
||||||
|
|
||||||
buildFeatures {
|
|
||||||
buildConfig = true
|
|
||||||
}
|
|
||||||
|
|
||||||
buildTypes {
|
|
||||||
release {
|
|
||||||
isMinifyEnabled = false
|
|
||||||
proguardFiles(
|
|
||||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
|
||||||
"proguard-rules.pro"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation(libs.androidx.activity.compose)
|
|
||||||
implementation(libs.androidx.preference)
|
|
||||||
implementation(projects.libraries.matrix.api)
|
|
||||||
implementation(projects.libraries.matrix.impl)
|
|
||||||
implementation(projects.libraries.permissions.noop)
|
|
||||||
implementation(projects.libraries.sessionStorage.implMemory)
|
|
||||||
implementation(projects.libraries.designsystem)
|
|
||||||
implementation(projects.libraries.androidutils)
|
|
||||||
implementation(projects.libraries.architecture)
|
|
||||||
implementation(projects.libraries.core)
|
|
||||||
implementation(projects.libraries.network)
|
|
||||||
implementation(projects.libraries.dateformatter.impl)
|
|
||||||
implementation(projects.libraries.eventformatter.impl)
|
|
||||||
implementation(projects.libraries.fullscreenintent.impl)
|
|
||||||
implementation(projects.libraries.preferences.impl)
|
|
||||||
implementation(projects.libraries.preferences.test)
|
|
||||||
implementation(projects.libraries.indicator.impl)
|
|
||||||
implementation(projects.features.invite.impl)
|
|
||||||
implementation(projects.features.roomlist.impl)
|
|
||||||
implementation(projects.features.leaveroom.impl)
|
|
||||||
implementation(projects.features.login.impl)
|
|
||||||
implementation(projects.features.logout.impl)
|
|
||||||
implementation(projects.features.networkmonitor.impl)
|
|
||||||
implementation(projects.services.toolbox.impl)
|
|
||||||
implementation(projects.libraries.featureflag.impl)
|
|
||||||
implementation(projects.services.analytics.noop)
|
|
||||||
implementation(libs.coroutines.core)
|
|
||||||
implementation(projects.libraries.push.test)
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
~ Copyright 2023 New Vector Ltd.
|
|
||||||
~
|
|
||||||
~ SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
~ Please see LICENSE in the repository root for full details.
|
|
||||||
-->
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
<application
|
|
||||||
android:allowBackup="true"
|
|
||||||
android:icon="@mipmap/ic_launcher"
|
|
||||||
android:label="@string/app_name"
|
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
|
||||||
android:supportsRtl="true"
|
|
||||||
android:theme="@style/Theme.ElementX">
|
|
||||||
<activity
|
|
||||||
android:name=".MainActivity"
|
|
||||||
android:exported="true"
|
|
||||||
android:theme="@style/Theme.ElementX">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN" />
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
</application>
|
|
||||||
|
|
||||||
</manifest>
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024 New Vector Ltd.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
* Please see LICENSE in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.element.android.samples.minimal
|
|
||||||
|
|
||||||
import io.element.android.libraries.featureflag.api.Feature
|
|
||||||
import io.element.android.libraries.featureflag.api.FeatureFlagService
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.flowOf
|
|
||||||
|
|
||||||
class AlwaysEnabledFeatureFlagService : FeatureFlagService {
|
|
||||||
override fun isFeatureEnabledFlow(feature: Feature): Flow<Boolean> {
|
|
||||||
return flowOf(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun setFeatureEnabled(feature: Feature, enabled: Boolean): Boolean {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2023, 2024 New Vector Ltd.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
* Please see LICENSE in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.element.android.samples.minimal
|
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import io.element.android.features.login.impl.DefaultLoginUserStory
|
|
||||||
import io.element.android.features.login.impl.accountprovider.AccountProviderDataSource
|
|
||||||
import io.element.android.features.login.impl.screens.loginpassword.LoginPasswordPresenter
|
|
||||||
import io.element.android.features.login.impl.screens.loginpassword.LoginPasswordView
|
|
||||||
import io.element.android.features.login.impl.util.defaultAccountProvider
|
|
||||||
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
|
||||||
|
|
||||||
class LoginScreen(private val authenticationService: MatrixAuthenticationService) {
|
|
||||||
@Composable
|
|
||||||
fun Content(modifier: Modifier = Modifier) {
|
|
||||||
val presenter = remember {
|
|
||||||
LoginPasswordPresenter(
|
|
||||||
authenticationService = authenticationService,
|
|
||||||
AccountProviderDataSource(),
|
|
||||||
DefaultLoginUserStory(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
|
||||||
authenticationService.setHomeserver(defaultAccountProvider.url)
|
|
||||||
}
|
|
||||||
|
|
||||||
val state = presenter.present()
|
|
||||||
LoginPasswordView(
|
|
||||||
state = state,
|
|
||||||
modifier = modifier,
|
|
||||||
onBackClick = {},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2023, 2024 New Vector Ltd.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
* Please see LICENSE in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.element.android.samples.minimal
|
|
||||||
|
|
||||||
import android.os.Bundle
|
|
||||||
import androidx.activity.ComponentActivity
|
|
||||||
import androidx.activity.compose.setContent
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.collectAsState
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.core.view.WindowCompat
|
|
||||||
import io.element.android.compound.theme.ElementTheme
|
|
||||||
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
|
||||||
import io.element.android.libraries.matrix.impl.RustClientBuilderProvider
|
|
||||||
import io.element.android.libraries.matrix.impl.RustMatrixClientFactory
|
|
||||||
import io.element.android.libraries.matrix.impl.auth.OidcConfigurationProvider
|
|
||||||
import io.element.android.libraries.matrix.impl.auth.RustMatrixAuthenticationService
|
|
||||||
import io.element.android.libraries.matrix.impl.paths.SessionPathsFactory
|
|
||||||
import io.element.android.libraries.matrix.impl.room.RustTimelineEventTypeFilterFactory
|
|
||||||
import io.element.android.libraries.network.useragent.SimpleUserAgentProvider
|
|
||||||
import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore
|
|
||||||
import io.element.android.libraries.sessionstorage.api.LoggedInState
|
|
||||||
import io.element.android.libraries.sessionstorage.impl.memory.InMemorySessionStore
|
|
||||||
import io.element.android.services.analytics.noop.NoopAnalyticsService
|
|
||||||
import io.element.android.services.toolbox.impl.systemclock.DefaultSystemClock
|
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
|
||||||
private val matrixAuthenticationService: MatrixAuthenticationService by lazy {
|
|
||||||
val baseDirectory = File(applicationContext.filesDir, "sessions")
|
|
||||||
val userAgentProvider = SimpleUserAgentProvider("MinimalSample")
|
|
||||||
val sessionStore = InMemorySessionStore()
|
|
||||||
val userCertificatesProvider = NoOpUserCertificatesProvider()
|
|
||||||
val proxyProvider = NoOpProxyProvider()
|
|
||||||
RustMatrixAuthenticationService(
|
|
||||||
sessionPathsFactory = SessionPathsFactory(baseDirectory, applicationContext.cacheDir),
|
|
||||||
coroutineDispatchers = Singleton.coroutineDispatchers,
|
|
||||||
sessionStore = sessionStore,
|
|
||||||
rustMatrixClientFactory = RustMatrixClientFactory(
|
|
||||||
baseDirectory = baseDirectory,
|
|
||||||
cacheDirectory = applicationContext.cacheDir,
|
|
||||||
appCoroutineScope = Singleton.appScope,
|
|
||||||
coroutineDispatchers = Singleton.coroutineDispatchers,
|
|
||||||
sessionStore = sessionStore,
|
|
||||||
userAgentProvider = userAgentProvider,
|
|
||||||
userCertificatesProvider = userCertificatesProvider,
|
|
||||||
proxyProvider = proxyProvider,
|
|
||||||
clock = DefaultSystemClock(),
|
|
||||||
analyticsService = NoopAnalyticsService(),
|
|
||||||
featureFlagService = AlwaysEnabledFeatureFlagService(),
|
|
||||||
timelineEventTypeFilterFactory = RustTimelineEventTypeFilterFactory(),
|
|
||||||
clientBuilderProvider = RustClientBuilderProvider(),
|
|
||||||
),
|
|
||||||
passphraseGenerator = NullPassphraseGenerator(),
|
|
||||||
oidcConfigurationProvider = OidcConfigurationProvider(baseDirectory),
|
|
||||||
appPreferencesStore = InMemoryAppPreferencesStore(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
|
||||||
setContent {
|
|
||||||
ElementTheme {
|
|
||||||
val loggedInState by matrixAuthenticationService.loggedInStateFlow().collectAsState(initial = LoggedInState.NotLoggedIn)
|
|
||||||
Content(isLoggedIn = loggedInState is LoggedInState.LoggedIn, modifier = Modifier.fillMaxSize())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun Content(
|
|
||||||
isLoggedIn: Boolean,
|
|
||||||
modifier: Modifier = Modifier
|
|
||||||
) {
|
|
||||||
if (!isLoggedIn) {
|
|
||||||
LoginScreen(authenticationService = matrixAuthenticationService).Content(modifier)
|
|
||||||
} else {
|
|
||||||
val matrixClient = runBlocking {
|
|
||||||
val sessionId = matrixAuthenticationService.getLatestSessionId()!!
|
|
||||||
matrixAuthenticationService.restoreSession(sessionId).getOrNull()
|
|
||||||
}
|
|
||||||
RoomListScreen(LocalContext.current, matrixClient!!).Content(modifier)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024 New Vector Ltd.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
* Please see LICENSE in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.element.android.samples.minimal
|
|
||||||
|
|
||||||
import io.element.android.libraries.matrix.impl.proxy.ProxyProvider
|
|
||||||
|
|
||||||
class NoOpProxyProvider : ProxyProvider {
|
|
||||||
override fun provides(): String? = null
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024 New Vector Ltd.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
* Please see LICENSE in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.element.android.samples.minimal
|
|
||||||
|
|
||||||
import io.element.android.libraries.matrix.impl.certificates.UserCertificatesProvider
|
|
||||||
|
|
||||||
class NoOpUserCertificatesProvider : UserCertificatesProvider {
|
|
||||||
override fun provides(): List<ByteArray> = emptyList()
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024 New Vector Ltd.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
* Please see LICENSE in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.element.android.samples.minimal
|
|
||||||
|
|
||||||
import io.element.android.libraries.matrix.impl.keys.PassphraseGenerator
|
|
||||||
|
|
||||||
class NullPassphraseGenerator : PassphraseGenerator {
|
|
||||||
override fun generatePassphrase(): String? = null
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2024 New Vector Ltd.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
* Please see LICENSE in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.element.android.samples.minimal
|
|
||||||
|
|
||||||
import android.net.Uri
|
|
||||||
import io.element.android.libraries.matrix.api.permalink.PermalinkData
|
|
||||||
import io.element.android.libraries.matrix.api.permalink.PermalinkParser
|
|
||||||
|
|
||||||
class OnlyFallbackPermalinkParser : PermalinkParser {
|
|
||||||
override fun parse(uriString: String): PermalinkData {
|
|
||||||
return PermalinkData.FallbackLink(Uri.parse(uriString))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,174 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2023, 2024 New Vector Ltd.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
* Please see LICENSE in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.element.android.samples.minimal
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.DisposableEffect
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import io.element.android.features.invite.impl.response.AcceptDeclineInvitePresenter
|
|
||||||
import io.element.android.features.invite.impl.response.AcceptDeclineInviteView
|
|
||||||
import io.element.android.features.leaveroom.impl.LeaveRoomPresenter
|
|
||||||
import io.element.android.features.logout.impl.direct.DirectLogoutPresenter
|
|
||||||
import io.element.android.features.networkmonitor.impl.DefaultNetworkMonitor
|
|
||||||
import io.element.android.features.roomlist.impl.RoomListPresenter
|
|
||||||
import io.element.android.features.roomlist.impl.RoomListView
|
|
||||||
import io.element.android.features.roomlist.impl.datasource.RoomListDataSource
|
|
||||||
import io.element.android.features.roomlist.impl.datasource.RoomListRoomSummaryFactory
|
|
||||||
import io.element.android.features.roomlist.impl.filters.RoomListFiltersPresenter
|
|
||||||
import io.element.android.features.roomlist.impl.filters.selection.DefaultFilterSelectionStrategy
|
|
||||||
import io.element.android.features.roomlist.impl.search.RoomListSearchDataSource
|
|
||||||
import io.element.android.features.roomlist.impl.search.RoomListSearchPresenter
|
|
||||||
import io.element.android.libraries.androidutils.system.DefaultDateTimeObserver
|
|
||||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
|
||||||
import io.element.android.libraries.dateformatter.impl.DateFormatters
|
|
||||||
import io.element.android.libraries.dateformatter.impl.DefaultLastMessageTimestampFormatter
|
|
||||||
import io.element.android.libraries.dateformatter.impl.LocalDateTimeProvider
|
|
||||||
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarDispatcher
|
|
||||||
import io.element.android.libraries.eventformatter.impl.DefaultRoomLastMessageFormatter
|
|
||||||
import io.element.android.libraries.eventformatter.impl.ProfileChangeContentFormatter
|
|
||||||
import io.element.android.libraries.eventformatter.impl.RoomMembershipContentFormatter
|
|
||||||
import io.element.android.libraries.eventformatter.impl.StateContentFormatter
|
|
||||||
import io.element.android.libraries.fullscreenintent.api.aFullScreenIntentPermissionsState
|
|
||||||
import io.element.android.libraries.indicator.impl.DefaultIndicatorService
|
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
|
||||||
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
|
||||||
import io.element.android.libraries.matrix.api.timeline.Timeline
|
|
||||||
import io.element.android.libraries.matrix.impl.room.join.DefaultJoinRoom
|
|
||||||
import io.element.android.libraries.preferences.impl.store.DefaultSessionPreferencesStore
|
|
||||||
import io.element.android.libraries.push.test.notifications.FakeNotificationCleaner
|
|
||||||
import io.element.android.services.analytics.noop.NoopAnalyticsService
|
|
||||||
import io.element.android.services.toolbox.impl.strings.AndroidStringProvider
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import kotlinx.datetime.Clock
|
|
||||||
import kotlinx.datetime.TimeZone
|
|
||||||
import timber.log.Timber
|
|
||||||
import java.util.Locale
|
|
||||||
|
|
||||||
class RoomListScreen(
|
|
||||||
context: Context,
|
|
||||||
private val matrixClient: MatrixClient,
|
|
||||||
private val coroutineDispatchers: CoroutineDispatchers = Singleton.coroutineDispatchers,
|
|
||||||
) {
|
|
||||||
private val clock = Clock.System
|
|
||||||
private val locale = Locale.getDefault()
|
|
||||||
private val dateTimeProvider = LocalDateTimeProvider(clock) { TimeZone.currentSystemDefault() }
|
|
||||||
private val dateFormatters = DateFormatters(locale, clock) { TimeZone.currentSystemDefault() }
|
|
||||||
private val sessionVerificationService = matrixClient.sessionVerificationService()
|
|
||||||
private val encryptionService = matrixClient.encryptionService()
|
|
||||||
private val stringProvider = AndroidStringProvider(context.resources)
|
|
||||||
private val featureFlagService = AlwaysEnabledFeatureFlagService()
|
|
||||||
private val roomListRoomSummaryFactory = RoomListRoomSummaryFactory(
|
|
||||||
lastMessageTimestampFormatter = DefaultLastMessageTimestampFormatter(
|
|
||||||
localDateTimeProvider = dateTimeProvider,
|
|
||||||
dateFormatters = dateFormatters
|
|
||||||
),
|
|
||||||
roomLastMessageFormatter = DefaultRoomLastMessageFormatter(
|
|
||||||
sp = stringProvider,
|
|
||||||
roomMembershipContentFormatter = RoomMembershipContentFormatter(
|
|
||||||
matrixClient = matrixClient,
|
|
||||||
sp = stringProvider
|
|
||||||
),
|
|
||||||
profileChangeContentFormatter = ProfileChangeContentFormatter(stringProvider),
|
|
||||||
stateContentFormatter = StateContentFormatter(stringProvider),
|
|
||||||
permalinkParser = OnlyFallbackPermalinkParser(),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
private val presenter = RoomListPresenter(
|
|
||||||
client = matrixClient,
|
|
||||||
networkMonitor = DefaultNetworkMonitor(context, Singleton.appScope),
|
|
||||||
snackbarDispatcher = SnackbarDispatcher(),
|
|
||||||
leaveRoomPresenter = LeaveRoomPresenter(matrixClient, RoomMembershipObserver(), coroutineDispatchers),
|
|
||||||
roomListDataSource = RoomListDataSource(
|
|
||||||
roomListService = matrixClient.roomListService,
|
|
||||||
roomListRoomSummaryFactory = roomListRoomSummaryFactory,
|
|
||||||
coroutineDispatchers = coroutineDispatchers,
|
|
||||||
notificationSettingsService = matrixClient.notificationSettingsService(),
|
|
||||||
appScope = Singleton.appScope,
|
|
||||||
dateTimeObserver = DefaultDateTimeObserver(context),
|
|
||||||
),
|
|
||||||
indicatorService = DefaultIndicatorService(
|
|
||||||
sessionVerificationService = sessionVerificationService,
|
|
||||||
encryptionService = encryptionService,
|
|
||||||
),
|
|
||||||
featureFlagService = featureFlagService,
|
|
||||||
searchPresenter = RoomListSearchPresenter(
|
|
||||||
RoomListSearchDataSource(
|
|
||||||
roomListService = matrixClient.roomListService,
|
|
||||||
roomSummaryFactory = roomListRoomSummaryFactory,
|
|
||||||
coroutineDispatchers = coroutineDispatchers,
|
|
||||||
),
|
|
||||||
featureFlagService = featureFlagService,
|
|
||||||
),
|
|
||||||
sessionPreferencesStore = DefaultSessionPreferencesStore(
|
|
||||||
context = context,
|
|
||||||
sessionId = matrixClient.sessionId,
|
|
||||||
sessionCoroutineScope = Singleton.appScope
|
|
||||||
),
|
|
||||||
filtersPresenter = RoomListFiltersPresenter(
|
|
||||||
roomListService = matrixClient.roomListService,
|
|
||||||
filterSelectionStrategy = DefaultFilterSelectionStrategy(),
|
|
||||||
),
|
|
||||||
acceptDeclineInvitePresenter = AcceptDeclineInvitePresenter(
|
|
||||||
client = matrixClient,
|
|
||||||
joinRoom = DefaultJoinRoom(matrixClient, NoopAnalyticsService()),
|
|
||||||
notificationCleaner = FakeNotificationCleaner(),
|
|
||||||
),
|
|
||||||
analyticsService = NoopAnalyticsService(),
|
|
||||||
fullScreenIntentPermissionsPresenter = { aFullScreenIntentPermissionsState() },
|
|
||||||
notificationCleaner = FakeNotificationCleaner(),
|
|
||||||
logoutPresenter = DirectLogoutPresenter(matrixClient, encryptionService),
|
|
||||||
)
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun Content(modifier: Modifier = Modifier) {
|
|
||||||
fun onRoomClick(roomId: RoomId) {
|
|
||||||
Singleton.appScope.launch {
|
|
||||||
withContext(coroutineDispatchers.io) {
|
|
||||||
matrixClient.getRoom(roomId)!!.use { room ->
|
|
||||||
room.liveTimeline.paginate(Timeline.PaginationDirection.BACKWARDS)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val state = presenter.present()
|
|
||||||
RoomListView(
|
|
||||||
state = state,
|
|
||||||
onRoomClick = ::onRoomClick,
|
|
||||||
onSettingsClick = {},
|
|
||||||
onSetUpRecoveryClick = {},
|
|
||||||
onConfirmRecoveryKeyClick = {},
|
|
||||||
onCreateRoomClick = {},
|
|
||||||
onRoomSettingsClick = {},
|
|
||||||
onMenuActionClick = {},
|
|
||||||
onRoomDirectorySearchClick = {},
|
|
||||||
modifier = modifier,
|
|
||||||
acceptDeclineInviteView = {
|
|
||||||
AcceptDeclineInviteView(state = state.acceptDeclineInviteState, onAcceptInvite = {}, onDeclineInvite = {})
|
|
||||||
},
|
|
||||||
onMigrateToNativeSlidingSyncClick = {},
|
|
||||||
)
|
|
||||||
|
|
||||||
DisposableEffect(Unit) {
|
|
||||||
Timber.w("Start sync!")
|
|
||||||
runBlocking {
|
|
||||||
matrixClient.syncService().startSync()
|
|
||||||
}
|
|
||||||
onDispose {
|
|
||||||
Timber.w("Stop sync!")
|
|
||||||
runBlocking {
|
|
||||||
matrixClient.syncService().stopSync()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2023, 2024 New Vector Ltd.
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
* Please see LICENSE in the repository root for full details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package io.element.android.samples.minimal
|
|
||||||
|
|
||||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
|
||||||
import io.element.android.libraries.core.meta.BuildMeta
|
|
||||||
import io.element.android.libraries.core.meta.BuildType
|
|
||||||
import io.element.android.libraries.matrix.api.tracing.TracingConfiguration
|
|
||||||
import io.element.android.libraries.matrix.api.tracing.TracingFilterConfigurations
|
|
||||||
import io.element.android.libraries.matrix.api.tracing.WriteToFilesConfiguration
|
|
||||||
import io.element.android.libraries.matrix.impl.tracing.RustTracingService
|
|
||||||
import kotlinx.coroutines.CoroutineName
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.MainScope
|
|
||||||
import kotlinx.coroutines.plus
|
|
||||||
|
|
||||||
object Singleton {
|
|
||||||
val buildMeta = BuildMeta(
|
|
||||||
isDebuggable = true,
|
|
||||||
buildType = BuildType.DEBUG,
|
|
||||||
applicationName = "EAX-Minimal",
|
|
||||||
productionApplicationName = "EAX-Minimal",
|
|
||||||
desktopApplicationName = "EAX-Minimal-Desktop",
|
|
||||||
applicationId = "io.element.android.samples.minimal",
|
|
||||||
isEnterpriseBuild = false,
|
|
||||||
lowPrivacyLoggingEnabled = false,
|
|
||||||
versionName = "0.1.0",
|
|
||||||
versionCode = 1,
|
|
||||||
gitRevision = "",
|
|
||||||
gitBranchName = "",
|
|
||||||
flavorDescription = "NA",
|
|
||||||
flavorShortDescription = "NA",
|
|
||||||
)
|
|
||||||
|
|
||||||
init {
|
|
||||||
val tracingConfiguration = TracingConfiguration(
|
|
||||||
filterConfiguration = TracingFilterConfigurations.debug,
|
|
||||||
writesToLogcat = true,
|
|
||||||
writesToFilesConfiguration = WriteToFilesConfiguration.Disabled
|
|
||||||
)
|
|
||||||
RustTracingService(buildMeta).setupTracing(tracingConfiguration)
|
|
||||||
}
|
|
||||||
|
|
||||||
val appScope = MainScope() + CoroutineName("Minimal Scope")
|
|
||||||
val coroutineDispatchers = CoroutineDispatchers(
|
|
||||||
io = Dispatchers.IO,
|
|
||||||
computation = Dispatchers.Default,
|
|
||||||
main = Dispatchers.Main,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 982 B |
|
Before Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 7.6 KiB |
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
~ Copyright 2023 New Vector Ltd.
|
|
||||||
~
|
|
||||||
~ SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
~ Please see LICENSE in the repository root for full details.
|
|
||||||
-->
|
|
||||||
<resources>
|
|
||||||
<style name="Theme.ElementX" parent="android:Theme.Material.NoActionBar" />
|
|
||||||
</resources>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<!--
|
|
||||||
~ Copyright 2023 New Vector Ltd.
|
|
||||||
~
|
|
||||||
~ SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
~ Please see LICENSE in the repository root for full details.
|
|
||||||
-->
|
|
||||||
<resources>
|
|
||||||
<string name="app_name">EAX-Sample</string>
|
|
||||||
</resources>
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!--
|
|
||||||
~ Copyright 2023 New Vector Ltd.
|
|
||||||
~
|
|
||||||
~ SPDX-License-Identifier: AGPL-3.0-only
|
|
||||||
~ Please see LICENSE in the repository root for full details.
|
|
||||||
-->
|
|
||||||
<resources>
|
|
||||||
<style name="Theme.ElementX" parent="android:Theme.Material.Light.NoActionBar" />
|
|
||||||
</resources>
|
|
||||||
@@ -70,8 +70,6 @@ include(":tests:testutils")
|
|||||||
include(":anvilannotations")
|
include(":anvilannotations")
|
||||||
include(":anvilcodegen")
|
include(":anvilcodegen")
|
||||||
|
|
||||||
include(":samples:minimal")
|
|
||||||
|
|
||||||
fun includeProjects(directory: File, path: String, maxDepth: Int = 1) {
|
fun includeProjects(directory: File, path: String, maxDepth: Int = 1) {
|
||||||
directory.listFiles().orEmpty().also { it.sort() }.forEach { file ->
|
directory.listFiles().orEmpty().also { it.sort() }.forEach { file ->
|
||||||
if (file.isDirectory) {
|
if (file.isDirectory) {
|
||||||
|
|||||||
@@ -18,5 +18,4 @@ set -e
|
|||||||
./gradlew runQualityChecks
|
./gradlew runQualityChecks
|
||||||
|
|
||||||
# Build, test and check the project, with warning as errors
|
# Build, test and check the project, with warning as errors
|
||||||
# It also check that the minimal app is compiling.
|
|
||||||
./gradlew check -PallWarningsAsErrors=true
|
./gradlew check -PallWarningsAsErrors=true
|
||||||
|
|||||||