diff --git a/.github/workflows/quality.yml b/.github/workflows/quality.yml
index 859e26defc..15092ad82c 100644
--- a/.github/workflows/quality.yml
+++ b/.github/workflows/quality.yml
@@ -33,6 +33,27 @@ jobs:
- name: Search for invalid screenshot files
run: ./tools/test/checkInvalidScreenshots.py
+ checkDependencies:
+ name: Search for invalid dependencies
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Use JDK 17
+ uses: actions/setup-java@v4
+ with:
+ distribution: 'temurin' # See 'Supported distributions' for available options
+ java-version: '17'
+ - name: Configure gradle
+ uses: gradle/actions/setup-gradle@v3
+ with:
+ cache-read-only: ${{ github.ref != 'refs/heads/develop' }}
+ - name: Set up Python 3.12
+ uses: actions/setup-python@v5
+ with:
+ python-version: 3.12
+ - name: Search for invalid dependencies
+ run: ./tools/dependencies/checkDependencies.py
+
# Code checks
konsist:
name: Konsist tests
diff --git a/.idea/dictionaries/shared.xml b/.idea/dictionaries/shared.xml
index 01db2cef83..e7bc929689 100644
--- a/.idea/dictionaries/shared.xml
+++ b/.idea/dictionaries/shared.xml
@@ -13,6 +13,7 @@
onboarding
placeables
posthog
+ rageshake
securebackup
showkase
snackbar
diff --git a/README.md b/README.md
index 7924c369a5..35d4cffb27 100644
--- a/README.md
+++ b/README.md
@@ -14,6 +14,8 @@ The application is a total rewrite of [Element-Android](https://github.com/eleme
Learn more about why we are building Element X in our blog post: [https://element.io/blog/element-x-experience-the-future-of-element/](https://element.io/blog/element-x-experience-the-future-of-element/).
+[
](https://play.google.com/store/apps/details?id=io.element.android.x)[
](https://f-droid.org/packages/io.element.android.x)
+
## Table of contents
@@ -25,13 +27,13 @@ Learn more about why we are building Element X in our blog post: [https://elemen
* [Contributing](#contributing)
* [Build instructions](#build-instructions)
* [Support](#support)
-* [Copyright & License](#copyright-&-license)
+* [Copyright and License](#copyright-and-license)
## Screenshots
-Here are some early screenshots of the application:
+Here are some screenshots of the application:
-|
|
|
|
|
+|
|
|
|
|
|-|-|-|-|
-|
|
|
|
|
+|
|
|
|
|
## Translations
@@ -90,7 +92,7 @@ When you are experiencing an issue on Element X Android, please first search in
and then in [#element-x-android:matrix.org](https://matrix.to/#/#element-x-android:matrix.org).
If after your research you still have a question, ask at [#element-x-android:matrix.org](https://matrix.to/#/#element-x-android:matrix.org). Otherwise feel free to create a GitHub issue if you encounter a bug or a crash, by explaining clearly in detail what happened. You can also perform bug reporting from the application settings. This is especially recommended when you encounter a crash.
-## Copyright & License
+## Copyright and License
Copyright © New Vector Ltd
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 4c21cef589..a4a4b1ee16 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -223,7 +223,6 @@ dependencies {
allLibrariesImpl()
allServicesImpl()
allFeaturesImpl(rootDir, logger)
- implementation(projects.features.call)
implementation(projects.features.migration.api)
implementation(projects.anvilannotations)
implementation(projects.appnav)
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
deleted file mode 100644
index fee1385c85..0000000000
--- a/app/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
- ignored
-
diff --git a/appconfig/src/main/kotlin/io/element/android/appconfig/ApplicationConfig.kt b/appconfig/src/main/kotlin/io/element/android/appconfig/ApplicationConfig.kt
index e8a8a2b33a..21af158ad6 100644
--- a/appconfig/src/main/kotlin/io/element/android/appconfig/ApplicationConfig.kt
+++ b/appconfig/src/main/kotlin/io/element/android/appconfig/ApplicationConfig.kt
@@ -40,9 +40,4 @@ object ApplicationConfig {
* For Element, the value is "Element". We use the same name for desktop and mobile for now.
*/
const val DESKTOP_APPLICATION_NAME: String = "Element"
-
- /**
- * The maximum size of the upload request. Default value is just below CloudFlare's max request size.
- */
- const val MAX_LOG_UPLOAD_SIZE = 50 * 1024 * 1024L
}
diff --git a/appconfig/src/main/kotlin/io/element/android/appconfig/RageshakeConfig.kt b/appconfig/src/main/kotlin/io/element/android/appconfig/RageshakeConfig.kt
new file mode 100644
index 0000000000..78d55e496e
--- /dev/null
+++ b/appconfig/src/main/kotlin/io/element/android/appconfig/RageshakeConfig.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2024 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.element.android.appconfig
+
+object RageshakeConfig {
+ /**
+ * The URL to submit bug reports to.
+ */
+ const val BUG_REPORT_URL = "https://riot.im/bugreports/submit"
+
+ /**
+ * As per https://github.com/matrix-org/rageshake:
+ * Identifier for the application (eg 'riot-web').
+ * Should correspond to a mapping configured in the configuration file for github issue reporting to work.
+ */
+ const val BUG_REPORT_APP_NAME = "element-x-android"
+
+ /**
+ * The maximum size of the upload request. Default value is just below CloudFlare's max request size.
+ */
+ const val MAX_LOG_UPLOAD_SIZE = 50 * 1024 * 1024L
+}
diff --git a/features/ftue/impl/build.gradle.kts b/features/ftue/impl/build.gradle.kts
index e42763d97c..4d84dc8fa3 100644
--- a/features/ftue/impl/build.gradle.kts
+++ b/features/ftue/impl/build.gradle.kts
@@ -50,7 +50,6 @@ dependencies {
implementation(projects.libraries.permissions.api)
implementation(projects.libraries.permissions.noop)
implementation(projects.services.toolbox.api)
- implementation(projects.services.toolbox.test)
testImplementation(libs.test.junit)
testImplementation(libs.coroutines.test)
@@ -63,6 +62,7 @@ dependencies {
testImplementation(projects.libraries.permissions.test)
testImplementation(projects.libraries.preferences.test)
testImplementation(projects.features.lockscreen.test)
+ testImplementation(projects.services.toolbox.test)
testImplementation(projects.tests.testutils)
ksp(libs.showkase.processor)
diff --git a/features/lockscreen/impl/build.gradle.kts b/features/lockscreen/impl/build.gradle.kts
index 168e72ba3d..030955ed72 100644
--- a/features/lockscreen/impl/build.gradle.kts
+++ b/features/lockscreen/impl/build.gradle.kts
@@ -58,6 +58,6 @@ dependencies {
testImplementation(projects.libraries.cryptography.test)
testImplementation(projects.libraries.cryptography.impl)
testImplementation(projects.libraries.featureflag.test)
- implementation(projects.libraries.sessionStorage.test)
- implementation(projects.services.appnavstate.test)
+ testImplementation(projects.libraries.sessionStorage.test)
+ testImplementation(projects.services.appnavstate.test)
}
diff --git a/features/logout/impl/src/main/AndroidManifest.xml b/features/logout/impl/src/main/AndroidManifest.xml
deleted file mode 100644
index 86d497f107..0000000000
--- a/features/logout/impl/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
diff --git a/features/logout/impl/src/main/res/values/tmp.xml b/features/logout/impl/src/main/res/values/tmp.xml
deleted file mode 100644
index e9e1e376c6..0000000000
--- a/features/logout/impl/src/main/res/values/tmp.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt
index b4e8a2effb..9e89ff9a76 100755
--- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt
+++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporter.kt
@@ -21,12 +21,11 @@ import android.os.Build
import androidx.core.net.toFile
import androidx.core.net.toUri
import com.squareup.anvil.annotations.ContributesBinding
-import io.element.android.appconfig.ApplicationConfig
+import io.element.android.appconfig.RageshakeConfig
import io.element.android.features.rageshake.api.crash.CrashDataStore
import io.element.android.features.rageshake.api.reporter.BugReporter
import io.element.android.features.rageshake.api.reporter.BugReporterListener
import io.element.android.features.rageshake.api.screenshot.ScreenshotHolder
-import io.element.android.features.rageshake.impl.R
import io.element.android.libraries.androidutils.file.compressFile
import io.element.android.libraries.androidutils.file.safeDelete
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
@@ -139,7 +138,7 @@ class DefaultBugReporter @Inject constructor(
// build the multi part request
val builder = BugReporterMultipartBody.Builder()
.addFormDataPart("text", bugDescription)
- .addFormDataPart("app", context.getString(R.string.bug_report_app_name))
+ .addFormDataPart("app", RageshakeConfig.BUG_REPORT_APP_NAME)
.addFormDataPart("user_agent", userAgentProvider.provide())
.addFormDataPart("user_id", userId?.toString() ?: "undefined")
.addFormDataPart("can_contact", canContact.toString())
@@ -178,7 +177,7 @@ class DefaultBugReporter @Inject constructor(
val requestBody = file.asRequestBody(MimeTypes.OctetStream.toMediaTypeOrNull())
totalUploadedSize += requestBody.contentLength()
// If we are about to upload more than the max request size, stop here
- if (totalUploadedSize > ApplicationConfig.MAX_LOG_UPLOAD_SIZE) {
+ if (totalUploadedSize > RageshakeConfig.MAX_LOG_UPLOAD_SIZE) {
Timber.e("Could not upload file ${file.name} because it would exceed the max request size")
break
}
@@ -375,7 +374,7 @@ class DefaultBugReporter @Inject constructor(
val separator = System.lineSeparator()
logcatProcess.inputStream
.reader()
- .buffered(ApplicationConfig.MAX_LOG_UPLOAD_SIZE.toInt())
+ .buffered(RageshakeConfig.MAX_LOG_UPLOAD_SIZE.toInt())
.forEachLine { line ->
streamWriter.append(line)
streamWriter.append(separator)
diff --git a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporterUrlProvider.kt b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporterUrlProvider.kt
index 5907a9a1c9..157ffb55a7 100644
--- a/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporterUrlProvider.kt
+++ b/features/rageshake/impl/src/main/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporterUrlProvider.kt
@@ -17,18 +17,15 @@
package io.element.android.features.rageshake.impl.reporter
import com.squareup.anvil.annotations.ContributesBinding
-import io.element.android.features.rageshake.impl.R
+import io.element.android.appconfig.RageshakeConfig
import io.element.android.libraries.di.AppScope
-import io.element.android.services.toolbox.api.strings.StringProvider
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl
import javax.inject.Inject
@ContributesBinding(AppScope::class)
-class DefaultBugReporterUrlProvider @Inject constructor(
- private val stringProvider: StringProvider
-) : BugReporterUrlProvider {
+class DefaultBugReporterUrlProvider @Inject constructor() : BugReporterUrlProvider {
override fun provide(): HttpUrl {
- return stringProvider.getString(R.string.bug_report_url).toHttpUrl()
+ return RageshakeConfig.BUG_REPORT_URL.toHttpUrl()
}
}
diff --git a/features/rageshake/impl/src/main/res/values/strings.xml b/features/rageshake/impl/src/main/res/values/strings.xml
deleted file mode 100644
index dc1069570b..0000000000
--- a/features/rageshake/impl/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
- https://riot.im/bugreports/submit
-
- element-x-android
-
-
-
diff --git a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporterUrlProviderTest.kt b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporterUrlProviderTest.kt
index a5c36df185..dae0b16bcc 100644
--- a/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporterUrlProviderTest.kt
+++ b/features/rageshake/impl/src/test/kotlin/io/element/android/features/rageshake/impl/reporter/DefaultBugReporterUrlProviderTest.kt
@@ -17,15 +17,15 @@
package io.element.android.features.rageshake.impl.reporter
import com.google.common.truth.Truth.assertThat
-import io.element.android.services.toolbox.test.strings.FakeStringProvider
+import io.element.android.appconfig.RageshakeConfig
import okhttp3.HttpUrl.Companion.toHttpUrl
import org.junit.Test
class DefaultBugReporterUrlProviderTest {
@Test
fun `test DefaultBugReporterUrlProvider`() {
- val sut = DefaultBugReporterUrlProvider(FakeStringProvider("https://example.org"))
+ val sut = DefaultBugReporterUrlProvider()
val result = sut.provide()
- assertThat(result).isEqualTo("https://example.org".toHttpUrl())
+ assertThat(result).isEqualTo(RageshakeConfig.BUG_REPORT_URL.toHttpUrl())
}
}
diff --git a/libraries/dateformatter/api/src/main/AndroidManifest.xml b/libraries/dateformatter/api/src/main/AndroidManifest.xml
deleted file mode 100644
index cf0e6386de..0000000000
--- a/libraries/dateformatter/api/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
diff --git a/libraries/dateformatter/impl/src/main/AndroidManifest.xml b/libraries/dateformatter/impl/src/main/AndroidManifest.xml
deleted file mode 100644
index cf0e6386de..0000000000
--- a/libraries/dateformatter/impl/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
diff --git a/libraries/dateformatter/test/src/main/AndroidManifest.xml b/libraries/dateformatter/test/src/main/AndroidManifest.xml
deleted file mode 100644
index cf0e6386de..0000000000
--- a/libraries/dateformatter/test/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-
-
diff --git a/libraries/designsystem/src/main/AndroidManifest.xml b/libraries/designsystem/src/main/AndroidManifest.xml
deleted file mode 100644
index 19db0c3d57..0000000000
--- a/libraries/designsystem/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
diff --git a/libraries/matrixui/src/main/AndroidManifest.xml b/libraries/matrixui/src/main/AndroidManifest.xml
deleted file mode 100644
index 122869829c..0000000000
--- a/libraries/matrixui/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
diff --git a/libraries/push/impl/src/main/res/values/colors.xml b/libraries/push/impl/src/main/res/values/colors.xml
index 6e04238a1a..64a9d928fb 100644
--- a/libraries/push/impl/src/main/res/values/colors.xml
+++ b/libraries/push/impl/src/main/res/values/colors.xml
@@ -16,7 +16,6 @@
-
#368BD6
diff --git a/libraries/testtags/src/main/AndroidManifest.xml b/libraries/testtags/src/main/AndroidManifest.xml
deleted file mode 100644
index ab34d2c3dd..0000000000
--- a/libraries/testtags/src/main/AndroidManifest.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
diff --git a/tests/uitests/build.gradle.kts b/tests/uitests/build.gradle.kts
index b141b85be9..b5d0d4607e 100644
--- a/tests/uitests/build.gradle.kts
+++ b/tests/uitests/build.gradle.kts
@@ -67,7 +67,6 @@ dependencies {
// `testOptions { unitTests.isIncludeAndroidResources = true }` in the app build.gradle.kts file
// implementation(projects.app)
implementation(projects.appnav)
- implementation(projects.features.call)
allLibrariesImpl()
allServicesImpl()
allFeaturesImpl(rootDir, logger)
diff --git a/tools/dependencies/checkDependencies.py b/tools/dependencies/checkDependencies.py
new file mode 100755
index 0000000000..cc734c9c38
--- /dev/null
+++ b/tools/dependencies/checkDependencies.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python3
+
+import os
+import subprocess
+
+
+def getProjectDependencies():
+ print("=> Computing dependencies...")
+ command = subprocess.run(
+ ["./gradlew :app:dependencies"],
+ shell=True,
+ capture_output=True,
+ text=True,
+ )
+ data = command.stdout
+ # Remove the trailing info like "(*)"
+ result = list(map(lambda x: x.split(" (")[0], data.split("\n")))
+ # Filter out comment line
+ result = list(filter(lambda x: "--- project" in x, result))
+ return result
+
+
+def checkThatModulesExist(dependencies):
+ print("=> Checking that all modules exist...")
+ error = 0
+ modules = set()
+ for line in dependencies:
+ if line:
+ line = line.split(" ")
+ for elem in line:
+ if ":" in elem:
+ modules.add(elem)
+ for module in modules:
+ path = "." + module.replace(":", "/") + "/build.gradle.kts"
+ if not os.path.exists(path):
+ error += 1
+ print("Error: there is at least one dependency to '" + module + "' but the module does not exist.")
+ print(" Please remove occurrence(s) of 'implementation(projects" + module.replace(":", ".") + ")'.")
+ return error
+
+
+def checkThatThereIsNoTestDependency(dependencies):
+ print("=> Checking that there are no test dependencies...")
+ errors = set()
+ currentProject = ""
+ for line in dependencies:
+ if line.startswith("+--- project "):
+ currentProject = line.split(" ")[2]
+ else:
+ if ":test" in currentProject:
+ continue
+ else:
+ subProject = line.split(" ")[-1]
+ if subProject.endswith(":test") or ":tests:" in subProject:
+ error = "Error: '" + currentProject + "' depends on the test project '" + subProject + "'\n"
+ error += " Please replace occurrence(s) of 'implementation(projects" + subProject.replace(":", ".") + ")'"
+ error += " with 'testImplementation(projects" + subProject.replace(":", ".") + ")'."
+ errors.add(error)
+ for error in errors:
+ print(error)
+ return len(errors)
+
+
+def main():
+ dependencies = getProjectDependencies()
+ # for dep in dependencies:
+ # print(dep)
+ errors = 0
+ errors += checkThatModulesExist(dependencies)
+ errors += checkThatThereIsNoTestDependency(dependencies)
+ print()
+ if (errors == 0):
+ print("All checks passed successfully.")
+ elif (errors == 1):
+ print("Please fix the error above.")
+ else:
+ print("Please fix the " + str(errors) + " errors above.")
+ exit(errors)
+
+
+if __name__ == "__main__":
+ main()