Merge pull request #224 from vector-im/bma/analytics
Add utility modules
This commit is contained in:
@@ -16,7 +16,7 @@ datastore = "1.0.0"
|
|||||||
constraintlayout = "2.1.4"
|
constraintlayout = "2.1.4"
|
||||||
recyclerview = "1.3.0"
|
recyclerview = "1.3.0"
|
||||||
lifecycle = "2.5.1"
|
lifecycle = "2.5.1"
|
||||||
activity_compose = "1.6.1"
|
activity = "1.6.1"
|
||||||
startup = "1.1.1"
|
startup = "1.1.1"
|
||||||
|
|
||||||
# Compose
|
# Compose
|
||||||
@@ -70,7 +70,8 @@ androidx_lifecycle_process = { module = "androidx.lifecycle:lifecycle-process",
|
|||||||
androidx_splash = "androidx.core:core-splashscreen:1.0.0"
|
androidx_splash = "androidx.core:core-splashscreen:1.0.0"
|
||||||
androidx_security_crypto = "androidx.security:security-crypto:1.0.0"
|
androidx_security_crypto = "androidx.security:security-crypto:1.0.0"
|
||||||
|
|
||||||
androidx_activity_compose = { module = "androidx.activity:activity-compose", version.ref = "activity_compose" }
|
androidx_activity_activity = { module = "androidx.activity:activity", version.ref = "activity" }
|
||||||
|
androidx_activity_compose = { module = "androidx.activity:activity-compose", version.ref = "activity" }
|
||||||
androidx_startup = { module = "androidx.startup:startup-runtime", version.ref = "startup" }
|
androidx_startup = { module = "androidx.startup:startup-runtime", version.ref = "startup" }
|
||||||
|
|
||||||
androidx_compose_bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose_bom" }
|
androidx_compose_bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose_bom" }
|
||||||
|
|||||||
@@ -26,5 +26,6 @@ android {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation(libs.timber)
|
implementation(libs.timber)
|
||||||
implementation(libs.androidx.corektx)
|
implementation(libs.androidx.corektx)
|
||||||
|
implementation(libs.androidx.activity.activity)
|
||||||
implementation(projects.libraries.core)
|
implementation(projects.libraries.core)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,4 +17,5 @@
|
|||||||
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<uses-permission android:name="android.permission.VIBRATE" />
|
<uses-permission android:name="android.permission.VIBRATE" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.libraries.androidutils.compat
|
||||||
|
|
||||||
|
import android.content.pm.ApplicationInfo
|
||||||
|
import android.content.pm.PackageInfo
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.Build
|
||||||
|
|
||||||
|
fun PackageManager.getApplicationInfoCompat(packageName: String, flags: Int): ApplicationInfo {
|
||||||
|
return when {
|
||||||
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> getApplicationInfo(
|
||||||
|
packageName,
|
||||||
|
PackageManager.ApplicationInfoFlags.of(flags.toLong())
|
||||||
|
)
|
||||||
|
else -> @Suppress("DEPRECATION") getApplicationInfo(packageName, flags)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun PackageManager.getPackageInfoCompat(packageName: String, flags: Int): PackageInfo {
|
||||||
|
return when {
|
||||||
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> getPackageInfo(
|
||||||
|
packageName,
|
||||||
|
PackageManager.PackageInfoFlags.of(flags.toLong())
|
||||||
|
)
|
||||||
|
else -> @Suppress("DEPRECATION") getPackageInfo(packageName, flags)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.libraries.androidutils.intent
|
||||||
|
|
||||||
|
import android.app.PendingIntent
|
||||||
|
import android.os.Build
|
||||||
|
|
||||||
|
object PendingIntentCompat {
|
||||||
|
const val FLAG_IMMUTABLE = PendingIntent.FLAG_IMMUTABLE
|
||||||
|
|
||||||
|
val FLAG_MUTABLE = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||||
|
PendingIntent.FLAG_MUTABLE
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.libraries.androidutils.network
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.ConnectivityManager
|
||||||
|
import android.net.NetworkCapabilities
|
||||||
|
import androidx.core.content.getSystemService
|
||||||
|
import io.element.android.libraries.core.bool.orFalse
|
||||||
|
import timber.log.Timber
|
||||||
|
|
||||||
|
class WifiDetector(
|
||||||
|
context: Context
|
||||||
|
) {
|
||||||
|
private val connectivityManager = context.getSystemService<ConnectivityManager>()!!
|
||||||
|
|
||||||
|
fun isConnectedToWifi(): Boolean {
|
||||||
|
return connectivityManager.activeNetwork
|
||||||
|
?.let { connectivityManager.getNetworkCapabilities(it) }
|
||||||
|
?.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
|
||||||
|
.orFalse()
|
||||||
|
.also { Timber.d("isConnected to WiFi: $it") }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2022 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.libraries.androidutils.system
|
||||||
|
|
||||||
|
import android.content.ClipData
|
||||||
|
import android.content.ClipboardManager
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.core.content.getSystemService
|
||||||
|
|
||||||
|
class CopyToClipboardUseCase(
|
||||||
|
private val context: Context,
|
||||||
|
) {
|
||||||
|
fun execute(text: CharSequence) {
|
||||||
|
context.getSystemService<ClipboardManager>()
|
||||||
|
?.setPrimaryClip(ClipData.newPlainText("", text))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,221 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.libraries.androidutils.system
|
||||||
|
|
||||||
|
import android.annotation.TargetApi
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.ActivityNotFoundException
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.PowerManager
|
||||||
|
import android.provider.Settings
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.activity.result.ActivityResultLauncher
|
||||||
|
import androidx.annotation.ChecksSdkIntAtLeast
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
|
import androidx.core.content.getSystemService
|
||||||
|
import io.element.android.libraries.androidutils.compat.getApplicationInfoCompat
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tells if the application ignores battery optimizations.
|
||||||
|
*
|
||||||
|
* Ignoring them allows the app to run in background to make background sync with the homeserver.
|
||||||
|
* This user option appears on Android M but Android O enforces its usage and kills apps not
|
||||||
|
* authorised by the user to run in background.
|
||||||
|
*
|
||||||
|
* @return true if battery optimisations are ignored
|
||||||
|
*/
|
||||||
|
fun Context.isIgnoringBatteryOptimizations(): Boolean {
|
||||||
|
// no issue before Android M, battery optimisations did not exist
|
||||||
|
return getSystemService<PowerManager>()?.isIgnoringBatteryOptimizations(packageName) == true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Context.isAirplaneModeOn(): Boolean {
|
||||||
|
return Settings.Global.getInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Context.isAnimationEnabled(): Boolean {
|
||||||
|
return Settings.Global.getFloat(contentResolver, Settings.Global.ANIMATOR_DURATION_SCALE, 1f) != 0f
|
||||||
|
}
|
||||||
|
|
||||||
|
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.O)
|
||||||
|
fun supportNotificationChannels() = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the application label of the provided package. If not found, the package is returned.
|
||||||
|
*/
|
||||||
|
fun Context.getApplicationLabel(packageName: String): String {
|
||||||
|
return try {
|
||||||
|
val ai = packageManager.getApplicationInfoCompat(packageName, 0)
|
||||||
|
packageManager.getApplicationLabel(ai).toString()
|
||||||
|
} catch (e: PackageManager.NameNotFoundException) {
|
||||||
|
packageName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* display the system dialog for granting this permission. If previously granted, the
|
||||||
|
* system will not show it (so you should call this method).
|
||||||
|
*
|
||||||
|
* Note: If the user finally does not grant the permission, PushManager.isBackgroundSyncAllowed()
|
||||||
|
* will return false and the notification privacy will fallback to "LOW_DETAIL".
|
||||||
|
*/
|
||||||
|
fun requestDisablingBatteryOptimization(activity: Activity, activityResultLauncher: ActivityResultLauncher<Intent>) {
|
||||||
|
val intent = Intent()
|
||||||
|
intent.action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
|
||||||
|
intent.data = Uri.parse("package:" + activity.packageName)
|
||||||
|
activityResultLauncher.launch(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==============================================================================================================
|
||||||
|
// Clipboard helper
|
||||||
|
// ==============================================================================================================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy a text to the clipboard, and display a Toast when done.
|
||||||
|
*
|
||||||
|
* @param context the context
|
||||||
|
* @param text the text to copy
|
||||||
|
* @param toastMessage content of the toast message as a String resource. Null for no toast
|
||||||
|
*/
|
||||||
|
fun copyToClipboard(
|
||||||
|
context: Context,
|
||||||
|
text: CharSequence,
|
||||||
|
toastMessage: String? = null
|
||||||
|
) {
|
||||||
|
CopyToClipboardUseCase(context).execute(text)
|
||||||
|
toastMessage?.let { context.toast(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows notification settings for the current app.
|
||||||
|
* In android O will directly opens the notification settings, in lower version it will show the App settings
|
||||||
|
*/
|
||||||
|
fun startNotificationSettingsIntent(context: Context, activityResultLauncher: ActivityResultLauncher<Intent>) {
|
||||||
|
val intent = Intent()
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
|
||||||
|
intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName)
|
||||||
|
} else {
|
||||||
|
intent.action = Settings.ACTION_APP_NOTIFICATION_SETTINGS
|
||||||
|
intent.putExtra("app_package", context.packageName)
|
||||||
|
intent.putExtra("app_uid", context.applicationInfo?.uid)
|
||||||
|
}
|
||||||
|
activityResultLauncher.launch(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows notification system settings for the given channel id.
|
||||||
|
*/
|
||||||
|
@TargetApi(Build.VERSION_CODES.O)
|
||||||
|
fun startNotificationChannelSettingsIntent(activity: Activity, channelID: String) {
|
||||||
|
if (!supportNotificationChannels()) return
|
||||||
|
val intent = Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS).apply {
|
||||||
|
putExtra(Settings.EXTRA_APP_PACKAGE, activity.packageName)
|
||||||
|
putExtra(Settings.EXTRA_CHANNEL_ID, channelID)
|
||||||
|
}
|
||||||
|
activity.startActivity(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun startAddGoogleAccountIntent(
|
||||||
|
context: Context,
|
||||||
|
activityResultLauncher: ActivityResultLauncher<Intent>,
|
||||||
|
noActivityFoundMessage: String,
|
||||||
|
) {
|
||||||
|
val intent = Intent(Settings.ACTION_ADD_ACCOUNT)
|
||||||
|
intent.putExtra(Settings.EXTRA_ACCOUNT_TYPES, arrayOf("com.google"))
|
||||||
|
try {
|
||||||
|
activityResultLauncher.launch(intent)
|
||||||
|
} catch (activityNotFoundException: ActivityNotFoundException) {
|
||||||
|
context.toast(noActivityFoundMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
|
fun startInstallFromSourceIntent(
|
||||||
|
context: Context,
|
||||||
|
activityResultLauncher: ActivityResultLauncher<Intent>,
|
||||||
|
noActivityFoundMessage: String,
|
||||||
|
) {
|
||||||
|
val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES)
|
||||||
|
.setData(Uri.parse(String.format("package:%s", context.packageName)))
|
||||||
|
try {
|
||||||
|
activityResultLauncher.launch(intent)
|
||||||
|
} catch (activityNotFoundException: ActivityNotFoundException) {
|
||||||
|
context.toast(noActivityFoundMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun startSharePlainTextIntent(
|
||||||
|
context: Context,
|
||||||
|
activityResultLauncher: ActivityResultLauncher<Intent>?,
|
||||||
|
chooserTitle: String?,
|
||||||
|
text: String,
|
||||||
|
subject: String? = null,
|
||||||
|
extraTitle: String? = null,
|
||||||
|
noActivityFoundMessage: String,
|
||||||
|
) {
|
||||||
|
val share = Intent(Intent.ACTION_SEND)
|
||||||
|
share.type = "text/plain"
|
||||||
|
share.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
|
||||||
|
// Add data to the intent, the receiving app will decide what to do with it.
|
||||||
|
share.putExtra(Intent.EXTRA_SUBJECT, subject)
|
||||||
|
share.putExtra(Intent.EXTRA_TEXT, text)
|
||||||
|
|
||||||
|
extraTitle?.let {
|
||||||
|
share.putExtra(Intent.EXTRA_TITLE, it)
|
||||||
|
}
|
||||||
|
|
||||||
|
val intent = Intent.createChooser(share, chooserTitle)
|
||||||
|
try {
|
||||||
|
if (activityResultLauncher != null) {
|
||||||
|
activityResultLauncher.launch(intent)
|
||||||
|
} else {
|
||||||
|
context.startActivity(intent)
|
||||||
|
}
|
||||||
|
} catch (activityNotFoundException: ActivityNotFoundException) {
|
||||||
|
context.toast(noActivityFoundMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun startImportTextFromFileIntent(
|
||||||
|
context: Context,
|
||||||
|
activityResultLauncher: ActivityResultLauncher<Intent>,
|
||||||
|
noActivityFoundMessage: String,
|
||||||
|
) {
|
||||||
|
val intent = Intent(Intent.ACTION_GET_CONTENT).apply {
|
||||||
|
type = "text/plain"
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
activityResultLauncher.launch(intent)
|
||||||
|
} catch (activityNotFoundException: ActivityNotFoundException) {
|
||||||
|
context.toast(noActivityFoundMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not in KTX anymore
|
||||||
|
fun Context.toast(resId: Int) {
|
||||||
|
Toast.makeText(this, resId, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not in KTX anymore
|
||||||
|
fun Context.toast(message: String) {
|
||||||
|
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.libraries.androidutils.throttler
|
||||||
|
|
||||||
|
import android.os.SystemClock
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple ThrottleFirst
|
||||||
|
* See https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/throttleFirst.png
|
||||||
|
*/
|
||||||
|
class FirstThrottler(private val minimumInterval: Long = 800) {
|
||||||
|
private var lastDate = 0L
|
||||||
|
|
||||||
|
sealed class CanHandleResult {
|
||||||
|
object Yes : CanHandleResult()
|
||||||
|
data class No(val shouldWaitMillis: Long) : CanHandleResult()
|
||||||
|
|
||||||
|
fun waitMillis(): Long {
|
||||||
|
return when (this) {
|
||||||
|
Yes -> 0
|
||||||
|
is No -> shouldWaitMillis
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun canHandle(): CanHandleResult {
|
||||||
|
val now = SystemClock.elapsedRealtime()
|
||||||
|
val delaySinceLast = now - lastDate
|
||||||
|
if (delaySinceLast > minimumInterval) {
|
||||||
|
lastDate = now
|
||||||
|
return CanHandleResult.Yes
|
||||||
|
}
|
||||||
|
|
||||||
|
// Too early
|
||||||
|
return CanHandleResult.No(minimumInterval - delaySinceLast)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.libraries.androidutils.uri
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
|
||||||
|
const val IGNORED_SCHEMA = "ignored"
|
||||||
|
|
||||||
|
fun Uri.isIgnored() = scheme == IGNORED_SCHEMA
|
||||||
|
|
||||||
|
fun createIgnoredUri(path: String): Uri = Uri.parse("$IGNORED_SCHEMA://$path")
|
||||||
@@ -65,7 +65,9 @@ fun DependencyHandlerScope.allLibrariesImpl() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun DependencyHandlerScope.allServicesImpl() {
|
fun DependencyHandlerScope.allServicesImpl() {
|
||||||
|
implementation(project(":services:analytics:noop"))
|
||||||
implementation(project(":services:appnavstate:impl"))
|
implementation(project(":services:appnavstate:impl"))
|
||||||
|
implementation(project(":services:toolbox:impl"))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun DependencyHandlerScope.allFeaturesApi() {
|
fun DependencyHandlerScope.allFeaturesApi() {
|
||||||
|
|||||||
23
services/analytics/api/build.gradle.kts
Normal file
23
services/analytics/api/build.gradle.kts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("io.element.android-library")
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "io.element.android.services.analytics.api"
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.services.analytics.api
|
||||||
|
|
||||||
|
import io.element.android.services.analytics.api.plan.UserProperties
|
||||||
|
|
||||||
|
interface AnalyticsTracker {
|
||||||
|
/**
|
||||||
|
* Capture an Event.
|
||||||
|
*/
|
||||||
|
fun capture(event: VectorAnalyticsEvent)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Track a displayed screen.
|
||||||
|
*/
|
||||||
|
fun screen(screen: VectorAnalyticsScreen)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update user specific properties.
|
||||||
|
*/
|
||||||
|
fun updateUserProperties(userProperties: UserProperties)
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.services.analytics.api
|
||||||
|
|
||||||
|
interface VectorAnalyticsEvent {
|
||||||
|
fun getName(): String
|
||||||
|
fun getProperties(): Map<String, Any?>?
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.services.analytics.api
|
||||||
|
|
||||||
|
interface VectorAnalyticsScreen {
|
||||||
|
fun getName(): String
|
||||||
|
fun getProperties(): Map<String, Any>?
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.services.analytics.api.plan
|
||||||
|
|
||||||
|
import io.element.android.services.analytics.api.VectorAnalyticsEvent
|
||||||
|
|
||||||
|
// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT
|
||||||
|
// https://github.com/matrix-org/matrix-analytics-events/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered when a call has ended.
|
||||||
|
*/
|
||||||
|
data class CallEnded(
|
||||||
|
/**
|
||||||
|
* The duration of the call in milliseconds.
|
||||||
|
*/
|
||||||
|
val durationMs: Int,
|
||||||
|
/**
|
||||||
|
* Whether its a video call or not.
|
||||||
|
*/
|
||||||
|
val isVideo: Boolean,
|
||||||
|
/**
|
||||||
|
* Number of participants in the call.
|
||||||
|
*/
|
||||||
|
val numParticipants: Int,
|
||||||
|
/**
|
||||||
|
* Whether this user placed it.
|
||||||
|
*/
|
||||||
|
val placed: Boolean,
|
||||||
|
) : VectorAnalyticsEvent {
|
||||||
|
|
||||||
|
override fun getName() = "CallEnded"
|
||||||
|
|
||||||
|
override fun getProperties(): Map<String, Any>? {
|
||||||
|
return mutableMapOf<String, Any>().apply {
|
||||||
|
put("durationMs", durationMs)
|
||||||
|
put("isVideo", isVideo)
|
||||||
|
put("numParticipants", numParticipants)
|
||||||
|
put("placed", placed)
|
||||||
|
}.takeIf { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.services.analytics.api.plan
|
||||||
|
|
||||||
|
import io.element.android.services.analytics.api.VectorAnalyticsEvent
|
||||||
|
|
||||||
|
// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT
|
||||||
|
// https://github.com/matrix-org/matrix-analytics-events/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered when an error occurred in a call.
|
||||||
|
*/
|
||||||
|
data class CallError(
|
||||||
|
/**
|
||||||
|
* Whether its a video call or not.
|
||||||
|
*/
|
||||||
|
val isVideo: Boolean,
|
||||||
|
/**
|
||||||
|
* Number of participants in the call.
|
||||||
|
*/
|
||||||
|
val numParticipants: Int,
|
||||||
|
/**
|
||||||
|
* Whether this user placed it.
|
||||||
|
*/
|
||||||
|
val placed: Boolean,
|
||||||
|
) : VectorAnalyticsEvent {
|
||||||
|
|
||||||
|
override fun getName() = "CallError"
|
||||||
|
|
||||||
|
override fun getProperties(): Map<String, Any>? {
|
||||||
|
return mutableMapOf<String, Any>().apply {
|
||||||
|
put("isVideo", isVideo)
|
||||||
|
put("numParticipants", numParticipants)
|
||||||
|
put("placed", placed)
|
||||||
|
}.takeIf { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.services.analytics.api.plan
|
||||||
|
|
||||||
|
import io.element.android.services.analytics.api.VectorAnalyticsEvent
|
||||||
|
|
||||||
|
// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT
|
||||||
|
// https://github.com/matrix-org/matrix-analytics-events/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered when a call is started.
|
||||||
|
*/
|
||||||
|
data class CallStarted(
|
||||||
|
/**
|
||||||
|
* Whether its a video call or not.
|
||||||
|
*/
|
||||||
|
val isVideo: Boolean,
|
||||||
|
/**
|
||||||
|
* Number of participants in the call.
|
||||||
|
*/
|
||||||
|
val numParticipants: Int,
|
||||||
|
/**
|
||||||
|
* Whether this user placed it.
|
||||||
|
*/
|
||||||
|
val placed: Boolean,
|
||||||
|
) : VectorAnalyticsEvent {
|
||||||
|
|
||||||
|
override fun getName() = "CallStarted"
|
||||||
|
|
||||||
|
override fun getProperties(): Map<String, Any>? {
|
||||||
|
return mutableMapOf<String, Any>().apply {
|
||||||
|
put("isVideo", isVideo)
|
||||||
|
put("numParticipants", numParticipants)
|
||||||
|
put("placed", placed)
|
||||||
|
}.takeIf { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.services.analytics.api.plan
|
||||||
|
|
||||||
|
import io.element.android.services.analytics.api.VectorAnalyticsEvent
|
||||||
|
|
||||||
|
// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT
|
||||||
|
// https://github.com/matrix-org/matrix-analytics-events/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered when the user sends a message via the composer.
|
||||||
|
*/
|
||||||
|
data class Composer(
|
||||||
|
/**
|
||||||
|
* Whether the user was using the composer inside of a thread.
|
||||||
|
*/
|
||||||
|
val inThread: Boolean,
|
||||||
|
/**
|
||||||
|
* Whether the user's composer interaction was editing a previously sent
|
||||||
|
* event.
|
||||||
|
*/
|
||||||
|
val isEditing: Boolean,
|
||||||
|
/**
|
||||||
|
* Whether the user's composer interaction was a reply to a previously
|
||||||
|
* sent event.
|
||||||
|
*/
|
||||||
|
val isReply: Boolean,
|
||||||
|
/**
|
||||||
|
* Whether this message begins a new thread or not.
|
||||||
|
*/
|
||||||
|
val startsThread: Boolean? = null,
|
||||||
|
) : VectorAnalyticsEvent {
|
||||||
|
|
||||||
|
override fun getName() = "Composer"
|
||||||
|
|
||||||
|
override fun getProperties(): Map<String, Any>? {
|
||||||
|
return mutableMapOf<String, Any>().apply {
|
||||||
|
put("inThread", inThread)
|
||||||
|
put("isEditing", isEditing)
|
||||||
|
put("isReply", isReply)
|
||||||
|
startsThread?.let { put("startsThread", it) }
|
||||||
|
}.takeIf { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.services.analytics.api.plan
|
||||||
|
|
||||||
|
import io.element.android.services.analytics.api.VectorAnalyticsEvent
|
||||||
|
|
||||||
|
// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT
|
||||||
|
// https://github.com/matrix-org/matrix-analytics-events/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered when the user creates a room.
|
||||||
|
*/
|
||||||
|
data class CreatedRoom(
|
||||||
|
/**
|
||||||
|
* Whether the room is a DM.
|
||||||
|
*/
|
||||||
|
val isDM: Boolean,
|
||||||
|
) : VectorAnalyticsEvent {
|
||||||
|
|
||||||
|
override fun getName() = "CreatedRoom"
|
||||||
|
|
||||||
|
override fun getProperties(): Map<String, Any>? {
|
||||||
|
return mutableMapOf<String, Any>().apply {
|
||||||
|
put("isDM", isDM)
|
||||||
|
}.takeIf { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.services.analytics.api.plan
|
||||||
|
|
||||||
|
import io.element.android.services.analytics.api.VectorAnalyticsEvent
|
||||||
|
|
||||||
|
// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT
|
||||||
|
// https://github.com/matrix-org/matrix-analytics-events/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered when an error occurred.
|
||||||
|
*/
|
||||||
|
data class Error(
|
||||||
|
/**
|
||||||
|
* Context - client defined, can be used for debugging.
|
||||||
|
*/
|
||||||
|
val context: String? = null,
|
||||||
|
/**
|
||||||
|
* Which crypto module is the client currently using.
|
||||||
|
*/
|
||||||
|
val cryptoModule: CryptoModule? = null,
|
||||||
|
val domain: Domain,
|
||||||
|
val name: Name,
|
||||||
|
) : VectorAnalyticsEvent {
|
||||||
|
|
||||||
|
enum class Domain {
|
||||||
|
E2EE,
|
||||||
|
TO_DEVICE,
|
||||||
|
VOIP,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class Name {
|
||||||
|
OlmIndexError,
|
||||||
|
OlmKeysNotSentError,
|
||||||
|
OlmUnspecifiedError,
|
||||||
|
ToDeviceFailedToDecrypt,
|
||||||
|
UnknownError,
|
||||||
|
VoipIceFailed,
|
||||||
|
VoipIceTimeout,
|
||||||
|
VoipInviteTimeout,
|
||||||
|
VoipUserHangup,
|
||||||
|
VoipUserMediaFailed,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class CryptoModule {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Native / legacy crypto module specific to each platform.
|
||||||
|
*/
|
||||||
|
Native,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shared / cross-platform crypto module written in Rust.
|
||||||
|
*/
|
||||||
|
Rust,
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getName() = "Error"
|
||||||
|
|
||||||
|
override fun getProperties(): Map<String, Any>? {
|
||||||
|
return mutableMapOf<String, Any>().apply {
|
||||||
|
context?.let { put("context", it) }
|
||||||
|
cryptoModule?.let { put("cryptoModule", it.name) }
|
||||||
|
put("domain", domain.name)
|
||||||
|
put("name", name.name)
|
||||||
|
}.takeIf { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,468 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.services.analytics.api.plan
|
||||||
|
|
||||||
|
import io.element.android.services.analytics.api.VectorAnalyticsEvent
|
||||||
|
|
||||||
|
// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT
|
||||||
|
// https://github.com/matrix-org/matrix-analytics-events/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered when the user clicks/taps/activates a UI element.
|
||||||
|
*/
|
||||||
|
data class Interaction(
|
||||||
|
/**
|
||||||
|
* The index of the element, if its in a list of elements.
|
||||||
|
*/
|
||||||
|
val index: Int? = null,
|
||||||
|
/**
|
||||||
|
* The manner with which the user activated the UI element.
|
||||||
|
*/
|
||||||
|
val interactionType: InteractionType? = null,
|
||||||
|
/**
|
||||||
|
* The unique name of this element.
|
||||||
|
*/
|
||||||
|
val name: Name,
|
||||||
|
) : VectorAnalyticsEvent {
|
||||||
|
|
||||||
|
enum class Name {
|
||||||
|
/**
|
||||||
|
* User tapped the All filter in the All Chats filter tab.
|
||||||
|
*/
|
||||||
|
MobileAllChatsFilterAll,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User tapped the Favourites filter in the All Chats filter tab.
|
||||||
|
*/
|
||||||
|
MobileAllChatsFilterFavourites,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User tapped the People filter in the All Chats filter tab.
|
||||||
|
*/
|
||||||
|
MobileAllChatsFilterPeople,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User tapped the Unreads filter in the All Chats filter tab.
|
||||||
|
*/
|
||||||
|
MobileAllChatsFilterUnreads,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User disabled filters from the all chats layout settings.
|
||||||
|
*/
|
||||||
|
MobileAllChatsFiltersDisabled,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User enabled filters from the all chats layout settings.
|
||||||
|
*/
|
||||||
|
MobileAllChatsFiltersEnabled,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User disabled recents from the all chats layout settings.
|
||||||
|
*/
|
||||||
|
MobileAllChatsRecentsDisabled,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User enabled recents from the all chats layout settings.
|
||||||
|
*/
|
||||||
|
MobileAllChatsRecentsEnabled,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User tapped on Add to Home button on Room Details screen.
|
||||||
|
*/
|
||||||
|
MobileRoomAddHome,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User tapped on Leave Room button on Room Details screen.
|
||||||
|
*/
|
||||||
|
MobileRoomLeave,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User tapped on Threads button on Room screen.
|
||||||
|
*/
|
||||||
|
MobileRoomThreadListButton,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User tapped on a thread summary item on Room screen.
|
||||||
|
*/
|
||||||
|
MobileRoomThreadSummaryItem,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User validated the creation of a new space.
|
||||||
|
*/
|
||||||
|
MobileSpaceCreationValidated,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User tapped on the filter button on ThreadList screen.
|
||||||
|
*/
|
||||||
|
MobileThreadListFilterItem,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User selected a thread on ThreadList screen.
|
||||||
|
*/
|
||||||
|
MobileThreadListThreadItem,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User tapped the already selected space from the space list.
|
||||||
|
*/
|
||||||
|
SpacePanelSelectedSpace,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User tapped an unselected space from the space list -> space
|
||||||
|
* switching should occur.
|
||||||
|
*/
|
||||||
|
SpacePanelSwitchSpace,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User tapped an unselected sub space from the space list -> space
|
||||||
|
* switching should occur.
|
||||||
|
*/
|
||||||
|
SpacePanelSwitchSubSpace,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked the create room button in the add existing room to space
|
||||||
|
* dialog in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebAddExistingToSpaceDialogCreateRoomButton,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked the create DM button in the home page of Element
|
||||||
|
* Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebHomeCreateChatButton,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked the create room button in the home page of Element
|
||||||
|
* Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebHomeCreateRoomButton,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked the explore rooms button in the home page of Element
|
||||||
|
* Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebHomeExploreRoomsButton,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked on the mini avatar uploader in the home page of Element
|
||||||
|
* Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebHomeMiniAvatarUploadButton,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked the explore rooms button next to the search field at the
|
||||||
|
* top of the left panel in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebLeftPanelExploreRoomsButton,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked on the avatar uploader in the profile settings of
|
||||||
|
* Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebProfileSettingsAvatarUploadButton,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User interacted with pin to sidebar checkboxes in the quick settings
|
||||||
|
* menu of Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebQuickSettingsPinToSidebarCheckbox,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User interacted with the theme dropdown in the quick settings menu of
|
||||||
|
* Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebQuickSettingsThemeDropdown,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User accessed the room invite flow using the button at the top of the
|
||||||
|
* room member list in the right panel of Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRightPanelMemberListInviteButton,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User accessed room member list using the 'People' button in the right
|
||||||
|
* panel room summary card of Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRightPanelRoomInfoPeopleButton,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User accessed room settings using the 'Settings' button in the right
|
||||||
|
* panel room summary card of Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRightPanelRoomInfoSettingsButton,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User accessed room member list using the back button in the right
|
||||||
|
* panel user info card of Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRightPanelRoomUserInfoBackButton,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User invited someone to room by clicking invite on the right panel
|
||||||
|
* user info card in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRightPanelRoomUserInfoInviteButton,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked the threads 'show' filter dropdown in the threads panel
|
||||||
|
* in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRightPanelThreadPanelFilterDropdown,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked the create room button in the room directory of Element
|
||||||
|
* Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomDirectoryCreateRoomButton,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked the Threads button in the top right of a room in Element
|
||||||
|
* Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomHeaderButtonsThreadsButton,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User adjusted their favourites using the context menu on the header
|
||||||
|
* of a room in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomHeaderContextMenuFavouriteToggle,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User accessed the room invite flow using the context menu on the
|
||||||
|
* header of a room in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomHeaderContextMenuInviteItem,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User interacted with leave action in the context menu on the header
|
||||||
|
* of a room in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomHeaderContextMenuLeaveItem,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User accessed their room notification settings via the context menu
|
||||||
|
* on the header of a room in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomHeaderContextMenuNotificationsItem,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User accessed room member list using the context menu on the header
|
||||||
|
* of a room in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomHeaderContextMenuPeopleItem,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User accessed room settings using the context menu on the header of a
|
||||||
|
* room in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomHeaderContextMenuSettingsItem,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked the create DM button in the + context menu of the room
|
||||||
|
* list header in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomListHeaderPlusMenuCreateChatItem,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked the create room button in the + context menu of the room
|
||||||
|
* list header in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomListHeaderPlusMenuCreateRoomItem,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked the explore rooms button in the + context menu of the
|
||||||
|
* room list header in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomListHeaderPlusMenuExploreRoomsItem,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User adjusted their favourites using the context menu on a room tile
|
||||||
|
* in the room list in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomListRoomTileContextMenuFavouriteToggle,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User accessed the room invite flow using the context menu on a room
|
||||||
|
* tile in the room list in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomListRoomTileContextMenuInviteItem,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User interacted with leave action in the context menu on a room tile
|
||||||
|
* in the room list in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomListRoomTileContextMenuLeaveItem,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User accessed room settings using the context menu on a room tile in
|
||||||
|
* the room list in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomListRoomTileContextMenuSettingsItem,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User accessed their room notification settings via the context menu
|
||||||
|
* on a room tile in the room list in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomListRoomTileNotificationsMenu,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked the create DM button in the + context menu of the rooms
|
||||||
|
* sublist in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomListRoomsSublistPlusMenuCreateChatItem,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked the create room button in the + context menu of the
|
||||||
|
* rooms sublist in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomListRoomsSublistPlusMenuCreateRoomItem,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked the explore rooms button in the + context menu of the
|
||||||
|
* rooms sublist in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomListRoomsSublistPlusMenuExploreRoomsItem,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked on the button to return to the user onboarding list in
|
||||||
|
* the room list in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomListUserOnboardingButton,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked on the button to close the user onboarding button in the
|
||||||
|
* room list in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomListUserOnboardingIgnoreButton,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User interacted with leave action in the general tab of the room
|
||||||
|
* settings dialog in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomSettingsLeaveButton,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User interacted with the prompt to create a new room when adjusting
|
||||||
|
* security settings in an existing room in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomSettingsSecurityTabCreateNewRoomButton,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked a thread summary in the timeline of a room in Element
|
||||||
|
* Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomTimelineThreadSummaryButton,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User interacted with the theme radio selector in the Appearance tab
|
||||||
|
* of Settings in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebSettingsAppearanceTabThemeSelector,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User interacted with the pre-built space checkboxes in the Sidebar
|
||||||
|
* tab of Settings in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebSettingsSidebarTabSpacesCheckbox,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked the explore rooms button in the context menu of a space
|
||||||
|
* in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebSpaceContextMenuExploreRoomsItem,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked the home button in the context menu of a space in
|
||||||
|
* Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebSpaceContextMenuHomeItem,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked the new room button in the context menu of a space in
|
||||||
|
* Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebSpaceContextMenuNewRoomItem,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked the new room button in the context menu on the space
|
||||||
|
* home in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebSpaceHomeCreateRoomButton,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked the back button on a Thread view going back to the
|
||||||
|
* Threads Panel of Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebThreadViewBackButton,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User selected a thread in the Threads panel in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebThreadsPanelThreadItem,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked the theme toggle button in the user menu of Element
|
||||||
|
* Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebUserMenuThemeToggleButton,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked on the send DM CTA in the header of the new user
|
||||||
|
* onboarding page in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebUserOnboardingHeaderSendDm,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked on the action of the download apps task on the new user
|
||||||
|
* onboarding page in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebUserOnboardingTaskDownloadApps,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked on the action of the enable notifications task on the
|
||||||
|
* new user onboarding page in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebUserOnboardingTaskEnableNotifications,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked on the action of the find people task on the new user
|
||||||
|
* onboarding page in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebUserOnboardingTaskSendDm,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User clicked on the action of the your profile task on the new user
|
||||||
|
* onboarding page in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebUserOnboardingTaskSetupProfile,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class InteractionType {
|
||||||
|
Keyboard,
|
||||||
|
Pointer,
|
||||||
|
Touch,
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getName() = "Interaction"
|
||||||
|
|
||||||
|
override fun getProperties(): Map<String, Any>? {
|
||||||
|
return mutableMapOf<String, Any>().apply {
|
||||||
|
index?.let { put("index", it) }
|
||||||
|
interactionType?.let { put("interactionType", it.name) }
|
||||||
|
put("name", name.name)
|
||||||
|
}.takeIf { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.services.analytics.api.plan
|
||||||
|
|
||||||
|
import io.element.android.services.analytics.api.VectorAnalyticsEvent
|
||||||
|
|
||||||
|
// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT
|
||||||
|
// https://github.com/matrix-org/matrix-analytics-events/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered when the user joins a room.
|
||||||
|
*/
|
||||||
|
data class JoinedRoom(
|
||||||
|
/**
|
||||||
|
* Whether the room is a DM.
|
||||||
|
*/
|
||||||
|
val isDM: Boolean,
|
||||||
|
/**
|
||||||
|
* Whether the room is a Space.
|
||||||
|
*/
|
||||||
|
val isSpace: Boolean,
|
||||||
|
/**
|
||||||
|
* The size of the room.
|
||||||
|
*/
|
||||||
|
val roomSize: RoomSize,
|
||||||
|
/**
|
||||||
|
* The trigger for a room being joined if known.
|
||||||
|
*/
|
||||||
|
val trigger: Trigger? = null,
|
||||||
|
) : VectorAnalyticsEvent {
|
||||||
|
|
||||||
|
enum class Trigger {
|
||||||
|
/**
|
||||||
|
* Room joined via an invite.
|
||||||
|
*/
|
||||||
|
Invite,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room joined via link.
|
||||||
|
*/
|
||||||
|
MobilePermalink,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room joined via a push/desktop notification.
|
||||||
|
*/
|
||||||
|
Notification,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room joined via the public rooms directory.
|
||||||
|
*/
|
||||||
|
RoomDirectory,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room joined via its preview.
|
||||||
|
*/
|
||||||
|
RoomPreview,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room joined via the /join slash command.
|
||||||
|
*/
|
||||||
|
SlashCommand,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room joined via the space hierarchy view.
|
||||||
|
*/
|
||||||
|
SpaceHierarchy,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room joined via a timeline pill or link in another room.
|
||||||
|
*/
|
||||||
|
Timeline,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class RoomSize {
|
||||||
|
ElevenToOneHundred,
|
||||||
|
MoreThanAThousand,
|
||||||
|
One,
|
||||||
|
OneHundredAndOneToAThousand,
|
||||||
|
ThreeToTen,
|
||||||
|
Two,
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getName() = "JoinedRoom"
|
||||||
|
|
||||||
|
override fun getProperties(): Map<String, Any>? {
|
||||||
|
return mutableMapOf<String, Any>().apply {
|
||||||
|
put("isDM", isDM)
|
||||||
|
put("isSpace", isSpace)
|
||||||
|
put("roomSize", roomSize.name)
|
||||||
|
trigger?.let { put("trigger", it.name) }
|
||||||
|
}.takeIf { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,327 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.services.analytics.api.plan
|
||||||
|
|
||||||
|
import io.element.android.services.analytics.api.VectorAnalyticsScreen
|
||||||
|
|
||||||
|
// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT
|
||||||
|
// https://github.com/matrix-org/matrix-analytics-events/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered when the user changed screen on Element Android/iOS.
|
||||||
|
*/
|
||||||
|
data class MobileScreen(
|
||||||
|
/**
|
||||||
|
* How long the screen was displayed for in milliseconds.
|
||||||
|
*/
|
||||||
|
val durationMs: Int? = null,
|
||||||
|
val screenName: ScreenName,
|
||||||
|
) : VectorAnalyticsScreen {
|
||||||
|
|
||||||
|
enum class ScreenName {
|
||||||
|
/**
|
||||||
|
* The screen that displays the user's breadcrumbs.
|
||||||
|
*/
|
||||||
|
Breadcrumbs,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The screen shown to create a new (non-direct) room.
|
||||||
|
*/
|
||||||
|
CreateRoom,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The screen shown to create a new space.
|
||||||
|
*/
|
||||||
|
CreateSpace,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The confirmation screen shown before deactivating an account.
|
||||||
|
*/
|
||||||
|
DeactivateAccount,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tab on mobile that displays the dialpad.
|
||||||
|
*/
|
||||||
|
Dialpad,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Favourites tab on mobile that lists your favourite people/rooms.
|
||||||
|
*/
|
||||||
|
Favourites,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The form for the forgot password use case.
|
||||||
|
*/
|
||||||
|
ForgotPassword,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Legacy: The screen that shows information about a specific group.
|
||||||
|
*/
|
||||||
|
Group,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Home tab on iOS | possibly the same on Android?
|
||||||
|
*/
|
||||||
|
Home,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The screen shown to share a link to download the app.
|
||||||
|
*/
|
||||||
|
InviteFriends,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via space bottom sheet list.
|
||||||
|
*/
|
||||||
|
Invites,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The screen that displays the login flow (when the user already has an
|
||||||
|
* account).
|
||||||
|
*/
|
||||||
|
Login,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Legacy: The screen that shows all groups/communities you have joined.
|
||||||
|
*/
|
||||||
|
MyGroups,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The People tab on mobile that lists all the DM rooms you have joined.
|
||||||
|
*/
|
||||||
|
People,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The screen that displays the registration flow (when the user wants
|
||||||
|
* to create an account).
|
||||||
|
*/
|
||||||
|
Register,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The screen that displays the messages and events received in a room.
|
||||||
|
*/
|
||||||
|
Room,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The room addresses screen shown from the Room Details screen.
|
||||||
|
*/
|
||||||
|
RoomAddresses,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The screen shown when tapping the name of a room from the Room
|
||||||
|
* screen.
|
||||||
|
*/
|
||||||
|
RoomDetails,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The screen that lists public rooms for you to discover.
|
||||||
|
*/
|
||||||
|
RoomDirectory,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The screen that lists all the user's rooms and let them filter the
|
||||||
|
* rooms.
|
||||||
|
*/
|
||||||
|
RoomFilter,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The screen that displays the list of members that are part of a room.
|
||||||
|
*/
|
||||||
|
RoomMembers,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The notifications settings screen shown from the Room Details screen.
|
||||||
|
*/
|
||||||
|
RoomNotifications,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The roles permissions screen shown from the Room Details screen.
|
||||||
|
*/
|
||||||
|
RoomPermissions,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Screen that displays room preview if user hasn't joined yet.
|
||||||
|
*/
|
||||||
|
RoomPreview,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The screen that allows you to search for messages/files in a specific
|
||||||
|
* room.
|
||||||
|
*/
|
||||||
|
RoomSearch,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The settings screen shown from the Room Details screen.
|
||||||
|
*/
|
||||||
|
RoomSettings,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The screen that allows you to see all of the files sent in a specific
|
||||||
|
* room.
|
||||||
|
*/
|
||||||
|
RoomUploads,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Rooms tab on mobile that lists all the (non-direct) rooms you've
|
||||||
|
* joined.
|
||||||
|
*/
|
||||||
|
Rooms,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Files tab shown in the global search screen on Mobile.
|
||||||
|
*/
|
||||||
|
SearchFiles,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Messages tab shown in the global search screen on Mobile.
|
||||||
|
*/
|
||||||
|
SearchMessages,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The People tab shown in the global search screen on Mobile.
|
||||||
|
*/
|
||||||
|
SearchPeople,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Rooms tab shown in the global search screen on Mobile.
|
||||||
|
*/
|
||||||
|
SearchRooms,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The global settings screen shown in the app.
|
||||||
|
*/
|
||||||
|
Settings,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The advanced settings screen (developer mode, rageshake, push
|
||||||
|
* notification rules).
|
||||||
|
*/
|
||||||
|
SettingsAdvanced,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The settings screen to change the default notification options.
|
||||||
|
*/
|
||||||
|
SettingsDefaultNotifications,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The settings screen with general profile settings.
|
||||||
|
*/
|
||||||
|
SettingsGeneral,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Help and About screen.
|
||||||
|
*/
|
||||||
|
SettingsHelp,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The settings screen with list of the ignored users.
|
||||||
|
*/
|
||||||
|
SettingsIgnoredUsers,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The experimental features settings screen.
|
||||||
|
*/
|
||||||
|
SettingsLabs,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The settings screen with legals information.
|
||||||
|
*/
|
||||||
|
SettingsLegals,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The settings screen to manage notification mentions and keywords.
|
||||||
|
*/
|
||||||
|
SettingsMentionsAndKeywords,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The notifications settings screen.
|
||||||
|
*/
|
||||||
|
SettingsNotifications,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The preferences screen (theme, language, editor preferences, etc.
|
||||||
|
*/
|
||||||
|
SettingsPreferences,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The global security settings screen.
|
||||||
|
*/
|
||||||
|
SettingsSecurity,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The calls settings screen.
|
||||||
|
*/
|
||||||
|
SettingsVoiceVideo,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The sidebar shown on mobile with spaces, settings etc.
|
||||||
|
*/
|
||||||
|
Sidebar,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via space bottom sheet list.
|
||||||
|
*/
|
||||||
|
SpaceBottomSheet,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Screen that displays the list of rooms and spaces of a space.
|
||||||
|
*/
|
||||||
|
SpaceExploreRooms,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Screen that displays the list of members of a space.
|
||||||
|
*/
|
||||||
|
SpaceMembers,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The bottom sheet that list all space options.
|
||||||
|
*/
|
||||||
|
SpaceMenu,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The screen shown to create a new direct room.
|
||||||
|
*/
|
||||||
|
StartChat,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The screen shown to select which room directory you'd like to use.
|
||||||
|
*/
|
||||||
|
SwitchDirectory,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Screen that displays list of threads for a room.
|
||||||
|
*/
|
||||||
|
ThreadList,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A screen that shows information about a room member.
|
||||||
|
*/
|
||||||
|
User,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The splash screen.
|
||||||
|
*/
|
||||||
|
Welcome,
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getName() = screenName.name
|
||||||
|
|
||||||
|
override fun getProperties(): Map<String, Any>? {
|
||||||
|
return mutableMapOf<String, Any>().apply {
|
||||||
|
durationMs?.let { put("durationMs", it) }
|
||||||
|
}.takeIf { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.services.analytics.api.plan
|
||||||
|
|
||||||
|
import io.element.android.services.analytics.api.VectorAnalyticsEvent
|
||||||
|
|
||||||
|
// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT
|
||||||
|
// https://github.com/matrix-org/matrix-analytics-events/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered after timing an operation in the app.
|
||||||
|
*/
|
||||||
|
data class PerformanceTimer(
|
||||||
|
/**
|
||||||
|
* Client defined, can be used for debugging.
|
||||||
|
*/
|
||||||
|
val context: String? = null,
|
||||||
|
/**
|
||||||
|
* Client defined, an optional value to indicate how many items were
|
||||||
|
* handled during the operation.
|
||||||
|
*/
|
||||||
|
val itemCount: Int? = null,
|
||||||
|
/**
|
||||||
|
* The timer that is being reported.
|
||||||
|
*/
|
||||||
|
val name: Name,
|
||||||
|
/**
|
||||||
|
* The time reported by the timer in milliseconds.
|
||||||
|
*/
|
||||||
|
val timeMs: Int,
|
||||||
|
) : VectorAnalyticsEvent {
|
||||||
|
|
||||||
|
enum class Name {
|
||||||
|
/**
|
||||||
|
* The time spent parsing the response from an initial /sync request. In
|
||||||
|
* this case, `itemCount` should contain the number of joined rooms.
|
||||||
|
*/
|
||||||
|
InitialSyncParsing,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The time spent waiting for a response to an initial /sync request. In
|
||||||
|
* this case, `itemCount` should contain the number of joined rooms.
|
||||||
|
*/
|
||||||
|
InitialSyncRequest,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The time taken to display an event in the timeline that was opened
|
||||||
|
* from a notification.
|
||||||
|
*/
|
||||||
|
NotificationsOpenEvent,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The duration of a regular /sync request when resuming the app. In
|
||||||
|
* this case, `itemCount` should contain the number of joined rooms in
|
||||||
|
* the response.
|
||||||
|
*/
|
||||||
|
StartupIncrementalSync,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The duration of an initial /sync request during startup (if the store
|
||||||
|
* has been wiped). In this case, `itemCount` should contain the number
|
||||||
|
* of joined rooms.
|
||||||
|
*/
|
||||||
|
StartupInitialSync,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* How long the app launch screen is displayed for.
|
||||||
|
*/
|
||||||
|
StartupLaunchScreen,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The time to preload data in the MXStore on iOS. In this case,
|
||||||
|
* `itemCount` should contain the number of rooms in the store.
|
||||||
|
*/
|
||||||
|
StartupStorePreload,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The time to load all data from the store (including
|
||||||
|
* StartupStorePreload time). In this case, `itemCount` should contain
|
||||||
|
* the number of rooms loaded into the session
|
||||||
|
*/
|
||||||
|
StartupStoreReady,
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getName() = "PerformanceTimer"
|
||||||
|
|
||||||
|
override fun getProperties(): Map<String, Any>? {
|
||||||
|
return mutableMapOf<String, Any>().apply {
|
||||||
|
context?.let { put("context", it) }
|
||||||
|
itemCount?.let { put("itemCount", it) }
|
||||||
|
put("name", name.name)
|
||||||
|
put("timeMs", timeMs)
|
||||||
|
}.takeIf { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.services.analytics.api.plan
|
||||||
|
|
||||||
|
import io.element.android.services.analytics.api.VectorAnalyticsEvent
|
||||||
|
|
||||||
|
// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT
|
||||||
|
// https://github.com/matrix-org/matrix-analytics-events/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered when the user changes a permission status.
|
||||||
|
*/
|
||||||
|
data class PermissionChanged(
|
||||||
|
/**
|
||||||
|
* Whether the permission has been granted by the user.
|
||||||
|
*/
|
||||||
|
val granted: Boolean,
|
||||||
|
/**
|
||||||
|
* The name of the permission.
|
||||||
|
*/
|
||||||
|
val permission: Permission,
|
||||||
|
) : VectorAnalyticsEvent {
|
||||||
|
|
||||||
|
enum class Permission {
|
||||||
|
/**
|
||||||
|
* Permissions related to sending notifications have changed.
|
||||||
|
*/
|
||||||
|
Notification,
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getName() = "PermissionChanged"
|
||||||
|
|
||||||
|
override fun getProperties(): Map<String, Any>? {
|
||||||
|
return mutableMapOf<String, Any>().apply {
|
||||||
|
put("granted", granted)
|
||||||
|
put("permission", permission.name)
|
||||||
|
}.takeIf { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.services.analytics.api.plan
|
||||||
|
|
||||||
|
import io.element.android.services.analytics.api.VectorAnalyticsEvent
|
||||||
|
|
||||||
|
// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT
|
||||||
|
// https://github.com/matrix-org/matrix-analytics-events/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered once onboarding has completed, but only if the user registered a
|
||||||
|
* new account.
|
||||||
|
*/
|
||||||
|
data class Signup(
|
||||||
|
/**
|
||||||
|
* The type of authentication that was used to sign up.
|
||||||
|
*/
|
||||||
|
val authenticationType: AuthenticationType,
|
||||||
|
) : VectorAnalyticsEvent {
|
||||||
|
|
||||||
|
enum class AuthenticationType {
|
||||||
|
/**
|
||||||
|
* Social login using Apple.
|
||||||
|
*/
|
||||||
|
Apple,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Social login using Facebook.
|
||||||
|
*/
|
||||||
|
Facebook,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Social login using GitHub.
|
||||||
|
*/
|
||||||
|
GitHub,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Social login using GitLab.
|
||||||
|
*/
|
||||||
|
GitLab,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Social login using Google.
|
||||||
|
*/
|
||||||
|
Google,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registration using some other mechanism such as fallback.
|
||||||
|
*/
|
||||||
|
Other,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registration with a username and password.
|
||||||
|
*/
|
||||||
|
Password,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registration using another SSO provider.
|
||||||
|
*/
|
||||||
|
SSO,
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getName() = "Signup"
|
||||||
|
|
||||||
|
override fun getProperties(): Map<String, Any>? {
|
||||||
|
return mutableMapOf<String, Any>().apply {
|
||||||
|
put("authenticationType", authenticationType.name)
|
||||||
|
}.takeIf { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.services.analytics.api.plan
|
||||||
|
|
||||||
|
import io.element.android.services.analytics.api.VectorAnalyticsEvent
|
||||||
|
|
||||||
|
// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT
|
||||||
|
// https://github.com/matrix-org/matrix-analytics-events/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered when the user runs a slash command in their composer.
|
||||||
|
*/
|
||||||
|
data class SlashCommand(
|
||||||
|
/**
|
||||||
|
* The name of this command.
|
||||||
|
*/
|
||||||
|
val command: Command,
|
||||||
|
) : VectorAnalyticsEvent {
|
||||||
|
|
||||||
|
enum class Command {
|
||||||
|
Invite,
|
||||||
|
Part,
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getName() = "SlashCommand"
|
||||||
|
|
||||||
|
override fun getProperties(): Map<String, Any>? {
|
||||||
|
return mutableMapOf<String, Any>().apply {
|
||||||
|
put("command", command.name)
|
||||||
|
}.takeIf { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.services.analytics.api.plan
|
||||||
|
|
||||||
|
import io.element.android.services.analytics.api.VectorAnalyticsEvent
|
||||||
|
|
||||||
|
// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT
|
||||||
|
// https://github.com/matrix-org/matrix-analytics-events/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered when the user becomes unauthenticated without actually clicking
|
||||||
|
* sign out(E.g. Due to expiry of an access token without a way to refresh).
|
||||||
|
*/
|
||||||
|
data class UnauthenticatedError(
|
||||||
|
/**
|
||||||
|
* The error code as defined in matrix spec. The source of this error is
|
||||||
|
* from the homeserver.
|
||||||
|
*/
|
||||||
|
val errorCode: ErrorCode,
|
||||||
|
/**
|
||||||
|
* The reason for the error. The source of this error is from the
|
||||||
|
* homeserver, the reason can vary and is subject to change so there is
|
||||||
|
* no enum of possible values.
|
||||||
|
*/
|
||||||
|
val errorReason: String,
|
||||||
|
/**
|
||||||
|
* Whether the auth mechanism is refresh-token-based.
|
||||||
|
*/
|
||||||
|
val refreshTokenAuth: Boolean,
|
||||||
|
/**
|
||||||
|
* Whether a soft logout or hard logout was triggered.
|
||||||
|
*/
|
||||||
|
val softLogout: Boolean,
|
||||||
|
) : VectorAnalyticsEvent {
|
||||||
|
|
||||||
|
enum class ErrorCode {
|
||||||
|
M_FORBIDDEN,
|
||||||
|
M_UNKNOWN,
|
||||||
|
M_UNKNOWN_TOKEN,
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getName() = "UnauthenticatedError"
|
||||||
|
|
||||||
|
override fun getProperties(): Map<String, Any>? {
|
||||||
|
return mutableMapOf<String, Any>().apply {
|
||||||
|
put("errorCode", errorCode.name)
|
||||||
|
put("errorReason", errorReason)
|
||||||
|
put("refreshTokenAuth", refreshTokenAuth)
|
||||||
|
put("softLogout", softLogout)
|
||||||
|
}.takeIf { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.services.analytics.api.plan
|
||||||
|
|
||||||
|
// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT
|
||||||
|
// https://github.com/matrix-org/matrix-analytics-events/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user properties to apply when identifying. This is not an event
|
||||||
|
* definition. These properties must all be device independent.
|
||||||
|
*/
|
||||||
|
data class UserProperties(
|
||||||
|
/**
|
||||||
|
* The active filter in the All Chats screen.
|
||||||
|
*/
|
||||||
|
val allChatsActiveFilter: AllChatsActiveFilter? = null,
|
||||||
|
/**
|
||||||
|
* The selected messaging use case during the onboarding flow.
|
||||||
|
*/
|
||||||
|
val ftueUseCaseSelection: FtueUseCaseSelection? = null,
|
||||||
|
/**
|
||||||
|
* Number of joined rooms the user has favourited.
|
||||||
|
*/
|
||||||
|
val numFavouriteRooms: Int? = null,
|
||||||
|
/**
|
||||||
|
* Number of spaces (and sub-spaces) the user is joined to.
|
||||||
|
*/
|
||||||
|
val numSpaces: Int? = null,
|
||||||
|
) {
|
||||||
|
|
||||||
|
enum class FtueUseCaseSelection {
|
||||||
|
/**
|
||||||
|
* The third option, Communities.
|
||||||
|
*/
|
||||||
|
CommunityMessaging,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The first option, Friends and family.
|
||||||
|
*/
|
||||||
|
PersonalMessaging,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The footer option to skip the question.
|
||||||
|
*/
|
||||||
|
Skip,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The second option, Teams.
|
||||||
|
*/
|
||||||
|
WorkMessaging,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class AllChatsActiveFilter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters are activated and All is selected.
|
||||||
|
*/
|
||||||
|
All,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters are activated and Favourites is selected.
|
||||||
|
*/
|
||||||
|
Favourites,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters are activated and People is selected.
|
||||||
|
*/
|
||||||
|
People,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters are activated and Unreads is selected.
|
||||||
|
*/
|
||||||
|
Unreads,
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getProperties(): Map<String, Any>? {
|
||||||
|
return mutableMapOf<String, Any>().apply {
|
||||||
|
allChatsActiveFilter?.let { put("allChatsActiveFilter", it.name) }
|
||||||
|
ftueUseCaseSelection?.let { put("ftueUseCaseSelection", it.name) }
|
||||||
|
numFavouriteRooms?.let { put("numFavouriteRooms", it) }
|
||||||
|
numSpaces?.let { put("numSpaces", it) }
|
||||||
|
}.takeIf { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,306 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2021 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.services.analytics.api.plan
|
||||||
|
|
||||||
|
import io.element.android.services.analytics.api.VectorAnalyticsEvent
|
||||||
|
|
||||||
|
// GENERATED FILE, DO NOT EDIT. FOR MORE INFORMATION VISIT
|
||||||
|
// https://github.com/matrix-org/matrix-analytics-events/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggered when the user changes rooms.
|
||||||
|
*/
|
||||||
|
data class ViewRoom(
|
||||||
|
/**
|
||||||
|
* active space when user navigated to the room.
|
||||||
|
*/
|
||||||
|
val activeSpace: ActiveSpace? = null,
|
||||||
|
/**
|
||||||
|
* Whether the room is a DM.
|
||||||
|
*/
|
||||||
|
val isDM: Boolean? = null,
|
||||||
|
/**
|
||||||
|
* Whether the room is a Space.
|
||||||
|
*/
|
||||||
|
val isSpace: Boolean? = null,
|
||||||
|
/**
|
||||||
|
* The reason for the room change if known.
|
||||||
|
*/
|
||||||
|
val trigger: Trigger? = null,
|
||||||
|
/**
|
||||||
|
* Whether the interaction was performed via the keyboard input.
|
||||||
|
*/
|
||||||
|
val viaKeyboard: Boolean? = null,
|
||||||
|
) : VectorAnalyticsEvent {
|
||||||
|
|
||||||
|
enum class Trigger {
|
||||||
|
/**
|
||||||
|
* Room accessed due to being just created.
|
||||||
|
*/
|
||||||
|
Created,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room switched due to user interacting with a message search result.
|
||||||
|
*/
|
||||||
|
MessageSearch,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room switched due to user selecting a user to go to a DM with.
|
||||||
|
*/
|
||||||
|
MessageUser,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via space explore.
|
||||||
|
*/
|
||||||
|
MobileExploreRooms,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room switched due to user interacting with a file search result.
|
||||||
|
*/
|
||||||
|
MobileFileSearch,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via interacting with the incall screen.
|
||||||
|
*/
|
||||||
|
MobileInCall,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed during external sharing.
|
||||||
|
*/
|
||||||
|
MobileLinkShare,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via link.
|
||||||
|
*/
|
||||||
|
MobilePermalink,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via interacting with direct chat item in the room
|
||||||
|
* contact detail screen.
|
||||||
|
*/
|
||||||
|
MobileRoomMemberDetail,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via preview.
|
||||||
|
*/
|
||||||
|
MobileRoomPreview,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room switched due to user interacting with a room search result.
|
||||||
|
*/
|
||||||
|
MobileRoomSearch,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via interacting with direct chat item in the search
|
||||||
|
* contact detail screen.
|
||||||
|
*/
|
||||||
|
MobileSearchContactDetail,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via space bottom sheet list.
|
||||||
|
*/
|
||||||
|
MobileSpaceBottomSheet,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via interacting with direct chat item in the space
|
||||||
|
* contact detail screen.
|
||||||
|
*/
|
||||||
|
MobileSpaceMemberDetail,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via space members list.
|
||||||
|
*/
|
||||||
|
MobileSpaceMembers,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Space accessed via interacting with the space menu.
|
||||||
|
*/
|
||||||
|
MobileSpaceMenu,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Space accessed via interacting with a space settings menu item.
|
||||||
|
*/
|
||||||
|
MobileSpaceSettings,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via a push/desktop notification.
|
||||||
|
*/
|
||||||
|
Notification,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via the predecessor link at the top of the upgraded
|
||||||
|
* room.
|
||||||
|
*/
|
||||||
|
Predecessor,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via the public rooms directory.
|
||||||
|
*/
|
||||||
|
RoomDirectory,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via the room list.
|
||||||
|
*/
|
||||||
|
RoomList,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via a shortcut.
|
||||||
|
*/
|
||||||
|
Shortcut,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via a slash command in Element Web/Desktop like /goto.
|
||||||
|
*/
|
||||||
|
SlashCommand,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via the space hierarchy view.
|
||||||
|
*/
|
||||||
|
SpaceHierarchy,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via a timeline pill or link in another room.
|
||||||
|
*/
|
||||||
|
Timeline,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via a tombstone at the bottom of a predecessor room.
|
||||||
|
*/
|
||||||
|
Tombstone,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room switched due to user interacting with incoming verification
|
||||||
|
* request.
|
||||||
|
*/
|
||||||
|
VerificationRequest,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room switched due to accepting a call in a different room in Element
|
||||||
|
* Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebAcceptCall,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room switched due to making a call via the dial pad in Element
|
||||||
|
* Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebDialPad,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via interacting with the floating call or Jitsi PIP in
|
||||||
|
* Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebFloatingCallWindow,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via the shortcut in Element Web/Desktop's forward
|
||||||
|
* modal.
|
||||||
|
*/
|
||||||
|
WebForwardShortcut,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via the Element Web/Desktop horizontal breadcrumbs at
|
||||||
|
* the top of the room list.
|
||||||
|
*/
|
||||||
|
WebHorizontalBreadcrumbs,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via an Element Web/Desktop keyboard shortcut like go to
|
||||||
|
* next room with unread messages.
|
||||||
|
*/
|
||||||
|
WebKeyboardShortcut,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via Element Web/Desktop's notification panel.
|
||||||
|
*/
|
||||||
|
WebNotificationPanel,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via the predecessor link in Settings > Advanced in
|
||||||
|
* Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebPredecessorSettings,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via clicking on a notifications badge on a room list
|
||||||
|
* sublist in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebRoomListNotificationBadge,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room switched due to the user changing space in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebSpaceContextSwitch,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via clicking on the notifications badge on the
|
||||||
|
* currently selected space in Element Web/Desktop.
|
||||||
|
*/
|
||||||
|
WebSpacePanelNotificationBadge,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via Element Web/Desktop's Unified Search modal.
|
||||||
|
*/
|
||||||
|
WebUnifiedSearch,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room accessed via the Element Web/Desktop vertical breadcrumb hover
|
||||||
|
* menu.
|
||||||
|
*/
|
||||||
|
WebVerticalBreadcrumbs,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Room switched due to widget interaction.
|
||||||
|
*/
|
||||||
|
Widget,
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class ActiveSpace {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Active space is Home.
|
||||||
|
*/
|
||||||
|
Home,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Active space is a meta space.
|
||||||
|
*/
|
||||||
|
Meta,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Active space is a private space.
|
||||||
|
*/
|
||||||
|
Private,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Active space is a public space.
|
||||||
|
*/
|
||||||
|
Public,
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getName() = "ViewRoom"
|
||||||
|
|
||||||
|
override fun getProperties(): Map<String, Any>? {
|
||||||
|
return mutableMapOf<String, Any>().apply {
|
||||||
|
activeSpace?.let { put("activeSpace", it.name) }
|
||||||
|
isDM?.let { put("isDM", it) }
|
||||||
|
isSpace?.let { put("isSpace", it) }
|
||||||
|
trigger?.let { put("trigger", it.name) }
|
||||||
|
viaKeyboard?.let { put("viaKeyboard", it) }
|
||||||
|
}.takeIf { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
}
|
||||||
34
services/analytics/noop/build.gradle.kts
Normal file
34
services/analytics/noop/build.gradle.kts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("io.element.android-library")
|
||||||
|
alias(libs.plugins.anvil)
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "io.element.android.services.analytics.impl"
|
||||||
|
}
|
||||||
|
|
||||||
|
anvil {
|
||||||
|
generateDaggerFactories.set(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(libs.dagger)
|
||||||
|
implementation(projects.libraries.di)
|
||||||
|
api(projects.services.analytics.api)
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.services.analytics.noop
|
||||||
|
|
||||||
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
|
import io.element.android.services.analytics.api.AnalyticsTracker
|
||||||
|
import io.element.android.services.analytics.api.VectorAnalyticsEvent
|
||||||
|
import io.element.android.services.analytics.api.VectorAnalyticsScreen
|
||||||
|
import io.element.android.services.analytics.api.plan.UserProperties
|
||||||
|
import io.element.android.libraries.di.AppScope
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ContributesBinding(AppScope::class)
|
||||||
|
class NoopAnalyticsTracker @Inject constructor() : AnalyticsTracker {
|
||||||
|
|
||||||
|
override fun capture(event: VectorAnalyticsEvent) = Unit
|
||||||
|
|
||||||
|
override fun screen(screen: VectorAnalyticsScreen) = Unit
|
||||||
|
|
||||||
|
override fun updateUserProperties(userProperties: UserProperties) = Unit
|
||||||
|
}
|
||||||
27
services/toolbox/api/build.gradle.kts
Normal file
27
services/toolbox/api/build.gradle.kts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("io.element.android-library")
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "io.element.android.services.toolbox.api"
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(libs.androidx.corektx)
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.services.toolbox.api.appname
|
||||||
|
|
||||||
|
interface AppNameProvider {
|
||||||
|
fun getAppName(): String
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.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
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.services.toolbox.api.systemclock
|
||||||
|
|
||||||
|
interface SystemClock {
|
||||||
|
fun epochMillis(): Long
|
||||||
|
}
|
||||||
36
services/toolbox/impl/build.gradle.kts
Normal file
36
services/toolbox/impl/build.gradle.kts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("io.element.android-library")
|
||||||
|
alias(libs.plugins.anvil)
|
||||||
|
}
|
||||||
|
|
||||||
|
android {
|
||||||
|
namespace = "io.element.android.services.toolbox.impl"
|
||||||
|
}
|
||||||
|
|
||||||
|
anvil {
|
||||||
|
generateDaggerFactories.set(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(libs.dagger)
|
||||||
|
implementation(projects.libraries.androidutils)
|
||||||
|
implementation(projects.libraries.di)
|
||||||
|
api(projects.services.toolbox.api)
|
||||||
|
implementation(libs.androidx.corektx)
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.services.toolbox.impl.appname
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
|
import io.element.android.libraries.androidutils.system.getApplicationLabel
|
||||||
|
import io.element.android.libraries.di.AppScope
|
||||||
|
import io.element.android.libraries.di.ApplicationContext
|
||||||
|
import io.element.android.services.toolbox.api.appname.AppNameProvider
|
||||||
|
import timber.log.Timber
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ContributesBinding(AppScope::class)
|
||||||
|
class DefaultAppNameProvider @Inject constructor(@ApplicationContext private val context: Context) :
|
||||||
|
AppNameProvider {
|
||||||
|
|
||||||
|
override fun getAppName(): String {
|
||||||
|
return try {
|
||||||
|
val appPackageName = context.packageName
|
||||||
|
var appName = context.getApplicationLabel(appPackageName)
|
||||||
|
|
||||||
|
// Use appPackageName instead of appName if appName contains any non-ASCII character
|
||||||
|
if (!appName.matches("\\A\\p{ASCII}*\\z".toRegex())) {
|
||||||
|
appName = appPackageName
|
||||||
|
}
|
||||||
|
appName
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Timber.e(e, "## AppNameProvider() : failed")
|
||||||
|
"ElementAndroid"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.services.toolbox.impl.strings
|
||||||
|
|
||||||
|
import android.content.res.Resources
|
||||||
|
import androidx.annotation.PluralsRes
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
|
import io.element.android.libraries.di.AppScope
|
||||||
|
import io.element.android.services.toolbox.api.strings.StringProvider
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ContributesBinding(AppScope::class)
|
||||||
|
class AndroidStringProvider @Inject constructor(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)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2023 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.services.toolbox.impl.systemclock
|
||||||
|
|
||||||
|
import com.squareup.anvil.annotations.ContributesBinding
|
||||||
|
import io.element.android.libraries.di.AppScope
|
||||||
|
import io.element.android.services.toolbox.api.systemclock.SystemClock
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ContributesBinding(AppScope::class)
|
||||||
|
class DefaultSystemClock @Inject constructor() : 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -66,8 +66,12 @@ include(":libraries:session-storage:api")
|
|||||||
include(":libraries:session-storage:impl")
|
include(":libraries:session-storage:impl")
|
||||||
include(":libraries:session-storage:impl-memory")
|
include(":libraries:session-storage:impl-memory")
|
||||||
|
|
||||||
|
include(":services:analytics:api")
|
||||||
|
include(":services:analytics:noop")
|
||||||
include(":services:appnavstate:api")
|
include(":services:appnavstate:api")
|
||||||
include(":services:appnavstate:impl")
|
include(":services:appnavstate:impl")
|
||||||
|
include(":services:toolbox:api")
|
||||||
|
include(":services:toolbox:impl")
|
||||||
|
|
||||||
include(":features:onboarding:api")
|
include(":features:onboarding:api")
|
||||||
include(":features:onboarding:impl")
|
include(":features:onboarding:impl")
|
||||||
|
|||||||
Reference in New Issue
Block a user