First Commit
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023-2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
plugins {
|
||||
id("io.element.android-library")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "io.element.android.services.toolbox.api"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.androidx.corektx)
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2024, 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.services.toolbox.api.intent
|
||||
|
||||
import android.content.Intent
|
||||
|
||||
/**
|
||||
* Used to launch external intents from anywhere in the app.
|
||||
*/
|
||||
interface ExternalIntentLauncher {
|
||||
fun launch(intent: Intent)
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023-2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.services.toolbox.api.sdk
|
||||
|
||||
import androidx.annotation.ChecksSdkIntAtLeast
|
||||
|
||||
interface BuildVersionSdkIntProvider {
|
||||
/**
|
||||
* Return the current version of the Android SDK.
|
||||
*/
|
||||
fun get(): Int
|
||||
|
||||
/**
|
||||
* Checks the if the current OS version is equal or greater than [version].
|
||||
* @return A `non-null` result if true, `null` otherwise.
|
||||
*/
|
||||
@ChecksSdkIntAtLeast(parameter = 0, lambda = 1)
|
||||
fun <T> whenAtLeast(version: Int, result: () -> T): T? {
|
||||
return if (get() >= version) {
|
||||
result()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
@ChecksSdkIntAtLeast(parameter = 0)
|
||||
fun isAtLeast(version: Int) = get() >= version
|
||||
}
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023-2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.services.toolbox.api.strings
|
||||
|
||||
import androidx.annotation.PluralsRes
|
||||
import androidx.annotation.StringRes
|
||||
|
||||
interface StringProvider {
|
||||
/**
|
||||
* Returns a localized string from the application's package's
|
||||
* default string table.
|
||||
*
|
||||
* @param resId Resource id for the string
|
||||
* @return The string data associated with the resource, stripped of styled
|
||||
* text information.
|
||||
*/
|
||||
fun getString(@StringRes resId: Int): String
|
||||
|
||||
/**
|
||||
* Returns a localized formatted string from the application's package's
|
||||
* default string table, substituting the format arguments as defined in
|
||||
* [java.util.Formatter] and [java.lang.String.format].
|
||||
*
|
||||
* @param resId Resource id for the format string
|
||||
* @param formatArgs The format arguments that will be used for
|
||||
* substitution.
|
||||
* @return The string data associated with the resource, formatted and
|
||||
* stripped of styled text information.
|
||||
*/
|
||||
fun getString(@StringRes resId: Int, vararg formatArgs: Any?): String
|
||||
fun getQuantityString(@PluralsRes resId: Int, quantity: Int, vararg formatArgs: Any?): String
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023-2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.services.toolbox.api.systemclock
|
||||
|
||||
fun interface SystemClock {
|
||||
fun epochMillis(): Long
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import extension.setupDependencyInjection
|
||||
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023, 2024 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
plugins {
|
||||
id("io.element.android-library")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "io.element.android.services.toolbox.impl"
|
||||
}
|
||||
|
||||
setupDependencyInjection()
|
||||
|
||||
dependencies {
|
||||
implementation(projects.libraries.androidutils)
|
||||
implementation(projects.libraries.di)
|
||||
api(projects.services.toolbox.api)
|
||||
implementation(libs.androidx.corektx)
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2024, 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.services.toolbox.impl.intent
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.ContributesBinding
|
||||
import io.element.android.libraries.di.annotations.ApplicationContext
|
||||
import io.element.android.services.toolbox.api.intent.ExternalIntentLauncher
|
||||
|
||||
@ContributesBinding(AppScope::class)
|
||||
class DefaultExternalIntentLauncher(
|
||||
@ApplicationContext private val context: Context,
|
||||
) : ExternalIntentLauncher {
|
||||
override fun launch(intent: Intent) {
|
||||
context.startActivity(intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK))
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023-2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.services.toolbox.impl.sdk
|
||||
|
||||
import android.os.Build
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.ContributesBinding
|
||||
import io.element.android.services.toolbox.api.sdk.BuildVersionSdkIntProvider
|
||||
|
||||
@ContributesBinding(AppScope::class)
|
||||
class DefaultBuildVersionSdkIntProvider :
|
||||
BuildVersionSdkIntProvider {
|
||||
override fun get() = Build.VERSION.SDK_INT
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023-2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.services.toolbox.impl.strings
|
||||
|
||||
import android.content.res.Resources
|
||||
import androidx.annotation.PluralsRes
|
||||
import androidx.annotation.StringRes
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.ContributesBinding
|
||||
import io.element.android.services.toolbox.api.strings.StringProvider
|
||||
|
||||
@ContributesBinding(AppScope::class)
|
||||
class AndroidStringProvider(private val resources: Resources) : StringProvider {
|
||||
override fun getString(@StringRes resId: Int): String {
|
||||
return resources.getString(resId)
|
||||
}
|
||||
|
||||
override fun getString(@StringRes resId: Int, vararg formatArgs: Any?): String {
|
||||
return resources.getString(resId, *formatArgs)
|
||||
}
|
||||
|
||||
override fun getQuantityString(@PluralsRes resId: Int, quantity: Int, vararg formatArgs: Any?): String {
|
||||
return resources.getQuantityString(resId, quantity, *formatArgs)
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023-2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.services.toolbox.impl.systemclock
|
||||
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.ContributesBinding
|
||||
import io.element.android.services.toolbox.api.systemclock.SystemClock
|
||||
|
||||
@ContributesBinding(AppScope::class)
|
||||
class DefaultSystemClock : SystemClock {
|
||||
/**
|
||||
* Provides a UTC epoch in milliseconds
|
||||
*
|
||||
* This value is not guaranteed to be correct with reality
|
||||
* as a User can override the system time and date to any values.
|
||||
*/
|
||||
override fun epochMillis(): Long {
|
||||
return System.currentTimeMillis()
|
||||
}
|
||||
}
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023-2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.services.toolbox.impl.systemclock
|
||||
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.BindingContainer
|
||||
import dev.zacsweers.metro.ContributesTo
|
||||
import dev.zacsweers.metro.Provides
|
||||
import kotlin.time.TimeSource
|
||||
|
||||
@BindingContainer
|
||||
@ContributesTo(AppScope::class)
|
||||
object TimeModule {
|
||||
@Provides
|
||||
fun timeSource(): TimeSource {
|
||||
return TimeSource.Monotonic
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023-2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
plugins {
|
||||
id("io.element.android-library")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "io.element.android.services.toolbox.test"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(projects.services.toolbox.api)
|
||||
implementation(projects.tests.testutils)
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2024, 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.services.toolbox.test.intent
|
||||
|
||||
import android.content.Intent
|
||||
import io.element.android.services.toolbox.api.intent.ExternalIntentLauncher
|
||||
import io.element.android.tests.testutils.lambda.lambdaError
|
||||
|
||||
class FakeExternalIntentLauncher(
|
||||
var launchLambda: (Intent) -> Unit = { lambdaError() },
|
||||
) : ExternalIntentLauncher {
|
||||
override fun launch(intent: Intent) {
|
||||
launchLambda(intent)
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023-2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.services.toolbox.test.sdk
|
||||
|
||||
import io.element.android.services.toolbox.api.sdk.BuildVersionSdkIntProvider
|
||||
|
||||
class FakeBuildVersionSdkIntProvider(
|
||||
private val sdkInt: Int
|
||||
) : BuildVersionSdkIntProvider {
|
||||
override fun get(): Int = sdkInt
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023-2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.services.toolbox.test.strings
|
||||
|
||||
import io.element.android.services.toolbox.api.strings.StringProvider
|
||||
|
||||
class FakeStringProvider(
|
||||
private val defaultResult: String = "A string"
|
||||
) : StringProvider {
|
||||
var lastResIdParam: Int? = null
|
||||
override fun getString(resId: Int): String {
|
||||
lastResIdParam = resId
|
||||
return defaultResult
|
||||
}
|
||||
|
||||
override fun getString(resId: Int, vararg formatArgs: Any?): String {
|
||||
lastResIdParam = resId
|
||||
return defaultResult + formatArgs.joinToString()
|
||||
}
|
||||
|
||||
override fun getQuantityString(resId: Int, quantity: Int, vararg formatArgs: Any?): String {
|
||||
lastResIdParam = resId
|
||||
return defaultResult + " ($quantity) " + formatArgs.joinToString()
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023-2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.services.toolbox.test.systemclock
|
||||
|
||||
import io.element.android.services.toolbox.api.systemclock.SystemClock
|
||||
|
||||
const val A_FAKE_TIMESTAMP = 123L
|
||||
|
||||
class FakeSystemClock(
|
||||
var epochMillisResult: Long = A_FAKE_TIMESTAMP
|
||||
) : SystemClock {
|
||||
override fun epochMillis() = epochMillisResult
|
||||
}
|
||||
Reference in New Issue
Block a user