Merge branch 'develop' into feature/fga/space_settings_iteration
This commit is contained in:
commit
ce079e84f5
600 changed files with 3591 additions and 2388 deletions
|
|
@ -60,7 +60,7 @@ fun Activity.openUrlInChromeCustomTab(
|
|||
})
|
||||
}
|
||||
.launchUrl(this, url.toUri())
|
||||
} catch (activityNotFoundException: ActivityNotFoundException) {
|
||||
} catch (_: ActivityNotFoundException) {
|
||||
openUrlInExternalApp(url)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ fun String.hash() = try {
|
|||
digest.digest()
|
||||
.joinToString("") { String.format(Locale.ROOT, "%02X", it) }
|
||||
.lowercase(Locale.ROOT)
|
||||
} catch (exc: Exception) {
|
||||
} catch (_: Exception) {
|
||||
// Should not happen, but just in case
|
||||
hashCode().toString()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ fun Context.getApplicationLabel(packageName: String): String {
|
|||
return try {
|
||||
val ai = packageManager.getApplicationInfoCompat(packageName, 0)
|
||||
packageManager.getApplicationLabel(ai).toString()
|
||||
} catch (e: PackageManager.NameNotFoundException) {
|
||||
} catch (_: PackageManager.NameNotFoundException) {
|
||||
packageName
|
||||
}
|
||||
}
|
||||
|
|
@ -96,7 +96,7 @@ fun Context.startNotificationSettingsIntent(
|
|||
} else {
|
||||
startActivity(intent)
|
||||
}
|
||||
} catch (activityNotFoundException: ActivityNotFoundException) {
|
||||
} catch (_: ActivityNotFoundException) {
|
||||
toast(noActivityFoundMessage)
|
||||
}
|
||||
}
|
||||
|
|
@ -112,7 +112,7 @@ fun Context.openAppSettingsPage(
|
|||
data = Uri.fromParts("package", packageName, null)
|
||||
}
|
||||
)
|
||||
} catch (activityNotFoundException: ActivityNotFoundException) {
|
||||
} catch (_: ActivityNotFoundException) {
|
||||
toast(noActivityFoundMessage)
|
||||
}
|
||||
}
|
||||
|
|
@ -126,7 +126,7 @@ fun Context.startInstallFromSourceIntent(
|
|||
.setData("package:$packageName".toUri())
|
||||
try {
|
||||
activityResultLauncher.launch(intent)
|
||||
} catch (activityNotFoundException: ActivityNotFoundException) {
|
||||
} catch (_: ActivityNotFoundException) {
|
||||
toast(noActivityFoundMessage)
|
||||
}
|
||||
}
|
||||
|
|
@ -157,7 +157,7 @@ fun Context.startSharePlainTextIntent(
|
|||
} else {
|
||||
startActivity(intent)
|
||||
}
|
||||
} catch (activityNotFoundException: ActivityNotFoundException) {
|
||||
} catch (_: ActivityNotFoundException) {
|
||||
toast(noActivityFoundMessage)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.androidutils.text
|
||||
|
||||
import java.net.URLDecoder
|
||||
import java.net.URLEncoder
|
||||
import java.nio.charset.Charset
|
||||
|
||||
fun String.urlEncoded(charset: Charset = Charsets.UTF_8): String = URLEncoder.encode(this, charset.name())
|
||||
fun String.urlDecoded(charset: Charset = Charsets.UTF_8): String = URLDecoder.decode(this, charset.name())
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4c0f668bcd8d511bc80daa1320bdcc1fe6a8f82cd53d91dbab9ffd0d09d72934
|
||||
size 210897
|
||||
oid sha256:fc758c149db501d0ac5eb235cca1d63b67230aae40356e7ccca4c9d481a9ce17
|
||||
size 216981
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:85eb26db4406a921c45f143c8ccb59214b2b70cb19359fe9e7eeeecfb733ca74
|
||||
size 222592
|
||||
oid sha256:db230bfe3d51527959d2a4f7c64a8cc79209dcfb752f077f84c0f5058d94f0bd
|
||||
size 228829
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9acd4fdec8deddbf723184ce5f373ed54e64a68d5b572419059e3feab3a508be
|
||||
size 223915
|
||||
oid sha256:4c6cd3ad1978c6f4e07d62b1edd08c5f32b3c498934d25af43932c50ef309fe0
|
||||
size 230519
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:578e9b5a38791e2686a7b9ba5c461eb1d1fb29dfbe950bf46c113ad75ceac175
|
||||
size 327758
|
||||
oid sha256:c846cd10b83361c368bdbb31ed6220cc22693c3cbf52791fb369841af1e9ea48
|
||||
size 327701
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:4cab40fc0506c8f2a2efafb1199e85f1da3ebacb49b176e9105e3f95175f85ee
|
||||
size 325565
|
||||
oid sha256:05b35fedbd53dec2cc5c4c211a8db1a56055963de69425ddae2cab5aff7e3e75
|
||||
size 325750
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:174f9d4ee70a29c0c8c2a01a15daeb14281530678ff7d7fb19a208bfd789533a
|
||||
size 309210
|
||||
oid sha256:8d98e64eda5d6333067ccc599e99636f618331397207bb7534595e2756edb75e
|
||||
size 309312
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7598b98462c015f2bf74b3ea3ad95fc0220b2efb9bb81ac56025cf6a158e3f8a
|
||||
size 308976
|
||||
oid sha256:5ccbf1234065b182939f001eb65eca0a62adae41a2d91ef0307d27b059407178
|
||||
size 309084
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:9f2584ffd8e3a4746937cdc3e0baf04a89839061f15d00342e6150c21bf13228
|
||||
size 83228
|
||||
oid sha256:1d4f46c82f1504a983885a7d177900cd6d6f7729dce6851520cd7e471870ad2d
|
||||
size 84955
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:fb1854bf504fcab7752c4d51f5fc6cae65511581fb64a1adcdcf6f912d4aa15a
|
||||
size 89148
|
||||
oid sha256:e2c1a78a88fad99c1fd9bc29d802ee8c2bdefec89626cd700c73f4909738aeb5
|
||||
size 91022
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1,12 +1,10 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* !!! WARNING !!!
|
||||
*
|
||||
|
|
@ -14,8 +12,6 @@
|
|||
* DO NOT EDIT MANUALLY.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@file:Suppress("all")
|
||||
package io.element.android.compound.tokens.generated
|
||||
|
||||
|
|
@ -185,6 +181,9 @@ object CompoundIcons {
|
|||
@Composable fun ErrorSolid(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_error_solid)
|
||||
}
|
||||
@Composable fun ExitFullScreen(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_exit_full_screen)
|
||||
}
|
||||
@Composable fun Expand(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_expand)
|
||||
}
|
||||
|
|
@ -218,6 +217,9 @@ object CompoundIcons {
|
|||
@Composable fun Forward(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_forward)
|
||||
}
|
||||
@Composable fun FullScreen(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_full_screen)
|
||||
}
|
||||
@Composable fun Grid(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_grid)
|
||||
}
|
||||
|
|
@ -296,6 +298,9 @@ object CompoundIcons {
|
|||
@Composable fun Leave(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_leave)
|
||||
}
|
||||
@Composable fun LeftPanelClose(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_left_panel_close)
|
||||
}
|
||||
@Composable fun Link(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_link)
|
||||
}
|
||||
|
|
@ -503,6 +508,12 @@ object CompoundIcons {
|
|||
@Composable fun SignOut(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_sign_out)
|
||||
}
|
||||
@Composable fun Space(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_space)
|
||||
}
|
||||
@Composable fun SpaceSolid(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_space_solid)
|
||||
}
|
||||
@Composable fun Spinner(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_spinner)
|
||||
}
|
||||
|
|
@ -620,12 +631,6 @@ object CompoundIcons {
|
|||
@Composable fun Windows(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_windows)
|
||||
}
|
||||
@Composable fun Workspace(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_workspace)
|
||||
}
|
||||
@Composable fun WorkspaceSolid(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_workspace_solid)
|
||||
}
|
||||
|
||||
val all @Composable get() = persistentListOf<ImageVector>(
|
||||
Admin(),
|
||||
|
|
@ -681,6 +686,7 @@ object CompoundIcons {
|
|||
EndCall(),
|
||||
Error(),
|
||||
ErrorSolid(),
|
||||
ExitFullScreen(),
|
||||
Expand(),
|
||||
Explore(),
|
||||
ExportArchive(),
|
||||
|
|
@ -692,6 +698,7 @@ object CompoundIcons {
|
|||
Files(),
|
||||
Filter(),
|
||||
Forward(),
|
||||
FullScreen(),
|
||||
Grid(),
|
||||
Group(),
|
||||
Guest(),
|
||||
|
|
@ -718,6 +725,7 @@ object CompoundIcons {
|
|||
Keyboard(),
|
||||
Labs(),
|
||||
Leave(),
|
||||
LeftPanelClose(),
|
||||
Link(),
|
||||
Linux(),
|
||||
ListBulleted(),
|
||||
|
|
@ -787,6 +795,8 @@ object CompoundIcons {
|
|||
Shield(),
|
||||
Sidebar(),
|
||||
SignOut(),
|
||||
Space(),
|
||||
SpaceSolid(),
|
||||
Spinner(),
|
||||
Spotlight(),
|
||||
SpotlightView(),
|
||||
|
|
@ -826,8 +836,6 @@ object CompoundIcons {
|
|||
Warning(),
|
||||
WebBrowser(),
|
||||
Windows(),
|
||||
Workspace(),
|
||||
WorkspaceSolid(),
|
||||
)
|
||||
|
||||
val allResIds get() = persistentListOf(
|
||||
|
|
@ -884,6 +892,7 @@ object CompoundIcons {
|
|||
R.drawable.ic_compound_end_call,
|
||||
R.drawable.ic_compound_error,
|
||||
R.drawable.ic_compound_error_solid,
|
||||
R.drawable.ic_compound_exit_full_screen,
|
||||
R.drawable.ic_compound_expand,
|
||||
R.drawable.ic_compound_explore,
|
||||
R.drawable.ic_compound_export_archive,
|
||||
|
|
@ -895,6 +904,7 @@ object CompoundIcons {
|
|||
R.drawable.ic_compound_files,
|
||||
R.drawable.ic_compound_filter,
|
||||
R.drawable.ic_compound_forward,
|
||||
R.drawable.ic_compound_full_screen,
|
||||
R.drawable.ic_compound_grid,
|
||||
R.drawable.ic_compound_group,
|
||||
R.drawable.ic_compound_guest,
|
||||
|
|
@ -921,6 +931,7 @@ object CompoundIcons {
|
|||
R.drawable.ic_compound_keyboard,
|
||||
R.drawable.ic_compound_labs,
|
||||
R.drawable.ic_compound_leave,
|
||||
R.drawable.ic_compound_left_panel_close,
|
||||
R.drawable.ic_compound_link,
|
||||
R.drawable.ic_compound_linux,
|
||||
R.drawable.ic_compound_list_bulleted,
|
||||
|
|
@ -990,6 +1001,8 @@ object CompoundIcons {
|
|||
R.drawable.ic_compound_shield,
|
||||
R.drawable.ic_compound_sidebar,
|
||||
R.drawable.ic_compound_sign_out,
|
||||
R.drawable.ic_compound_space,
|
||||
R.drawable.ic_compound_space_solid,
|
||||
R.drawable.ic_compound_spinner,
|
||||
R.drawable.ic_compound_spotlight,
|
||||
R.drawable.ic_compound_spotlight_view,
|
||||
|
|
@ -1029,7 +1042,5 @@ object CompoundIcons {
|
|||
R.drawable.ic_compound_warning,
|
||||
R.drawable.ic_compound_web_browser,
|
||||
R.drawable.ic_compound_windows,
|
||||
R.drawable.ic_compound_workspace,
|
||||
R.drawable.ic_compound_workspace_solid,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,19 +1,10 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
|
||||
@file:Suppress("all")
|
||||
package io.element.android.compound.tokens.generated
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
|
||||
/**
|
||||
* !!! WARNING !!!
|
||||
*
|
||||
|
|
@ -21,12 +12,14 @@ import androidx.compose.ui.graphics.Color
|
|||
* DO NOT EDIT MANUALLY.
|
||||
*/
|
||||
|
||||
@file:Suppress("all")
|
||||
package io.element.android.compound.tokens.generated
|
||||
|
||||
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
||||
/**
|
||||
* This class holds all the semantic tokens of the Compound theme.
|
||||
*/
|
||||
* This class holds all the semantic tokens of the Compound theme.
|
||||
*/
|
||||
data class SemanticColors(
|
||||
/** Background colour for accent or brand actions. State: Hover */
|
||||
val bgAccentHovered: Color,
|
||||
|
|
@ -50,17 +43,21 @@ data class SemanticColors(
|
|||
val bgActionSecondaryPressed: Color,
|
||||
/** Background colour for secondary actions. State: Rest. */
|
||||
val bgActionSecondaryRest: Color,
|
||||
/** Background colour for tertiary actions. State: Hover */
|
||||
val bgActionTertiaryHovered: Color,
|
||||
/** Background colour for tertiary actions. State: Rest */
|
||||
val bgActionTertiaryRest: Color,
|
||||
/** Background colour for tertiary actions. State: Selected */
|
||||
val bgActionTertiarySelected: Color,
|
||||
/** Badge accent background colour */
|
||||
val bgBadgeAccent: Color,
|
||||
/** Badge default background colour */
|
||||
val bgBadgeDefault: Color,
|
||||
/** Badge info background colour */
|
||||
val bgBadgeInfo: Color,
|
||||
/** Default global background for the user interface.
|
||||
Elevation: Default (Level 0) */
|
||||
/** Default global background for the user interface. Elevation: Default (Level 0) */
|
||||
val bgCanvasDefault: Color,
|
||||
/** Default global background for the user interface.
|
||||
Elevation: Level 1. */
|
||||
/** Default global background for the user interface. Elevation: Level 1. */
|
||||
val bgCanvasDefaultLevel1: Color,
|
||||
/** Default background for disabled elements. There's no minimum contrast requirement. */
|
||||
val bgCanvasDisabled: Color,
|
||||
|
|
@ -86,14 +83,11 @@ Elevation: Level 1. */
|
|||
val bgDecorative6: Color,
|
||||
/** Subtle background colour for informational elements. State: Rest. */
|
||||
val bgInfoSubtle: Color,
|
||||
/** Medium contrast surfaces.
|
||||
Elevation: Default (Level 2). */
|
||||
/** Medium contrast surfaces. Elevation: Default (Level 2). */
|
||||
val bgSubtlePrimary: Color,
|
||||
/** Low contrast surfaces.
|
||||
Elevation: Default (Level 1). */
|
||||
/** Low contrast surfaces. Elevation: Default (Level 1). */
|
||||
val bgSubtleSecondary: Color,
|
||||
/** Lower contrast surfaces.
|
||||
Elevation: Level 0. */
|
||||
/** Lower contrast surfaces. Elevation: Level 0. */
|
||||
val bgSubtleSecondaryLevel0: Color,
|
||||
/** Subtle background colour for success state elements. State: Rest. */
|
||||
val bgSuccessSubtle: Color,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
|
|
@ -13,8 +12,6 @@
|
|||
* DO NOT EDIT MANUALLY.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@file:Suppress("all")
|
||||
package io.element.android.compound.tokens.generated
|
||||
|
||||
|
|
@ -37,9 +34,12 @@ val compoundColorsDark = SemanticColors(
|
|||
bgActionSecondaryHovered = DarkColorTokens.colorAlphaGray200,
|
||||
bgActionSecondaryPressed = DarkColorTokens.colorAlphaGray300,
|
||||
bgActionSecondaryRest = DarkColorTokens.colorThemeBg,
|
||||
bgBadgeAccent = DarkColorTokens.colorAlphaGreen300,
|
||||
bgBadgeDefault = DarkColorTokens.colorAlphaGray300,
|
||||
bgBadgeInfo = DarkColorTokens.colorAlphaBlue300,
|
||||
bgActionTertiaryHovered = DarkColorTokens.colorGray300,
|
||||
bgActionTertiaryRest = DarkColorTokens.colorThemeBg,
|
||||
bgActionTertiarySelected = DarkColorTokens.colorGray400,
|
||||
bgBadgeAccent = DarkColorTokens.colorAlphaGreen500,
|
||||
bgBadgeDefault = DarkColorTokens.colorAlphaGray500,
|
||||
bgBadgeInfo = DarkColorTokens.colorAlphaBlue500,
|
||||
bgCanvasDefault = DarkColorTokens.colorThemeBg,
|
||||
bgCanvasDefaultLevel1 = DarkColorTokens.colorGray300,
|
||||
bgCanvasDisabled = DarkColorTokens.colorGray200,
|
||||
|
|
@ -89,7 +89,7 @@ val compoundColorsDark = SemanticColors(
|
|||
iconAccentTertiary = DarkColorTokens.colorGreen800,
|
||||
iconCriticalPrimary = DarkColorTokens.colorRed900,
|
||||
iconDisabled = DarkColorTokens.colorGray700,
|
||||
iconInfoPrimary = DarkColorTokens.colorBlue900,
|
||||
iconInfoPrimary = DarkColorTokens.colorBlue1100,
|
||||
iconOnSolidPrimary = DarkColorTokens.colorThemeBg,
|
||||
iconPrimary = DarkColorTokens.colorGray1400,
|
||||
iconPrimaryAlpha = DarkColorTokens.colorAlphaGray1400,
|
||||
|
|
@ -112,8 +112,8 @@ val compoundColorsDark = SemanticColors(
|
|||
textDecorative5 = DarkColorTokens.colorPink1100,
|
||||
textDecorative6 = DarkColorTokens.colorOrange1100,
|
||||
textDisabled = DarkColorTokens.colorGray800,
|
||||
textInfoPrimary = DarkColorTokens.colorBlue900,
|
||||
textLinkExternal = DarkColorTokens.colorBlue900,
|
||||
textInfoPrimary = DarkColorTokens.colorBlue1100,
|
||||
textLinkExternal = DarkColorTokens.colorBlue1100,
|
||||
textOnSolidPrimary = DarkColorTokens.colorThemeBg,
|
||||
textPrimary = DarkColorTokens.colorGray1400,
|
||||
textSecondary = DarkColorTokens.colorGray900,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
|
|
@ -13,8 +12,6 @@
|
|||
* DO NOT EDIT MANUALLY.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@file:Suppress("all")
|
||||
package io.element.android.compound.tokens.generated
|
||||
|
||||
|
|
@ -37,9 +34,12 @@ val compoundColorsHcDark = SemanticColors(
|
|||
bgActionSecondaryHovered = DarkHcColorTokens.colorAlphaGray200,
|
||||
bgActionSecondaryPressed = DarkHcColorTokens.colorAlphaGray300,
|
||||
bgActionSecondaryRest = DarkHcColorTokens.colorThemeBg,
|
||||
bgBadgeAccent = DarkHcColorTokens.colorAlphaGreen300,
|
||||
bgBadgeDefault = DarkHcColorTokens.colorAlphaGray300,
|
||||
bgBadgeInfo = DarkHcColorTokens.colorAlphaBlue300,
|
||||
bgActionTertiaryHovered = DarkHcColorTokens.colorGray300,
|
||||
bgActionTertiaryRest = DarkHcColorTokens.colorThemeBg,
|
||||
bgActionTertiarySelected = DarkHcColorTokens.colorGray400,
|
||||
bgBadgeAccent = DarkHcColorTokens.colorAlphaGreen500,
|
||||
bgBadgeDefault = DarkHcColorTokens.colorAlphaGray500,
|
||||
bgBadgeInfo = DarkHcColorTokens.colorAlphaBlue500,
|
||||
bgCanvasDefault = DarkHcColorTokens.colorThemeBg,
|
||||
bgCanvasDefaultLevel1 = DarkHcColorTokens.colorGray300,
|
||||
bgCanvasDisabled = DarkHcColorTokens.colorGray200,
|
||||
|
|
@ -89,7 +89,7 @@ val compoundColorsHcDark = SemanticColors(
|
|||
iconAccentTertiary = DarkHcColorTokens.colorGreen800,
|
||||
iconCriticalPrimary = DarkHcColorTokens.colorRed900,
|
||||
iconDisabled = DarkHcColorTokens.colorGray700,
|
||||
iconInfoPrimary = DarkHcColorTokens.colorBlue900,
|
||||
iconInfoPrimary = DarkHcColorTokens.colorBlue1100,
|
||||
iconOnSolidPrimary = DarkHcColorTokens.colorThemeBg,
|
||||
iconPrimary = DarkHcColorTokens.colorGray1400,
|
||||
iconPrimaryAlpha = DarkHcColorTokens.colorAlphaGray1400,
|
||||
|
|
@ -112,8 +112,8 @@ val compoundColorsHcDark = SemanticColors(
|
|||
textDecorative5 = DarkHcColorTokens.colorPink1100,
|
||||
textDecorative6 = DarkHcColorTokens.colorOrange1100,
|
||||
textDisabled = DarkHcColorTokens.colorGray800,
|
||||
textInfoPrimary = DarkHcColorTokens.colorBlue900,
|
||||
textLinkExternal = DarkHcColorTokens.colorBlue900,
|
||||
textInfoPrimary = DarkHcColorTokens.colorBlue1100,
|
||||
textLinkExternal = DarkHcColorTokens.colorBlue1100,
|
||||
textOnSolidPrimary = DarkHcColorTokens.colorThemeBg,
|
||||
textPrimary = DarkHcColorTokens.colorGray1400,
|
||||
textSecondary = DarkHcColorTokens.colorGray900,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
|
|
@ -13,8 +12,6 @@
|
|||
* DO NOT EDIT MANUALLY.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@file:Suppress("all")
|
||||
package io.element.android.compound.tokens.generated
|
||||
|
||||
|
|
@ -37,9 +34,12 @@ val compoundColorsLight = SemanticColors(
|
|||
bgActionSecondaryHovered = LightColorTokens.colorAlphaGray200,
|
||||
bgActionSecondaryPressed = LightColorTokens.colorAlphaGray300,
|
||||
bgActionSecondaryRest = LightColorTokens.colorThemeBg,
|
||||
bgBadgeAccent = LightColorTokens.colorAlphaGreen300,
|
||||
bgBadgeDefault = LightColorTokens.colorAlphaGray300,
|
||||
bgBadgeInfo = LightColorTokens.colorAlphaBlue300,
|
||||
bgActionTertiaryHovered = LightColorTokens.colorGray300,
|
||||
bgActionTertiaryRest = LightColorTokens.colorThemeBg,
|
||||
bgActionTertiarySelected = LightColorTokens.colorGray400,
|
||||
bgBadgeAccent = LightColorTokens.colorAlphaGreen400,
|
||||
bgBadgeDefault = LightColorTokens.colorAlphaGray400,
|
||||
bgBadgeInfo = LightColorTokens.colorAlphaBlue400,
|
||||
bgCanvasDefault = LightColorTokens.colorThemeBg,
|
||||
bgCanvasDefaultLevel1 = LightColorTokens.colorThemeBg,
|
||||
bgCanvasDisabled = LightColorTokens.colorGray200,
|
||||
|
|
@ -89,7 +89,7 @@ val compoundColorsLight = SemanticColors(
|
|||
iconAccentTertiary = LightColorTokens.colorGreen800,
|
||||
iconCriticalPrimary = LightColorTokens.colorRed900,
|
||||
iconDisabled = LightColorTokens.colorGray700,
|
||||
iconInfoPrimary = LightColorTokens.colorBlue900,
|
||||
iconInfoPrimary = LightColorTokens.colorBlue1100,
|
||||
iconOnSolidPrimary = LightColorTokens.colorThemeBg,
|
||||
iconPrimary = LightColorTokens.colorGray1400,
|
||||
iconPrimaryAlpha = LightColorTokens.colorAlphaGray1400,
|
||||
|
|
@ -112,8 +112,8 @@ val compoundColorsLight = SemanticColors(
|
|||
textDecorative5 = LightColorTokens.colorPink1100,
|
||||
textDecorative6 = LightColorTokens.colorOrange1100,
|
||||
textDisabled = LightColorTokens.colorGray800,
|
||||
textInfoPrimary = LightColorTokens.colorBlue900,
|
||||
textLinkExternal = LightColorTokens.colorBlue900,
|
||||
textInfoPrimary = LightColorTokens.colorBlue1100,
|
||||
textLinkExternal = LightColorTokens.colorBlue1100,
|
||||
textOnSolidPrimary = LightColorTokens.colorThemeBg,
|
||||
textPrimary = LightColorTokens.colorGray1400,
|
||||
textSecondary = LightColorTokens.colorGray900,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
|
|
@ -13,8 +12,6 @@
|
|||
* DO NOT EDIT MANUALLY.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@file:Suppress("all")
|
||||
package io.element.android.compound.tokens.generated
|
||||
|
||||
|
|
@ -37,9 +34,12 @@ val compoundColorsHcLight = SemanticColors(
|
|||
bgActionSecondaryHovered = LightHcColorTokens.colorAlphaGray200,
|
||||
bgActionSecondaryPressed = LightHcColorTokens.colorAlphaGray300,
|
||||
bgActionSecondaryRest = LightHcColorTokens.colorThemeBg,
|
||||
bgBadgeAccent = LightHcColorTokens.colorAlphaGreen300,
|
||||
bgBadgeDefault = LightHcColorTokens.colorAlphaGray300,
|
||||
bgBadgeInfo = LightHcColorTokens.colorAlphaBlue300,
|
||||
bgActionTertiaryHovered = LightHcColorTokens.colorGray300,
|
||||
bgActionTertiaryRest = LightHcColorTokens.colorThemeBg,
|
||||
bgActionTertiarySelected = LightHcColorTokens.colorGray400,
|
||||
bgBadgeAccent = LightHcColorTokens.colorAlphaGreen400,
|
||||
bgBadgeDefault = LightHcColorTokens.colorAlphaGray400,
|
||||
bgBadgeInfo = LightHcColorTokens.colorAlphaBlue400,
|
||||
bgCanvasDefault = LightHcColorTokens.colorThemeBg,
|
||||
bgCanvasDefaultLevel1 = LightHcColorTokens.colorThemeBg,
|
||||
bgCanvasDisabled = LightHcColorTokens.colorGray200,
|
||||
|
|
@ -89,7 +89,7 @@ val compoundColorsHcLight = SemanticColors(
|
|||
iconAccentTertiary = LightHcColorTokens.colorGreen800,
|
||||
iconCriticalPrimary = LightHcColorTokens.colorRed900,
|
||||
iconDisabled = LightHcColorTokens.colorGray700,
|
||||
iconInfoPrimary = LightHcColorTokens.colorBlue900,
|
||||
iconInfoPrimary = LightHcColorTokens.colorBlue1100,
|
||||
iconOnSolidPrimary = LightHcColorTokens.colorThemeBg,
|
||||
iconPrimary = LightHcColorTokens.colorGray1400,
|
||||
iconPrimaryAlpha = LightHcColorTokens.colorAlphaGray1400,
|
||||
|
|
@ -112,8 +112,8 @@ val compoundColorsHcLight = SemanticColors(
|
|||
textDecorative5 = LightHcColorTokens.colorPink1100,
|
||||
textDecorative6 = LightHcColorTokens.colorOrange1100,
|
||||
textDisabled = LightHcColorTokens.colorGray800,
|
||||
textInfoPrimary = LightHcColorTokens.colorBlue900,
|
||||
textLinkExternal = LightHcColorTokens.colorBlue900,
|
||||
textInfoPrimary = LightHcColorTokens.colorBlue1100,
|
||||
textLinkExternal = LightHcColorTokens.colorBlue1100,
|
||||
textOnSolidPrimary = LightHcColorTokens.colorThemeBg,
|
||||
textPrimary = LightHcColorTokens.colorGray1400,
|
||||
textSecondary = LightHcColorTokens.colorGray900,
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* !!! WARNING !!!
|
||||
*
|
||||
|
|
@ -14,8 +12,6 @@
|
|||
* DO NOT EDIT MANUALLY.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@file:Suppress("all")
|
||||
package io.element.android.compound.tokens.generated
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
|
|
@ -13,8 +12,6 @@
|
|||
* DO NOT EDIT MANUALLY.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@file:Suppress("all")
|
||||
package io.element.android.compound.tokens.generated.internal
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
|
|
@ -13,8 +12,6 @@
|
|||
* DO NOT EDIT MANUALLY.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@file:Suppress("all")
|
||||
package io.element.android.compound.tokens.generated.internal
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
|
|
@ -13,8 +12,6 @@
|
|||
* DO NOT EDIT MANUALLY.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@file:Suppress("all")
|
||||
package io.element.android.compound.tokens.generated.internal
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
|
|
@ -13,8 +12,6 @@
|
|||
* DO NOT EDIT MANUALLY.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
@file:Suppress("all")
|
||||
package io.element.android.compound.tokens.generated.internal
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M10,20a1,1 0,1 1,-2 0v-4L4,16a1,1 0,1 1,0 -2h6zM20,14a1,1 0,1 1,0 2h-4v4a1,1 0,1 1,-2 0v-6zM9,3a1,1 0,0 1,1 1v6L4,10a1,1 0,0 1,0 -2h4L8,4a1,1 0,0 1,1 -1m6,0a1,1 0,0 1,1 1v4h4a1,1 0,1 1,0 2h-6L14,4a1,1 0,0 1,1 -1"
|
||||
android:fillColor="#FF000000"/>
|
||||
</vector>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M4,14a1,1 0,0 1,1 1v4h4a1,1 0,1 1,0 2L3,21v-6a1,1 0,0 1,1 -1m16,0a1,1 0,0 1,1 1v6h-6a1,1 0,1 1,0 -2h4v-4a1,1 0,0 1,1 -1M9,3a1,1 0,0 1,0 2L5,5v4a1,1 0,0 1,-2 0L3,3zM21,9a1,1 0,1 1,-2 0L19,5h-4a1,1 0,1 1,0 -2h6z"
|
||||
android:fillColor="#FF000000"/>
|
||||
</vector>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M16.5,14.8L16.5,9.2q0,-0.35 -0.3,-0.475t-0.55,0.125L13.2,11.3q-0.3,0.3 -0.3,0.7t0.3,0.7l2.45,2.45q0.25,0.25 0.55,0.125t0.3,-0.475M5,19q-0.824,0 -1.412,-0.587A1.93,1.93 0,0 1,3 17L3,7q0,-0.824 0.587,-1.412A1.93,1.93 0,0 1,5 5h14q0.824,0 1.413,0.588Q21,6.175 21,7v10q0,0.824 -0.587,1.413A1.93,1.93 0,0 1,19 19zM8,17L8,7L5,7v10zM10,17h9L19,7h-9z"
|
||||
android:fillColor="#FF000000"/>
|
||||
</vector>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M6,21q-1.65,0 -2.825,-1.175T2,17t1.175,-2.825T6,13t2.825,1.175T10,17t-1.175,2.825T6,21m12,0q-1.65,0 -2.825,-1.175T14,17t1.175,-2.825T18,13t2.825,1.175T22,17t-1.175,2.825T18,21M6,19q0.824,0 1.412,-0.587Q8,17.825 8,17t-0.588,-1.412A1.93,1.93 0,0 0,6 15q-0.824,0 -1.412,0.588A1.93,1.93 0,0 0,4 17q0,0.824 0.588,1.413Q5.175,19 6,19m12,0q0.824,0 1.413,-0.587Q20,17.825 20,17t-0.587,-1.412A1.93,1.93 0,0 0,18 15q-0.824,0 -1.413,0.588A1.93,1.93 0,0 0,16 17q0,0.824 0.587,1.413Q17.176,19 18,19m-6,-8q-1.65,0 -2.825,-1.175T8,7t1.175,-2.825T12,3t2.825,1.175T16,7t-1.175,2.825T12,11m0,-2q0.825,0 1.412,-0.588Q14,7.826 14,7q0,-0.824 -0.588,-1.412A1.93,1.93 0,0 0,12 5q-0.825,0 -1.412,0.588A1.93,1.93 0,0 0,10 7q0,0.824 0.588,1.412Q11.175,9 12,9"
|
||||
android:fillColor="#FF000000"/>
|
||||
</vector>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M3.175,19.825Q4.35,21 6,21t2.825,-1.175T10,17t-1.175,-2.825T6,13t-2.825,1.175T2,17t1.175,2.825m12,0Q16.35,21 18,21t2.825,-1.175T22,17t-1.175,-2.825T18,13t-2.825,1.175T14,17t1.175,2.825m-6,-10Q10.35,11 12,11t2.825,-1.175T16,7t-1.175,-2.825T12,3 9.175,4.175 8,7t1.175,2.825"
|
||||
android:fillColor="#FF000000"/>
|
||||
</vector>
|
||||
|
|
@ -4,10 +4,10 @@
|
|||
android:autoMirrored="true"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M7 10a0.97 0.97 0 0 1-0.71-0.29A0.97 0.97 0 0 1 6 9q0-0.42 0.29-0.71A0.97 0.97 0 0 1 7 8h10q0.42 0 0.71 0.29T18 9t-0.29 0.71A0.97 0.97 0 0 1 17 10z m0 4a0.97 0.97 0 0 1-0.71-0.29A0.97 0.97 0 0 1 6 13q0-0.42 0.29-0.71A0.97 0.97 0 0 1 7 12h6q0.42 0 0.71 0.29T14 13q0 0.42-0.29 0.71A0.97 0.97 0 0 1 13 14z"/>
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M3.7 21.3C3.09 21.91 2 21.47 2 20.58V5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H6zM6 17h14V5H4v13.17l0.59-0.58A2 2 0 0 1 6 17"/>
|
||||
<path
|
||||
android:pathData="M7,10a0.97,0.97 0,0 1,-0.713 -0.287A0.97,0.97 0,0 1,6 9q0,-0.424 0.287,-0.713A0.97,0.97 0,0 1,7 8h10q0.424,0 0.712,0.287Q18,8.576 18,9t-0.288,0.713A0.97,0.97 0,0 1,17 10zM7,14a0.97,0.97 0,0 1,-0.713 -0.287A0.97,0.97 0,0 1,6 13q0,-0.424 0.287,-0.713A0.97,0.97 0,0 1,7 12h6q0.424,0 0.713,0.287 0.287,0.288 0.287,0.713 0,0.424 -0.287,0.713A0.97,0.97 0,0 1,13 14z"
|
||||
android:fillColor="#FF000000"/>
|
||||
<path
|
||||
android:pathData="M3.707,21.293c-0.63,0.63 -1.707,0.184 -1.707,-0.707V5a2,2 0,0 1,2 -2h16a2,2 0,0 1,2 2v12a2,2 0,0 1,-2 2H6zM6,17h14V5H4v13.172l0.586,-0.586A2,2 0,0 1,6 17"
|
||||
android:fillColor="#FF000000"/>
|
||||
</vector>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
android:autoMirrored="true"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M4 3h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H6l-2.3 2.3C3.09 21.91 2 21.47 2 20.58V5a2 2 0 0 1 2-2m3 7h10q0.42 0 0.71-0.29A0.97 0.97 0 0 0 18 9a0.97 0.97 0 0 0-0.29-0.71A0.97 0.97 0 0 0 17 8H7a0.97 0.97 0 0 0-0.71 0.29A0.97 0.97 0 0 0 6 9q0 0.42 0.29 0.71T7 10m0 4h6q0.42 0 0.71-0.29A0.97 0.97 0 0 0 14 13a0.97 0.97 0 0 0-0.29-0.71A0.97 0.97 0 0 0 13 12H7a0.97 0.97 0 0 0-0.71 0.29A0.97 0.97 0 0 0 6 13q0 0.42 0.29 0.71T7 14"/>
|
||||
<path
|
||||
android:pathData="M4,3h16a2,2 0,0 1,2 2v12a2,2 0,0 1,-2 2H6l-2.293,2.293c-0.63,0.63 -1.707,0.184 -1.707,-0.707V5a2,2 0,0 1,2 -2m3,7h10q0.424,0 0.712,-0.287A0.97,0.97 0,0 0,18 9a0.97,0.97 0,0 0,-0.288 -0.713A0.97,0.97 0,0 0,17 8H7a0.97,0.97 0,0 0,-0.713 0.287A0.97,0.97 0,0 0,6 9q0,0.424 0.287,0.713Q6.576,10 7,10m0,4h6q0.424,0 0.713,-0.287A0.97,0.97 0,0 0,14 13a0.97,0.97 0,0 0,-0.287 -0.713A0.97,0.97 0,0 0,13 12H7a0.97,0.97 0,0 0,-0.713 0.287A0.97,0.97 0,0 0,6 13q0,0.424 0.287,0.713Q6.576,14 7,14"
|
||||
android:fillColor="#FF000000"/>
|
||||
</vector>
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M6,21q-1.65,0 -2.825,-1.175T2,17t1.175,-2.825T6,13t2.825,1.175T10,17t-1.175,2.825T6,21m12,0q-1.65,0 -2.825,-1.175T14,17t1.175,-2.825T18,13t2.825,1.175T22,17t-1.175,2.825T18,21M6,19q0.824,0 1.412,-0.587Q8,17.825 8,17t-0.588,-1.412A1.93,1.93 0,0 0,6 15q-0.824,0 -1.412,0.588A1.93,1.93 0,0 0,4 17q0,0.824 0.588,1.413Q5.175,19 6,19m12,0q0.824,0 1.413,-0.587Q20,17.825 20,17t-0.587,-1.412A1.93,1.93 0,0 0,18 15q-0.824,0 -1.413,0.588A1.93,1.93 0,0 0,16 17q0,0.824 0.587,1.413Q17.176,19 18,19m-6,-8q-1.65,0 -2.825,-1.175T8,7t1.175,-2.825T12,3t2.825,1.175T16,7t-1.175,2.825T12,11m0,-2q0.825,0 1.412,-0.588Q14,7.826 14,7q0,-0.824 -0.588,-1.412A1.93,1.93 0,0 0,12 5q-0.825,0 -1.412,0.588A1.93,1.93 0,0 0,10 7q0,0.824 0.588,1.412Q11.175,9 12,9"
|
||||
android:fillColor="#FF000000"/>
|
||||
</vector>
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M3.175,19.825Q4.35,21 6,21t2.825,-1.175T10,17t-1.175,-2.825T6,13t-2.825,1.175T2,17t1.175,2.825m12,0Q16.35,21 18,21t2.825,-1.175T22,17t-1.175,-2.825T18,13t-2.825,1.175T14,17t1.175,2.825m-6,-10Q10.35,11 12,11t2.825,-1.175T16,7t-1.175,-2.825T12,3 9.175,4.175 8,7t1.175,2.825"
|
||||
android:fillColor="#FF000000"/>
|
||||
</vector>
|
||||
|
|
@ -21,7 +21,7 @@ fun String.md5() = try {
|
|||
digest.digest()
|
||||
.joinToString("") { String.format(locale, "%02X", it) }
|
||||
.lowercase(locale)
|
||||
} catch (exc: Exception) {
|
||||
} catch (_: Exception) {
|
||||
// Should not happen, but just in case
|
||||
hashCode().toString()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ fun String.isValidUrl(): Boolean {
|
|||
return try {
|
||||
URI(this).toURL()
|
||||
true
|
||||
} catch (t: Throwable) {
|
||||
} catch (_: Throwable) {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ package io.element.android.libraries.deeplink.impl
|
|||
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.ContributesBinding
|
||||
import io.element.android.libraries.androidutils.text.urlEncoded
|
||||
import io.element.android.libraries.deeplink.api.DeepLinkCreator
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
|
|
@ -21,13 +22,13 @@ class DefaultDeepLinkCreator : DeepLinkCreator {
|
|||
override fun create(sessionId: SessionId, roomId: RoomId?, threadId: ThreadId?, eventId: EventId?): String {
|
||||
return buildString {
|
||||
append("$SCHEME://$HOST/")
|
||||
append(sessionId.value)
|
||||
append(sessionId.value.urlEncoded())
|
||||
append("/")
|
||||
append(roomId?.value.orEmpty())
|
||||
append(roomId?.value?.urlEncoded().orEmpty())
|
||||
append("/")
|
||||
append(threadId?.value.orEmpty())
|
||||
append(threadId?.value?.urlEncoded().orEmpty())
|
||||
append("/")
|
||||
append(eventId?.value.orEmpty())
|
||||
append(eventId?.value?.urlEncoded().orEmpty())
|
||||
}
|
||||
// Remove all possible trailing '/' characters:
|
||||
// No event id
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import android.content.Intent
|
|||
import android.net.Uri
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.ContributesBinding
|
||||
import io.element.android.libraries.androidutils.text.urlDecoded
|
||||
import io.element.android.libraries.deeplink.api.DeeplinkData
|
||||
import io.element.android.libraries.deeplink.api.DeeplinkParser
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
|
|
@ -31,7 +32,7 @@ class DefaultDeeplinkParser : DeeplinkParser {
|
|||
private fun Uri.toDeeplinkData(): DeeplinkData? {
|
||||
if (scheme != SCHEME) return null
|
||||
if (host != HOST) return null
|
||||
val pathBits = path.orEmpty().split("/").drop(1)
|
||||
val pathBits = encodedPath.orEmpty().split("/").drop(1).map { it.urlDecoded() }
|
||||
val sessionId = pathBits.elementAtOrNull(0)?.let(::SessionId) ?: return null
|
||||
|
||||
return when (val screenPathComponent = pathBits.elementAtOrNull(1)) {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,10 @@
|
|||
package io.element.android.libraries.deeplink.impl
|
||||
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.core.ThreadId
|
||||
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||
|
|
@ -19,15 +23,36 @@ class DefaultDeepLinkCreatorTest {
|
|||
@Test
|
||||
fun create() {
|
||||
val sut = DefaultDeepLinkCreator()
|
||||
assertThat(sut.create(A_SESSION_ID, null, null, null))
|
||||
.isEqualTo("elementx://open/@alice:server.org")
|
||||
assertThat(sut.create(A_SESSION_ID, A_ROOM_ID, null, null))
|
||||
.isEqualTo("elementx://open/@alice:server.org/!aRoomId:domain")
|
||||
assertThat(sut.create(A_SESSION_ID, A_ROOM_ID, A_THREAD_ID, null))
|
||||
.isEqualTo("elementx://open/@alice:server.org/!aRoomId:domain/\$aThreadId")
|
||||
assertThat(sut.create(A_SESSION_ID, A_ROOM_ID, A_THREAD_ID, AN_EVENT_ID))
|
||||
.isEqualTo("elementx://open/@alice:server.org/!aRoomId:domain/\$aThreadId/\$anEventId")
|
||||
assertThat(sut.create(A_SESSION_ID, A_ROOM_ID, null, AN_EVENT_ID))
|
||||
.isEqualTo("elementx://open/@alice:server.org/!aRoomId:domain//\$anEventId")
|
||||
val sessionId = A_SESSION_ID
|
||||
val roomId = A_ROOM_ID
|
||||
val threadId = A_THREAD_ID
|
||||
val eventId = AN_EVENT_ID
|
||||
assertThat(sut.create(sessionId, null, null, null))
|
||||
.isEqualTo("elementx://open/%40alice%3Aserver.org")
|
||||
assertThat(sut.create(sessionId, roomId, null, null))
|
||||
.isEqualTo("elementx://open/%40alice%3Aserver.org/%21aRoomId%3Adomain")
|
||||
assertThat(sut.create(sessionId, roomId, threadId, null))
|
||||
.isEqualTo("elementx://open/%40alice%3Aserver.org/%21aRoomId%3Adomain/%24aThreadId")
|
||||
assertThat(sut.create(sessionId, roomId, threadId, eventId))
|
||||
.isEqualTo("elementx://open/%40alice%3Aserver.org/%21aRoomId%3Adomain/%24aThreadId/%24anEventId")
|
||||
assertThat(sut.create(sessionId, roomId, null, eventId))
|
||||
.isEqualTo("elementx://open/%40alice%3Aserver.org/%21aRoomId%3Adomain//%24anEventId")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `create - with escaped invalid characters`() {
|
||||
val sut = DefaultDeepLinkCreator()
|
||||
val sessionId = SessionId("@a/:domain")
|
||||
val roomId = RoomId("!a/RoomId:domain")
|
||||
val threadId = ThreadId("\$a/ThreadId")
|
||||
val eventId = EventId("\$an/EventId")
|
||||
assertThat(sut.create(sessionId, roomId, null, null))
|
||||
.isEqualTo("elementx://open/%40a%2F%3Adomain/%21a%2FRoomId%3Adomain")
|
||||
assertThat(sut.create(sessionId, roomId, threadId, null))
|
||||
.isEqualTo("elementx://open/%40a%2F%3Adomain/%21a%2FRoomId%3Adomain/%24a%2FThreadId")
|
||||
assertThat(sut.create(sessionId, roomId, threadId, eventId))
|
||||
.isEqualTo("elementx://open/%40a%2F%3Adomain/%21a%2FRoomId%3Adomain/%24a%2FThreadId/%24an%2FEventId")
|
||||
assertThat(sut.create(sessionId, roomId, null, eventId))
|
||||
.isEqualTo("elementx://open/%40a%2F%3Adomain/%21a%2FRoomId%3Adomain//%24an%2FEventId")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@ import android.content.Intent
|
|||
import androidx.core.net.toUri
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.deeplink.api.DeeplinkData
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.core.ThreadId
|
||||
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||
|
|
@ -34,6 +38,8 @@ class DefaultDeeplinkParserTest {
|
|||
"elementx://open/@alice:server.org/!aRoomId:domain/\$aThreadId/\$anEventId"
|
||||
const val A_URI_WITH_ROOM_WITH_EVENT_AND_NO_THREAD =
|
||||
"elementx://open/@alice:server.org/!aRoomId:domain//\$anEventId"
|
||||
const val A_URI_WITH_ROOM_WITH_THREAD_AND_EVENT_AND_INVALID_CHARACTERS =
|
||||
"elementx://open/@a%2Flice:server.org/!a%2FRoomId:domain/\$a%2FThreadId/\$an%2FEventId"
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -49,6 +55,15 @@ class DefaultDeeplinkParserTest {
|
|||
.isEqualTo(DeeplinkData.Room(A_SESSION_ID, A_ROOM_ID, A_THREAD_ID, AN_EVENT_ID))
|
||||
assertThat(sut.getFromIntent(createIntent(A_URI_WITH_ROOM_WITH_EVENT_AND_NO_THREAD)))
|
||||
.isEqualTo(DeeplinkData.Room(A_SESSION_ID, A_ROOM_ID, null, AN_EVENT_ID))
|
||||
assertThat(sut.getFromIntent(createIntent(A_URI_WITH_ROOM_WITH_THREAD_AND_EVENT_AND_INVALID_CHARACTERS)))
|
||||
.isEqualTo(
|
||||
DeeplinkData.Room(
|
||||
sessionId = SessionId("@a/lice:server.org"),
|
||||
roomId = RoomId("!a/RoomId:domain"),
|
||||
threadId = ThreadId("\$a/ThreadId"),
|
||||
eventId = EventId("\$an/EventId"),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ class FullScreenIntentPermissionsPresenter(
|
|||
"package:${buildMeta.applicationId}".toUri()
|
||||
)
|
||||
externalIntentLauncher.launch(intent)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
} catch (_: ActivityNotFoundException) {
|
||||
val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS)
|
||||
.putExtra(Settings.EXTRA_APP_PACKAGE, buildMeta.applicationId)
|
||||
externalIntentLauncher.launch(intent)
|
||||
|
|
|
|||
|
|
@ -194,6 +194,8 @@ interface MatrixClient {
|
|||
* Use [Timeline.markAsRead] instead when possible.
|
||||
*/
|
||||
suspend fun markRoomAsFullyRead(roomId: RoomId, eventId: EventId): Result<Unit>
|
||||
|
||||
suspend fun performDatabaseVacuum(): Result<Unit>
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.api.auth
|
||||
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
|
||||
sealed class SessionRestorationException(message: String, cause: Throwable? = null) : Exception(message, cause) {
|
||||
data class MissingSession(val sessionId: SessionId) : SessionRestorationException("Session with id $sessionId not found")
|
||||
class InvalidToken : SessionRestorationException("Access token is invalid or expired")
|
||||
}
|
||||
|
|
@ -8,10 +8,14 @@
|
|||
|
||||
package io.element.android.libraries.matrix.api.exception
|
||||
|
||||
sealed class ClientException(message: String, val details: String?) : Exception(message) {
|
||||
class Generic(message: String, details: String?) : ClientException(message, details)
|
||||
class MatrixApi(val kind: ErrorKind, val code: String, message: String, details: String?) : ClientException(message, details)
|
||||
class Other(message: String) : ClientException(message, null)
|
||||
sealed class ClientException(message: String, val details: String?, cause: Throwable? = null) : Exception(message, cause) {
|
||||
class Generic(message: String, details: String?, cause: Throwable? = null) : ClientException(message, details, cause)
|
||||
class MatrixApi(val kind: ErrorKind, val code: String, message: String, details: String?, cause: Throwable? = null) : ClientException(
|
||||
message = message,
|
||||
details = details,
|
||||
cause = cause
|
||||
)
|
||||
class Other(message: String, cause: Throwable? = null) : ClientException(message, null, cause)
|
||||
}
|
||||
|
||||
fun ClientException.isNetworkError(): Boolean {
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ suspend fun RoomList.awaitLoaded(timeout: Duration = Duration.INFINITE) {
|
|||
it is RoomList.LoadingState.Loaded
|
||||
}
|
||||
}
|
||||
} catch (timeoutException: TimeoutCancellationException) {
|
||||
} catch (_: TimeoutCancellationException) {
|
||||
Timber.d("awaitAllRoomsAreLoaded: no response after $timeout")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,12 @@ enum class TraceLogPack(val key: String) {
|
|||
},
|
||||
NOTIFICATION_CLIENT("notification_client") {
|
||||
override val title: String = "Notification Client"
|
||||
},
|
||||
SYNC_PROFILING("sync_profiling") {
|
||||
override val title: String = "Sync Profiling"
|
||||
},
|
||||
LATEST_EVENTS("latest_events") {
|
||||
override val title = "Latest Events"
|
||||
};
|
||||
|
||||
abstract val title: String
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ dependencies {
|
|||
implementation(projects.libraries.featureflag.api)
|
||||
implementation(projects.libraries.network)
|
||||
implementation(projects.libraries.preferences.api)
|
||||
implementation(projects.libraries.workmanager.api)
|
||||
implementation(projects.services.analytics.api)
|
||||
implementation(projects.services.toolbox.api)
|
||||
api(projects.libraries.matrix.api)
|
||||
|
|
@ -49,6 +50,7 @@ dependencies {
|
|||
testImplementation(projects.libraries.preferences.test)
|
||||
testImplementation(projects.libraries.previewutils)
|
||||
testImplementation(projects.libraries.sessionStorage.test)
|
||||
testImplementation(projects.libraries.workmanager.test)
|
||||
testImplementation(projects.services.analytics.test)
|
||||
testImplementation(projects.services.toolbox.test)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,7 +75,10 @@ import io.element.android.libraries.matrix.impl.util.SessionPathsProvider
|
|||
import io.element.android.libraries.matrix.impl.util.cancelAndDestroy
|
||||
import io.element.android.libraries.matrix.impl.util.mxCallbackFlow
|
||||
import io.element.android.libraries.matrix.impl.verification.RustSessionVerificationService
|
||||
import io.element.android.libraries.matrix.impl.workmanager.PerformDatabaseVacuumWorkManagerRequest
|
||||
import io.element.android.libraries.sessionstorage.api.SessionStore
|
||||
import io.element.android.libraries.workmanager.api.WorkManagerRequestType
|
||||
import io.element.android.libraries.workmanager.api.WorkManagerScheduler
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
import io.element.android.services.toolbox.api.systemclock.SystemClock
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
|
@ -133,6 +136,7 @@ class RustMatrixClient(
|
|||
timelineEventTypeFilterFactory: TimelineEventTypeFilterFactory,
|
||||
private val featureFlagService: FeatureFlagService,
|
||||
private val analyticsService: AnalyticsService,
|
||||
private val workManagerScheduler: WorkManagerScheduler,
|
||||
) : MatrixClient {
|
||||
override val sessionId: UserId = UserId(innerClient.userId())
|
||||
override val deviceId: DeviceId = DeviceId(innerClient.deviceId())
|
||||
|
|
@ -276,6 +280,9 @@ class RustMatrixClient(
|
|||
// Force a refresh of the profile
|
||||
getUserProfile()
|
||||
}
|
||||
|
||||
// Schedule regular database vacuuming to ensure DB performance remains optimal
|
||||
scheduleDatabaseVacuum()
|
||||
}
|
||||
|
||||
override fun userIdServerName(): String {
|
||||
|
|
@ -726,6 +733,13 @@ class RustMatrixClient(
|
|||
}
|
||||
}
|
||||
|
||||
override suspend fun performDatabaseVacuum(): Result<Unit> = withContext(sessionDispatcher) {
|
||||
runCatchingExceptions {
|
||||
Timber.d("Performing database vacuuming for session $sessionId...")
|
||||
innerClient.optimizeStores()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getCacheSize(
|
||||
includeCryptoDb: Boolean = false,
|
||||
): Long = withContext(sessionDispatcher) {
|
||||
|
|
@ -750,6 +764,15 @@ class RustMatrixClient(
|
|||
// Delete all the files for this session
|
||||
sessionPathsProvider.provides(sessionId)?.deleteRecursively()
|
||||
}
|
||||
|
||||
private fun scheduleDatabaseVacuum() {
|
||||
// If there's already a periodic work request, do not schedule another one
|
||||
if (workManagerScheduler.hasPendingWork(sessionId, WorkManagerRequestType.DB_VACUUM)) return
|
||||
|
||||
Timber.i("Scheduling periodic database vacuuming for session $sessionId")
|
||||
val request = PerformDatabaseVacuumWorkManagerRequest(sessionId)
|
||||
workManagerScheduler.submit(request)
|
||||
}
|
||||
}
|
||||
|
||||
private val defaultRoomCreationPowerLevels = PowerLevels(
|
||||
|
|
|
|||
|
|
@ -22,10 +22,12 @@ import io.element.android.libraries.matrix.impl.paths.SessionPaths
|
|||
import io.element.android.libraries.matrix.impl.paths.getSessionPaths
|
||||
import io.element.android.libraries.matrix.impl.proxy.ProxyProvider
|
||||
import io.element.android.libraries.matrix.impl.room.TimelineEventTypeFilterFactory
|
||||
import io.element.android.libraries.matrix.impl.storage.SqliteStoreBuilderProvider
|
||||
import io.element.android.libraries.matrix.impl.util.anonymizedTokens
|
||||
import io.element.android.libraries.network.useragent.UserAgentProvider
|
||||
import io.element.android.libraries.sessionstorage.api.SessionData
|
||||
import io.element.android.libraries.sessionstorage.api.SessionStore
|
||||
import io.element.android.libraries.workmanager.api.WorkManagerScheduler
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
import io.element.android.services.toolbox.api.systemclock.SystemClock
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
|
@ -36,7 +38,6 @@ import org.matrix.rustcomponents.sdk.RequestConfig
|
|||
import org.matrix.rustcomponents.sdk.Session
|
||||
import org.matrix.rustcomponents.sdk.SlidingSyncVersion
|
||||
import org.matrix.rustcomponents.sdk.SlidingSyncVersionBuilder
|
||||
import org.matrix.rustcomponents.sdk.SqliteStoreBuilder
|
||||
import org.matrix.rustcomponents.sdk.use
|
||||
import timber.log.Timber
|
||||
import uniffi.matrix_sdk_base.MediaRetentionPolicy
|
||||
|
|
@ -62,6 +63,8 @@ class RustMatrixClientFactory(
|
|||
private val featureFlagService: FeatureFlagService,
|
||||
private val timelineEventTypeFilterFactory: TimelineEventTypeFilterFactory,
|
||||
private val clientBuilderProvider: ClientBuilderProvider,
|
||||
private val sqliteStoreBuilderProvider: SqliteStoreBuilderProvider,
|
||||
private val workManagerScheduler: WorkManagerScheduler,
|
||||
) {
|
||||
private val sessionDelegate = RustClientSessionDelegate(sessionStore, appCoroutineScope, coroutineDispatchers)
|
||||
|
||||
|
|
@ -115,6 +118,7 @@ class RustMatrixClientFactory(
|
|||
timelineEventTypeFilterFactory = timelineEventTypeFilterFactory,
|
||||
featureFlagService = featureFlagService,
|
||||
analyticsService = analyticsService,
|
||||
workManagerScheduler = workManagerScheduler,
|
||||
).also {
|
||||
Timber.tag(it.toString()).d("Creating Client with access token '$anonymizedAccessToken' and refresh token '$anonymizedRefreshToken'")
|
||||
}
|
||||
|
|
@ -126,12 +130,11 @@ class RustMatrixClientFactory(
|
|||
slidingSyncType: ClientBuilderSlidingSync,
|
||||
): ClientBuilder {
|
||||
return clientBuilderProvider.provide()
|
||||
.sqliteStore(
|
||||
SqliteStoreBuilder(
|
||||
dataPath = sessionPaths.fileDirectory.absolutePath,
|
||||
cachePath = sessionPaths.cacheDirectory.absolutePath,
|
||||
).passphrase(passphrase)
|
||||
)
|
||||
.run {
|
||||
sqliteStoreBuilderProvider.provide(sessionPaths)
|
||||
.passphrase(passphrase)
|
||||
.setupClientBuilder(this)
|
||||
}
|
||||
.setSessionDelegate(sessionDelegate)
|
||||
.userAgent(userAgentProvider.provide())
|
||||
.addRootCertificates(userCertificatesProvider.provides())
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
|||
import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails
|
||||
import io.element.android.libraries.matrix.api.auth.OidcDetails
|
||||
import io.element.android.libraries.matrix.api.auth.OidcPrompt
|
||||
import io.element.android.libraries.matrix.api.auth.SessionRestorationException
|
||||
import io.element.android.libraries.matrix.api.auth.external.ExternalSession
|
||||
import io.element.android.libraries.matrix.api.auth.qrlogin.MatrixQrCodeLoginData
|
||||
import io.element.android.libraries.matrix.api.auth.qrlogin.QrCodeLoginStep
|
||||
|
|
@ -91,10 +92,10 @@ class RustMatrixAuthenticationService(
|
|||
}
|
||||
rustMatrixClientFactory.create(sessionData)
|
||||
} else {
|
||||
error("Token is not valid")
|
||||
throw SessionRestorationException.InvalidToken()
|
||||
}
|
||||
} else {
|
||||
error("No session to restore with id $sessionId")
|
||||
throw SessionRestorationException.MissingSession(sessionId)
|
||||
}
|
||||
}.mapFailure { failure ->
|
||||
failure.mapClientException()
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ fun Throwable.mapRecoveryException(): RecoveryException {
|
|||
}
|
||||
}
|
||||
else -> RecoveryException.Client(
|
||||
ClientException.Other("Unknown error")
|
||||
ClientException.Other("Unknown error", this)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,15 +15,16 @@ fun Throwable.mapClientException(): ClientException {
|
|||
return when (this) {
|
||||
is RustClientException -> {
|
||||
when (this) {
|
||||
is RustClientException.Generic -> ClientException.Generic(msg, details)
|
||||
is RustClientException.Generic -> ClientException.Generic(message = msg, details = details, cause = this)
|
||||
is RustClientException.MatrixApi -> ClientException.MatrixApi(
|
||||
kind = kind.map(),
|
||||
code = code,
|
||||
message = msg,
|
||||
details = details,
|
||||
cause = this,
|
||||
)
|
||||
}
|
||||
}
|
||||
else -> ClientException.Other(message ?: "Unknown error")
|
||||
else -> ClientException.Other(message ?: "Unknown error", this)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class RoomSyncSubscriber(
|
|||
}
|
||||
subscribedRoomIds.add(roomId)
|
||||
} catch (exception: Exception) {
|
||||
Timber.e("Failed to subscribe to room $roomId")
|
||||
Timber.e(exception, "Failed to subscribe to room $roomId")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,7 +85,9 @@ class RustBaseRoom(
|
|||
}.stateIn(roomCoroutineScope, started = SharingStarted.Lazily, initialValue = initialRoomInfo)
|
||||
|
||||
override fun predecessorRoom(): PredecessorRoom? {
|
||||
return innerRoom.predecessorRoom()?.map()
|
||||
return runCatchingExceptions { innerRoom.predecessorRoom()?.map() }
|
||||
.onFailure { Timber.e(it, "Could not get predecessor room") }
|
||||
.getOrNull()
|
||||
}
|
||||
|
||||
override suspend fun subscribeToSync() = roomSyncSubscriber.subscribe(roomId)
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ fun RoomListInterface.loadingStateFlow(): Flow<RoomListLoadingState> =
|
|||
try {
|
||||
send(result.state)
|
||||
} catch (exception: Exception) {
|
||||
Timber.d("loadingStateFlow() initialState failed.")
|
||||
Timber.d(exception, "loadingStateFlow() initialState failed.")
|
||||
}
|
||||
result.stateStream
|
||||
}.catch {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ class RoomSummaryFactory(
|
|||
) {
|
||||
suspend fun create(room: Room): RoomSummary {
|
||||
val roomInfo = room.roomInfo().let(roomInfoMapper::map)
|
||||
val latestEvent = room.newLatestEvent().use { event ->
|
||||
val latestEvent = room.latestEvent().use { event ->
|
||||
when (event) {
|
||||
is RustLatestEventValue.None -> LatestEventValue.None
|
||||
is RustLatestEventValue.Local -> LatestEventValue.Local(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl.storage
|
||||
|
||||
import io.element.android.libraries.matrix.impl.paths.SessionPaths
|
||||
import org.matrix.rustcomponents.sdk.ClientBuilder
|
||||
import org.matrix.rustcomponents.sdk.SqliteStoreBuilder as SdkSqliteStoreBuilder
|
||||
|
||||
interface SqliteStoreBuilder {
|
||||
fun passphrase(passphrase: String?): SqliteStoreBuilder
|
||||
fun setupClientBuilder(clientBuilder: ClientBuilder): ClientBuilder
|
||||
}
|
||||
|
||||
class RustSqliteStoreBuilder(
|
||||
private val sessionPaths: SessionPaths,
|
||||
) : SqliteStoreBuilder {
|
||||
private var inner = SdkSqliteStoreBuilder(
|
||||
dataPath = sessionPaths.fileDirectory.absolutePath,
|
||||
cachePath = sessionPaths.cacheDirectory.absolutePath,
|
||||
)
|
||||
|
||||
override fun passphrase(passphrase: String?): SqliteStoreBuilder {
|
||||
inner = inner.passphrase(passphrase)
|
||||
return this
|
||||
}
|
||||
|
||||
override fun setupClientBuilder(clientBuilder: ClientBuilder): ClientBuilder {
|
||||
return clientBuilder.sqliteStore(this.inner)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl.storage
|
||||
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.ContributesBinding
|
||||
import io.element.android.libraries.matrix.impl.paths.SessionPaths
|
||||
|
||||
interface SqliteStoreBuilderProvider {
|
||||
fun provide(sessionPaths: SessionPaths): SqliteStoreBuilder
|
||||
}
|
||||
|
||||
@ContributesBinding(AppScope::class)
|
||||
class RustSqliteStoreBuilderProvider : SqliteStoreBuilderProvider {
|
||||
override fun provide(sessionPaths: SessionPaths): SqliteStoreBuilder {
|
||||
return RustSqliteStoreBuilder(sessionPaths)
|
||||
}
|
||||
}
|
||||
|
|
@ -16,6 +16,8 @@ fun TraceLogPack.map(): RustTraceLogPack = when (this) {
|
|||
TraceLogPack.EVENT_CACHE -> RustTraceLogPack.EVENT_CACHE
|
||||
TraceLogPack.TIMELINE -> RustTraceLogPack.TIMELINE
|
||||
TraceLogPack.NOTIFICATION_CLIENT -> RustTraceLogPack.NOTIFICATION_CLIENT
|
||||
TraceLogPack.LATEST_EVENTS -> RustTraceLogPack.LATEST_EVENTS
|
||||
TraceLogPack.SYNC_PROFILING -> RustTraceLogPack.SYNC_PROFILING
|
||||
}
|
||||
|
||||
fun Collection<TraceLogPack>.map(): List<RustTraceLogPack> {
|
||||
|
|
|
|||
|
|
@ -14,10 +14,10 @@ import timber.log.Timber
|
|||
fun logError(throwable: Throwable) {
|
||||
when (throwable) {
|
||||
is ClientException.Generic -> {
|
||||
Timber.e("Error ${throwable.msg}", throwable)
|
||||
Timber.e(throwable, "Error ${throwable.msg}")
|
||||
}
|
||||
else -> {
|
||||
Timber.e("Error", throwable)
|
||||
Timber.e(throwable, "Error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ class RustWidgetDriver(
|
|||
override suspend fun send(message: String) {
|
||||
try {
|
||||
driverAndHandle.handle.send(message)
|
||||
} catch (e: IllegalStateException) {
|
||||
} catch (_: IllegalStateException) {
|
||||
// The handle is closed, ignore
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl.workmanager
|
||||
|
||||
import androidx.work.Constraints
|
||||
import androidx.work.Data
|
||||
import androidx.work.PeriodicWorkRequest
|
||||
import androidx.work.WorkRequest
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.impl.workmanager.VacuumDatabaseWorker.Companion.SESSION_ID_PARAM
|
||||
import io.element.android.libraries.workmanager.api.WorkManagerRequest
|
||||
import io.element.android.libraries.workmanager.api.WorkManagerRequestType
|
||||
import io.element.android.libraries.workmanager.api.workManagerTag
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class PerformDatabaseVacuumWorkManagerRequest(
|
||||
private val sessionId: SessionId,
|
||||
) : WorkManagerRequest {
|
||||
override fun build(): Result<List<WorkRequest>> {
|
||||
val data = Data.Builder().putString(SESSION_ID_PARAM, sessionId.value).build()
|
||||
val workRequest = PeriodicWorkRequest.Builder(
|
||||
workerClass = VacuumDatabaseWorker::class,
|
||||
// Run once a day
|
||||
repeatInterval = 1,
|
||||
repeatIntervalTimeUnit = TimeUnit.DAYS,
|
||||
)
|
||||
.addTag(workManagerTag(sessionId, WorkManagerRequestType.DB_VACUUM))
|
||||
.setInputData(data)
|
||||
// Only run when the device is idle to avoid impacting user experience
|
||||
.setConstraints(Constraints.Builder().setRequiresDeviceIdle(true).build())
|
||||
.build()
|
||||
|
||||
return Result.success(listOf(workRequest))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl.workmanager
|
||||
|
||||
import android.content.Context
|
||||
import androidx.work.CoroutineWorker
|
||||
import androidx.work.WorkerParameters
|
||||
import dev.zacsweers.metro.AppScope
|
||||
import dev.zacsweers.metro.Assisted
|
||||
import dev.zacsweers.metro.AssistedFactory
|
||||
import dev.zacsweers.metro.AssistedInject
|
||||
import dev.zacsweers.metro.ContributesIntoMap
|
||||
import dev.zacsweers.metro.binding
|
||||
import io.element.android.libraries.di.annotations.ApplicationContext
|
||||
import io.element.android.libraries.matrix.api.MatrixClientProvider
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.workmanager.api.di.MetroWorkerFactory
|
||||
import io.element.android.libraries.workmanager.api.di.WorkerKey
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
import io.element.android.services.analytics.api.recordTransaction
|
||||
import timber.log.Timber
|
||||
|
||||
@AssistedInject
|
||||
class VacuumDatabaseWorker(
|
||||
@Assisted workerParams: WorkerParameters,
|
||||
@ApplicationContext private val context: Context,
|
||||
private val matrixClientProvider: MatrixClientProvider,
|
||||
private val analyticsService: AnalyticsService,
|
||||
) : CoroutineWorker(context, workerParams) {
|
||||
companion object {
|
||||
const val SESSION_ID_PARAM = "session_id"
|
||||
}
|
||||
|
||||
override suspend fun doWork(): Result {
|
||||
Timber.d("Starting database vacuuming...")
|
||||
val sessionId = inputData.getString(SESSION_ID_PARAM)?.let(::SessionId) ?: return Result.failure()
|
||||
val client = matrixClientProvider.getOrRestore(sessionId).getOrNull() ?: return Result.failure()
|
||||
return analyticsService.recordTransaction("Vacuuming DBs", "vacuuming") { transaction ->
|
||||
client.performDatabaseVacuum()
|
||||
.fold(
|
||||
onSuccess = {
|
||||
Timber.d("Database vacuuming finished successfully")
|
||||
Result.success()
|
||||
},
|
||||
onFailure = { error ->
|
||||
transaction.attachError(error)
|
||||
Timber.e(error, "Database vacuuming failed")
|
||||
Result.failure()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ContributesIntoMap(AppScope::class, binding = binding<MetroWorkerFactory.WorkerInstanceFactory<*>>())
|
||||
@WorkerKey(VacuumDatabaseWorker::class)
|
||||
@AssistedFactory
|
||||
interface Factory : MetroWorkerFactory.WorkerInstanceFactory<VacuumDatabaseWorker>
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl
|
||||
|
||||
import org.matrix.rustcomponents.sdk.NoHandle
|
||||
import org.matrix.rustcomponents.sdk.SqliteStoreBuilder
|
||||
|
||||
class FakeFfiSqliteStoreBuilder : SqliteStoreBuilder(NoHandle) {
|
||||
override fun cacheSize(cacheSize: UInt?): SqliteStoreBuilder = this
|
||||
override fun journalSizeLimit(limit: UInt?): SqliteStoreBuilder = this
|
||||
override fun passphrase(passphrase: String?): SqliteStoreBuilder = this
|
||||
override fun poolMaxSize(poolMaxSize: UInt?): SqliteStoreBuilder = this
|
||||
override fun systemIsMemoryConstrained(): SqliteStoreBuilder = this
|
||||
}
|
||||
|
|
@ -14,26 +14,33 @@ import io.element.android.libraries.matrix.api.core.SessionId
|
|||
import io.element.android.libraries.matrix.impl.auth.FakeProxyProvider
|
||||
import io.element.android.libraries.matrix.impl.auth.FakeUserCertificatesProvider
|
||||
import io.element.android.libraries.matrix.impl.room.FakeTimelineEventTypeFilterFactory
|
||||
import io.element.android.libraries.matrix.impl.storage.FakeSqliteStoreBuilderProvider
|
||||
import io.element.android.libraries.network.useragent.SimpleUserAgentProvider
|
||||
import io.element.android.libraries.sessionstorage.api.SessionStore
|
||||
import io.element.android.libraries.sessionstorage.test.InMemorySessionStore
|
||||
import io.element.android.libraries.sessionstorage.test.aSessionData
|
||||
import io.element.android.libraries.workmanager.api.WorkManagerRequest
|
||||
import io.element.android.libraries.workmanager.test.FakeWorkManagerScheduler
|
||||
import io.element.android.services.analytics.test.FakeAnalyticsService
|
||||
import io.element.android.services.toolbox.test.systemclock.FakeSystemClock
|
||||
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||
import io.element.android.tests.testutils.testCoroutineDispatchers
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
class RustMatrixClientFactoryTest {
|
||||
@Test
|
||||
fun test() = runTest {
|
||||
val sut = createRustMatrixClientFactory()
|
||||
val scheduleVacuumLambda = lambdaRecorder<WorkManagerRequest, Unit> {}
|
||||
val workManagerScheduler = FakeWorkManagerScheduler(submitLambda = scheduleVacuumLambda)
|
||||
val sut = createRustMatrixClientFactory(workManagerScheduler = workManagerScheduler)
|
||||
|
||||
val result = sut.create(aSessionData())
|
||||
|
||||
assertThat(result.sessionId).isEqualTo(SessionId("@alice:server.org"))
|
||||
scheduleVacuumLambda.assertions().isCalledOnce()
|
||||
result.destroy()
|
||||
}
|
||||
}
|
||||
|
|
@ -44,6 +51,7 @@ fun TestScope.createRustMatrixClientFactory(
|
|||
updateUserProfileResult = { _, _, _ -> },
|
||||
),
|
||||
clientBuilderProvider: ClientBuilderProvider = FakeClientBuilderProvider(),
|
||||
workManagerScheduler: FakeWorkManagerScheduler = FakeWorkManagerScheduler(),
|
||||
) = RustMatrixClientFactory(
|
||||
cacheDirectory = cacheDirectory,
|
||||
appCoroutineScope = backgroundScope,
|
||||
|
|
@ -57,4 +65,6 @@ fun TestScope.createRustMatrixClientFactory(
|
|||
featureFlagService = FakeFeatureFlagService(),
|
||||
timelineEventTypeFilterFactory = FakeTimelineEventTypeFilterFactory(),
|
||||
clientBuilderProvider = clientBuilderProvider,
|
||||
sqliteStoreBuilderProvider = FakeSqliteStoreBuilderProvider(),
|
||||
workManagerScheduler = workManagerScheduler,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import io.element.android.libraries.matrix.test.A_USER_NAME
|
|||
import io.element.android.libraries.sessionstorage.api.SessionStore
|
||||
import io.element.android.libraries.sessionstorage.test.InMemorySessionStore
|
||||
import io.element.android.libraries.sessionstorage.test.aSessionData
|
||||
import io.element.android.libraries.workmanager.test.FakeWorkManagerScheduler
|
||||
import io.element.android.services.analytics.test.FakeAnalyticsService
|
||||
import io.element.android.services.toolbox.test.systemclock.FakeSystemClock
|
||||
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||
|
|
@ -31,13 +32,11 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.advanceUntilIdle
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import org.matrix.rustcomponents.sdk.Client
|
||||
import org.matrix.rustcomponents.sdk.UserProfile
|
||||
import java.io.File
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
class RustMatrixClientTest {
|
||||
@Test
|
||||
fun `ensure that sessionId and deviceId can be retrieved from the client`() = runTest {
|
||||
|
|
@ -118,5 +117,6 @@ class RustMatrixClientTest {
|
|||
timelineEventTypeFilterFactory = FakeTimelineEventTypeFilterFactory(),
|
||||
featureFlagService = FakeFeatureFlagService(),
|
||||
analyticsService = FakeAnalyticsService(),
|
||||
workManagerScheduler = FakeWorkManagerScheduler(submitLambda = {}),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,10 +11,8 @@ package io.element.android.libraries.matrix.impl.auth
|
|||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.matrix.api.auth.MatrixHomeServerDetails
|
||||
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiHomeserverLoginDetails
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
class HomeserverDetailsKtTest {
|
||||
@Test
|
||||
fun `map should be correct`() {
|
||||
|
|
|
|||
|
|
@ -14,10 +14,8 @@ import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiClient
|
|||
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiClientBuilder
|
||||
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiHomeserverLoginDetails
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
class RustHomeserverLoginCompatibilityCheckerTest {
|
||||
@Test
|
||||
fun `check - is valid if it supports OIDC login`() = runTest {
|
||||
|
|
|
|||
|
|
@ -23,12 +23,10 @@ import io.element.android.libraries.sessionstorage.test.InMemorySessionStore
|
|||
import io.element.android.tests.testutils.testCoroutineDispatchers
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import java.io.File
|
||||
|
||||
class RustMatrixAuthenticationServiceTest {
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
fun `setHomeserver is successful`() = runTest {
|
||||
val sut = createRustMatrixAuthenticationService(
|
||||
|
|
|
|||
|
|
@ -11,10 +11,8 @@ package io.element.android.libraries.matrix.impl.auth.qrlogin
|
|||
import com.google.common.truth.Truth.assertThat
|
||||
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiQrCodeData
|
||||
import io.element.android.libraries.matrix.test.A_HOMESERVER_URL
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
class SdkQrCodeLoginDataTest {
|
||||
@Test
|
||||
fun `getServer reads the value from the Rust side, null case`() {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import org.matrix.rustcomponents.sdk.SyncServiceBuilder
|
|||
import org.matrix.rustcomponents.sdk.TaskHandle
|
||||
import org.matrix.rustcomponents.sdk.UnableToDecryptDelegate
|
||||
import org.matrix.rustcomponents.sdk.UserProfile
|
||||
import uniffi.matrix_sdk_base.MediaRetentionPolicy
|
||||
|
||||
class FakeFfiClient(
|
||||
private val userId: String = A_USER_ID.value,
|
||||
|
|
@ -88,5 +89,7 @@ class FakeFfiClient(
|
|||
return homeserverLoginDetailsResult()
|
||||
}
|
||||
|
||||
override suspend fun setMediaRetentionPolicy(policy: MediaRetentionPolicy) {}
|
||||
|
||||
override fun close() = closeResult()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,5 +44,6 @@ class FakeFfiClientBuilder(
|
|||
override fun enableShareHistoryOnInvite(enableShareHistoryOnInvite: Boolean): ClientBuilder = this
|
||||
override fun threadsEnabled(enabled: Boolean, threadSubscriptions: Boolean): ClientBuilder = this
|
||||
override fun sqliteStore(config: SqliteStoreBuilder): ClientBuilder = this
|
||||
override fun inMemoryStore(): ClientBuilder = this
|
||||
override suspend fun build() = buildResult()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import io.element.android.libraries.matrix.api.core.RoomId
|
|||
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomInfo
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
import io.element.android.tests.testutils.lambda.lambdaError
|
||||
import org.matrix.rustcomponents.sdk.EventTimelineItem
|
||||
import org.matrix.rustcomponents.sdk.LatestEventValue
|
||||
import org.matrix.rustcomponents.sdk.NoHandle
|
||||
import org.matrix.rustcomponents.sdk.Room
|
||||
import org.matrix.rustcomponents.sdk.RoomInfo
|
||||
|
|
@ -24,7 +24,7 @@ class FakeFfiRoom(
|
|||
private val getMembers: () -> RoomMembersIterator = { lambdaError() },
|
||||
private val getMembersNoSync: () -> RoomMembersIterator = { lambdaError() },
|
||||
private val leaveLambda: () -> Unit = { lambdaError() },
|
||||
private val latestEventLambda: () -> EventTimelineItem? = { lambdaError() },
|
||||
private val latestEventLambda: () -> LatestEventValue = { lambdaError() },
|
||||
private val suggestedRoleForUserLambda: (String) -> RoomMemberRole = { lambdaError() },
|
||||
private val roomInfo: RoomInfo = aRustRoomInfo(id = roomId.value),
|
||||
) : Room(NoHandle) {
|
||||
|
|
@ -48,7 +48,7 @@ class FakeFfiRoom(
|
|||
return roomInfo
|
||||
}
|
||||
|
||||
override suspend fun latestEvent(): EventTimelineItem? {
|
||||
override suspend fun latestEvent(): LatestEventValue {
|
||||
return latestEventLambda()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,15 +29,13 @@ import io.element.android.tests.testutils.lambda.lambdaRecorder
|
|||
import io.element.android.tests.testutils.testCoroutineDispatchers
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import org.matrix.rustcomponents.sdk.NotificationClient
|
||||
import org.matrix.rustcomponents.sdk.NotificationStatus
|
||||
import org.matrix.rustcomponents.sdk.TimelineEventType
|
||||
|
||||
class RustNotificationServiceTest {
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun test() = runTest {
|
||||
val notificationClient = FakeFfiNotificationClient(
|
||||
notificationItemResult = mapOf(AN_EVENT_ID.value to aRustBatchNotificationResult()),
|
||||
|
|
@ -58,8 +56,7 @@ class RustNotificationServiceTest {
|
|||
)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `test mapping invalid item only drops that item`() = runTest {
|
||||
val error = IllegalStateException("This event type is not supported")
|
||||
val faultyEvent = object : FakeFfiTimelineEvent() {
|
||||
|
|
@ -86,8 +83,7 @@ class RustNotificationServiceTest {
|
|||
assertThat(successfulResult?.isSuccess).isTrue()
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `test unable to resolve event`() = runTest {
|
||||
val notificationClient = FakeFfiNotificationClient(
|
||||
notificationItemResult = emptyMap(),
|
||||
|
|
@ -99,8 +95,7 @@ class RustNotificationServiceTest {
|
|||
assertThat(exception).isInstanceOf(NotificationResolverException::class.java)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `close should invoke the close method of the service`() = runTest {
|
||||
val closeResult = lambdaRecorder<Unit> { }
|
||||
val notificationClient = FakeFfiNotificationClient(
|
||||
|
|
|
|||
|
|
@ -16,13 +16,11 @@ import io.element.android.libraries.matrix.test.A_ROOM_ID
|
|||
import io.element.android.tests.testutils.testCoroutineDispatchers
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import org.matrix.rustcomponents.sdk.NotificationSettings
|
||||
|
||||
class RustNotificationSettingsServiceTest {
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun test() = runTest {
|
||||
val sut = createRustNotificationSettingsService()
|
||||
val result = sut.getRoomNotificationSettings(
|
||||
|
|
|
|||
|
|
@ -13,10 +13,8 @@ import io.element.android.libraries.matrix.api.pusher.UnsetHttpPusherData
|
|||
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiClient
|
||||
import io.element.android.tests.testutils.testCoroutineDispatchers
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
class RustPushersServiceTest {
|
||||
@Test
|
||||
fun `setPusher should invoke the client method`() = runTest {
|
||||
|
|
|
|||
|
|
@ -14,10 +14,8 @@ import io.element.android.libraries.matrix.api.user.MatrixUser
|
|||
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomHero
|
||||
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustRoomInfo
|
||||
import io.element.android.libraries.matrix.test.A_USER_ID
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
class RoomInfoExtTest {
|
||||
@Test
|
||||
fun `get non empty element Heroes`() {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@ import io.element.android.libraries.matrix.test.room.defaultRoomPowerLevelValues
|
|||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.persistentMapOf
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import org.matrix.rustcomponents.sdk.Membership
|
||||
import uniffi.matrix_sdk_base.EncryptionState
|
||||
|
|
@ -40,7 +39,6 @@ import org.matrix.rustcomponents.sdk.JoinRule as RustJoinRule
|
|||
import org.matrix.rustcomponents.sdk.RoomHistoryVisibility as RustRoomHistoryVisibility
|
||||
import org.matrix.rustcomponents.sdk.RoomNotificationMode as RustRoomNotificationMode
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
class RoomInfoMapperTest {
|
||||
@Test
|
||||
fun `mapping of RustRoomInfo should map all the fields`() {
|
||||
|
|
|
|||
|
|
@ -31,11 +31,9 @@ import kotlinx.coroutines.flow.shareIn
|
|||
import kotlinx.coroutines.isActive
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import uniffi.matrix_sdk.RoomMemberRole
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
class RustBaseRoomTest {
|
||||
@Test
|
||||
fun `RustBaseRoom should cancel the room coroutine scope when it is destroyed`() = runTest {
|
||||
|
|
|
|||
|
|
@ -25,10 +25,8 @@ import io.element.android.services.analytics.test.FakeAnalyticsService
|
|||
import io.element.android.tests.testutils.lambda.lambdaRecorder
|
||||
import io.element.android.tests.testutils.lambda.value
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
class DefaultJoinRoomTest {
|
||||
@Test
|
||||
fun `when using roomId and there is no server names, the classic join room API is used`() = runTest {
|
||||
|
|
|
|||
|
|
@ -24,10 +24,8 @@ import io.element.android.libraries.matrix.test.A_USER_ID_3
|
|||
import io.element.android.libraries.matrix.test.A_USER_ID_4
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
class RoomMemberListFetcherTest {
|
||||
@Test
|
||||
fun `fetchRoomMembers with CACHE source - emits cached members, if any`() = runTest {
|
||||
|
|
|
|||
|
|
@ -19,12 +19,10 @@ import kotlinx.coroutines.test.StandardTestDispatcher
|
|||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runCurrent
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import org.matrix.rustcomponents.sdk.RoomDirectorySearch
|
||||
import org.matrix.rustcomponents.sdk.RoomDirectorySearchEntryUpdate
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class RustBaseRoomDirectoryListTest {
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -11,12 +11,10 @@ package io.element.android.libraries.matrix.impl.roomdirectory
|
|||
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiClient
|
||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
|
||||
class RustBaseRoomDirectoryServiceTest {
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun test() = runTest {
|
||||
val client = FakeFfiClient()
|
||||
val sut = RustRoomDirectoryService(
|
||||
|
|
|
|||
|
|
@ -12,13 +12,11 @@ import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiRoomList
|
|||
import io.element.android.libraries.matrix.impl.fixtures.fakes.FakeFfiRoomListService
|
||||
import io.element.android.services.analytics.test.FakeAnalyticsService
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
|
||||
class RoomListFactoryTest {
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `createRoomList should work`() = runTest {
|
||||
val sut = RoomListFactory(
|
||||
innerRoomListService = FakeFfiRoomListService(),
|
||||
|
|
|
|||
|
|
@ -21,15 +21,14 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
|||
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import org.matrix.rustcomponents.sdk.LatestEventValue
|
||||
import org.matrix.rustcomponents.sdk.RoomListEntriesUpdate
|
||||
|
||||
class RoomSummaryListProcessorTest {
|
||||
private val summaries = MutableStateFlow<List<RoomSummary>>(emptyList())
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `Append adds new entries at the end of the list`() = runTest {
|
||||
summaries.value = listOf(aRoomSummary())
|
||||
val processor = createProcessor()
|
||||
|
|
@ -41,8 +40,7 @@ class RoomSummaryListProcessorTest {
|
|||
assertThat(summaries.value.subList(1, 4).all { it.roomId == A_ROOM_ID_2 }).isTrue()
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `PushBack adds a new entry at the end of the list`() = runTest {
|
||||
summaries.value = listOf(aRoomSummary())
|
||||
val processor = createProcessor()
|
||||
|
|
@ -52,8 +50,7 @@ class RoomSummaryListProcessorTest {
|
|||
assertThat(summaries.value.last().roomId).isEqualTo(A_ROOM_ID_2)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `PushFront inserts a new entry at the start of the list`() = runTest {
|
||||
summaries.value = listOf(aRoomSummary())
|
||||
val processor = createProcessor()
|
||||
|
|
@ -63,8 +60,7 @@ class RoomSummaryListProcessorTest {
|
|||
assertThat(summaries.value.first().roomId).isEqualTo(A_ROOM_ID_2)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `Set replaces an entry at some index`() = runTest {
|
||||
summaries.value = listOf(aRoomSummary())
|
||||
val processor = createProcessor()
|
||||
|
|
@ -76,8 +72,7 @@ class RoomSummaryListProcessorTest {
|
|||
assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_2)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `Insert inserts a new entry at the provided index`() = runTest {
|
||||
summaries.value = listOf(aRoomSummary())
|
||||
val processor = createProcessor()
|
||||
|
|
@ -89,8 +84,7 @@ class RoomSummaryListProcessorTest {
|
|||
assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_2)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `Remove removes an entry at some index`() = runTest {
|
||||
summaries.value = listOf(
|
||||
aRoomSummary(roomId = A_ROOM_ID),
|
||||
|
|
@ -105,8 +99,7 @@ class RoomSummaryListProcessorTest {
|
|||
assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_2)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `PopBack removes an entry at the end of the list`() = runTest {
|
||||
summaries.value = listOf(
|
||||
aRoomSummary(roomId = A_ROOM_ID),
|
||||
|
|
@ -121,8 +114,7 @@ class RoomSummaryListProcessorTest {
|
|||
assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `PopFront removes an entry at the start of the list`() = runTest {
|
||||
summaries.value = listOf(
|
||||
aRoomSummary(roomId = A_ROOM_ID),
|
||||
|
|
@ -137,8 +129,7 @@ class RoomSummaryListProcessorTest {
|
|||
assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID_2)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `Clear removes all the entries`() = runTest {
|
||||
summaries.value = listOf(
|
||||
aRoomSummary(roomId = A_ROOM_ID),
|
||||
|
|
@ -151,8 +142,7 @@ class RoomSummaryListProcessorTest {
|
|||
assertThat(summaries.value).isEmpty()
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `Truncate removes all entries after the provided length`() = runTest {
|
||||
summaries.value = listOf(
|
||||
aRoomSummary(roomId = A_ROOM_ID),
|
||||
|
|
@ -167,8 +157,7 @@ class RoomSummaryListProcessorTest {
|
|||
assertThat(summaries.value[index].roomId).isEqualTo(A_ROOM_ID)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `Reset removes all entries and add the provided ones`() = runTest {
|
||||
summaries.value = listOf(
|
||||
aRoomSummary(roomId = A_ROOM_ID),
|
||||
|
|
@ -185,7 +174,7 @@ class RoomSummaryListProcessorTest {
|
|||
|
||||
private fun aRustRoom(roomId: RoomId = A_ROOM_ID) = FakeFfiRoom(
|
||||
roomId = roomId,
|
||||
latestEventLambda = { null },
|
||||
latestEventLambda = { LatestEventValue.None }
|
||||
)
|
||||
|
||||
private fun TestScope.createProcessor() = RoomSummaryListProcessor(
|
||||
|
|
|
|||
|
|
@ -19,12 +19,10 @@ import kotlinx.coroutines.test.StandardTestDispatcher
|
|||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runCurrent
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import org.matrix.rustcomponents.sdk.RoomListServiceSyncIndicator
|
||||
import org.matrix.rustcomponents.sdk.RoomListService as RustRoomListService
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class RustBaseRoomListServiceTest {
|
||||
@Test
|
||||
|
|
|
|||
|
|
@ -18,15 +18,13 @@ import io.element.android.libraries.previewutils.room.aSpaceRoom
|
|||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import org.matrix.rustcomponents.sdk.SpaceListUpdate
|
||||
|
||||
class RoomSummaryListProcessorTest {
|
||||
private val spaceRoomsFlow = MutableStateFlow<List<SpaceRoom>>(emptyList())
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `Append adds new entries at the end of the list`() = runTest {
|
||||
spaceRoomsFlow.value = listOf(aSpaceRoom())
|
||||
val processor = createProcessor()
|
||||
|
|
@ -38,8 +36,7 @@ class RoomSummaryListProcessorTest {
|
|||
assertThat(spaceRoomsFlow.value.subList(1, 4).all { it.roomId == A_ROOM_ID_2 }).isTrue()
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `PushBack adds a new entry at the end of the list`() = runTest {
|
||||
spaceRoomsFlow.value = listOf(aSpaceRoom())
|
||||
val processor = createProcessor()
|
||||
|
|
@ -49,8 +46,7 @@ class RoomSummaryListProcessorTest {
|
|||
assertThat(spaceRoomsFlow.value.last().roomId).isEqualTo(A_ROOM_ID_2)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `PushFront inserts a new entry at the start of the list`() = runTest {
|
||||
spaceRoomsFlow.value = listOf(aSpaceRoom())
|
||||
val processor = createProcessor()
|
||||
|
|
@ -60,8 +56,7 @@ class RoomSummaryListProcessorTest {
|
|||
assertThat(spaceRoomsFlow.value.first().roomId).isEqualTo(A_ROOM_ID_2)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `Set replaces an entry at some index`() = runTest {
|
||||
spaceRoomsFlow.value = listOf(aSpaceRoom())
|
||||
val processor = createProcessor()
|
||||
|
|
@ -73,8 +68,7 @@ class RoomSummaryListProcessorTest {
|
|||
assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID_2)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `Insert inserts a new entry at the provided index`() = runTest {
|
||||
spaceRoomsFlow.value = listOf(aSpaceRoom())
|
||||
val processor = createProcessor()
|
||||
|
|
@ -86,8 +80,7 @@ class RoomSummaryListProcessorTest {
|
|||
assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID_2)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `Remove removes an entry at some index`() = runTest {
|
||||
spaceRoomsFlow.value = listOf(
|
||||
aSpaceRoom(roomId = A_ROOM_ID),
|
||||
|
|
@ -102,8 +95,7 @@ class RoomSummaryListProcessorTest {
|
|||
assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID_2)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `PopBack removes an entry at the end of the list`() = runTest {
|
||||
spaceRoomsFlow.value = listOf(
|
||||
aSpaceRoom(roomId = A_ROOM_ID),
|
||||
|
|
@ -118,8 +110,7 @@ class RoomSummaryListProcessorTest {
|
|||
assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `PopFront removes an entry at the start of the list`() = runTest {
|
||||
spaceRoomsFlow.value = listOf(
|
||||
aSpaceRoom(roomId = A_ROOM_ID),
|
||||
|
|
@ -134,8 +125,7 @@ class RoomSummaryListProcessorTest {
|
|||
assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID_2)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `Clear removes all the entries`() = runTest {
|
||||
spaceRoomsFlow.value = listOf(
|
||||
aSpaceRoom(roomId = A_ROOM_ID),
|
||||
|
|
@ -148,8 +138,7 @@ class RoomSummaryListProcessorTest {
|
|||
assertThat(spaceRoomsFlow.value).isEmpty()
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `Truncate removes all entries after the provided length`() = runTest {
|
||||
spaceRoomsFlow.value = listOf(
|
||||
aSpaceRoom(roomId = A_ROOM_ID),
|
||||
|
|
@ -164,8 +153,7 @@ class RoomSummaryListProcessorTest {
|
|||
assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `Reset removes all entries and add the provided ones`() = runTest {
|
||||
spaceRoomsFlow.value = listOf(
|
||||
aSpaceRoom(roomId = A_ROOM_ID),
|
||||
|
|
@ -180,8 +168,7 @@ class RoomSummaryListProcessorTest {
|
|||
assertThat(spaceRoomsFlow.value[index].roomId).isEqualTo(A_ROOM_ID_3)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `When there is no replay cache SpaceListUpdateProcessor starts with an empty list`() = runTest {
|
||||
val spaceRoomsSharedFlow = MutableSharedFlow<List<SpaceRoom>>(replay = 1)
|
||||
val processor = createProcessor(
|
||||
|
|
|
|||
|
|
@ -23,15 +23,13 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runCurrent
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import org.matrix.rustcomponents.sdk.SpaceListUpdate
|
||||
import uniffi.matrix_sdk_ui.SpaceRoomListPaginationState
|
||||
import org.matrix.rustcomponents.sdk.SpaceRoomList as InnerSpaceRoomList
|
||||
|
||||
class RustSpaceRoomListTest {
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `paginationStatusFlow emits values`() = runTest {
|
||||
val innerSpaceRoomList = FakeFfiSpaceRoomList(
|
||||
paginationStateResult = { SpaceRoomListPaginationState.Idle(false) }
|
||||
|
|
@ -53,8 +51,7 @@ class RustSpaceRoomListTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `spaceRoomsFlow emits values`() = runTest {
|
||||
val innerSpaceRoomList = FakeFfiSpaceRoomList(
|
||||
paginationStateResult = { SpaceRoomListPaginationState.Idle(false) }
|
||||
|
|
@ -76,8 +73,7 @@ class RustSpaceRoomListTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `paginate invokes paginate on the inner class`() = runTest {
|
||||
val paginateResult = lambdaRecorder<Unit> { }
|
||||
val innerSpaceRoomList = FakeFfiSpaceRoomList(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl.storage
|
||||
|
||||
import org.matrix.rustcomponents.sdk.ClientBuilder
|
||||
|
||||
class FakeSqliteStoreBuilder : SqliteStoreBuilder {
|
||||
override fun passphrase(passphrase: String?): SqliteStoreBuilder = this
|
||||
|
||||
override fun setupClientBuilder(clientBuilder: ClientBuilder): ClientBuilder {
|
||||
return clientBuilder
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.matrix.impl.storage
|
||||
|
||||
import io.element.android.libraries.matrix.impl.paths.SessionPaths
|
||||
|
||||
class FakeSqliteStoreBuilderProvider : SqliteStoreBuilderProvider {
|
||||
override fun provide(sessionPaths: SessionPaths): SqliteStoreBuilder {
|
||||
return FakeSqliteStoreBuilder()
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +21,6 @@ import kotlinx.coroutines.flow.MutableSharedFlow
|
|||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import org.matrix.rustcomponents.sdk.TimelineDiff
|
||||
|
||||
|
|
@ -31,8 +30,7 @@ class MatrixTimelineDiffProcessorTest {
|
|||
private val anEvent = MatrixTimelineItem.Event(A_UNIQUE_ID, anEventTimelineItem())
|
||||
private val anEvent2 = MatrixTimelineItem.Event(A_UNIQUE_ID_2, anEventTimelineItem())
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `Append adds new entries at the end of the list`() = runTest {
|
||||
timelineItems.value = listOf(anEvent)
|
||||
val processor = createMatrixTimelineDiffProcessor(timelineItems)
|
||||
|
|
@ -44,8 +42,7 @@ class MatrixTimelineDiffProcessorTest {
|
|||
)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `PushBack adds a new entry at the end of the list`() = runTest {
|
||||
timelineItems.value = listOf(anEvent)
|
||||
val processor = createMatrixTimelineDiffProcessor(timelineItems)
|
||||
|
|
@ -57,8 +54,7 @@ class MatrixTimelineDiffProcessorTest {
|
|||
)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `PushFront inserts a new entry at the start of the list`() = runTest {
|
||||
timelineItems.value = listOf(anEvent)
|
||||
val processor = createMatrixTimelineDiffProcessor(timelineItems)
|
||||
|
|
@ -70,8 +66,7 @@ class MatrixTimelineDiffProcessorTest {
|
|||
)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `Set replaces an entry at some index`() = runTest {
|
||||
timelineItems.value = listOf(anEvent, anEvent2)
|
||||
val processor = createMatrixTimelineDiffProcessor(timelineItems)
|
||||
|
|
@ -83,8 +78,7 @@ class MatrixTimelineDiffProcessorTest {
|
|||
)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `Insert inserts a new entry at the provided index`() = runTest {
|
||||
timelineItems.value = listOf(anEvent, anEvent2)
|
||||
val processor = createMatrixTimelineDiffProcessor(timelineItems)
|
||||
|
|
@ -97,8 +91,7 @@ class MatrixTimelineDiffProcessorTest {
|
|||
)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `Remove removes an entry at some index`() = runTest {
|
||||
timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2)
|
||||
val processor = createMatrixTimelineDiffProcessor(timelineItems)
|
||||
|
|
@ -110,8 +103,7 @@ class MatrixTimelineDiffProcessorTest {
|
|||
)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `PopBack removes an entry at the end of the list`() = runTest {
|
||||
timelineItems.value = listOf(anEvent, anEvent2)
|
||||
val processor = createMatrixTimelineDiffProcessor(timelineItems)
|
||||
|
|
@ -122,8 +114,7 @@ class MatrixTimelineDiffProcessorTest {
|
|||
)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `PopFront removes an entry at the start of the list`() = runTest {
|
||||
timelineItems.value = listOf(anEvent, anEvent2)
|
||||
val processor = createMatrixTimelineDiffProcessor(timelineItems)
|
||||
|
|
@ -134,8 +125,7 @@ class MatrixTimelineDiffProcessorTest {
|
|||
)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `Clear removes all the entries`() = runTest {
|
||||
timelineItems.value = listOf(anEvent, anEvent2)
|
||||
val processor = createMatrixTimelineDiffProcessor(timelineItems)
|
||||
|
|
@ -143,8 +133,7 @@ class MatrixTimelineDiffProcessorTest {
|
|||
assertThat(timelineItems.value).isEmpty()
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `Truncate removes all entries after the provided length`() = runTest {
|
||||
timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2)
|
||||
val processor = createMatrixTimelineDiffProcessor(timelineItems)
|
||||
|
|
@ -155,8 +144,7 @@ class MatrixTimelineDiffProcessorTest {
|
|||
)
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `Reset removes all entries and add the provided ones`() = runTest {
|
||||
timelineItems.value = listOf(anEvent, MatrixTimelineItem.Other, anEvent2)
|
||||
val processor = createMatrixTimelineDiffProcessor(timelineItems)
|
||||
|
|
|
|||
|
|
@ -30,13 +30,11 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
|
|||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runCurrent
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import org.matrix.rustcomponents.sdk.TimelineDiff
|
||||
import uniffi.matrix_sdk.RoomPaginationStatus
|
||||
import org.matrix.rustcomponents.sdk.Timeline as InnerTimeline
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
class RustTimelineTest {
|
||||
@Test
|
||||
fun `ensure that the timeline emits new loading item when pagination does not bring new events`() = runTest {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@ import kotlinx.coroutines.test.StandardTestDispatcher
|
|||
import kotlinx.coroutines.test.TestScope
|
||||
import kotlinx.coroutines.test.runCurrent
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Ignore
|
||||
import org.junit.Test
|
||||
import org.matrix.rustcomponents.sdk.Timeline
|
||||
import org.matrix.rustcomponents.sdk.TimelineDiff
|
||||
|
|
@ -28,8 +27,7 @@ import uniffi.matrix_sdk_ui.EventItemOrigin
|
|||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
class TimelineItemsSubscriberTest {
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `when timeline emits an empty list of items, the flow must emits an empty list`() = runTest {
|
||||
val timelineItems: MutableSharedFlow<List<MatrixTimelineItem>> =
|
||||
MutableSharedFlow(replay = 1, extraBufferCapacity = Int.MAX_VALUE)
|
||||
|
|
@ -52,8 +50,7 @@ class TimelineItemsSubscriberTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `when timeline emits a non empty list of items, the flow must emits a non empty list`() = runTest {
|
||||
val timelineItems: MutableSharedFlow<List<MatrixTimelineItem>> =
|
||||
MutableSharedFlow(replay = 1, extraBufferCapacity = Int.MAX_VALUE)
|
||||
|
|
@ -76,8 +73,7 @@ class TimelineItemsSubscriberTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `when timeline emits an item with SYNC origin`() = runTest {
|
||||
val timelineItems: MutableSharedFlow<List<MatrixTimelineItem>> =
|
||||
MutableSharedFlow(replay = 1, extraBufferCapacity = Int.MAX_VALUE)
|
||||
|
|
@ -108,8 +104,7 @@ class TimelineItemsSubscriberTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Ignore("JNA direct mapping has broken unit tests with FFI fakes")
|
||||
@Test
|
||||
@Test
|
||||
fun `multiple subscriptions does not have side effect`() = runTest {
|
||||
val timelineItemsSubscriber = createTimelineItemsSubscriber()
|
||||
timelineItemsSubscriber.subscribeIfNeeded()
|
||||
|
|
|
|||
|
|
@ -104,6 +104,7 @@ class FakeMatrixClient(
|
|||
private val getRecentEmojisLambda: () -> Result<List<String>> = { Result.success(emptyList()) },
|
||||
private val addRecentEmojiLambda: (String) -> Result<Unit> = { Result.success(Unit) },
|
||||
private val markRoomAsFullyReadResult: (RoomId, EventId) -> Result<Unit> = { _, _ -> lambdaError() },
|
||||
private val performDatabaseVacuumLambda: () -> Result<Unit> = { lambdaError() },
|
||||
) : MatrixClient {
|
||||
var setDisplayNameCalled: Boolean = false
|
||||
private set
|
||||
|
|
@ -351,4 +352,8 @@ class FakeMatrixClient(
|
|||
override suspend fun markRoomAsFullyRead(roomId: RoomId, eventId: EventId): Result<Unit> {
|
||||
return markRoomAsFullyReadResult(roomId, eventId)
|
||||
}
|
||||
|
||||
override suspend fun performDatabaseVacuum(): Result<Unit> {
|
||||
return performDatabaseVacuumLambda()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,8 +11,9 @@ package io.element.android.libraries.matrix.ui.components
|
|||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.ui.Alignment
|
||||
|
|
@ -20,10 +21,10 @@ import androidx.compose.ui.Modifier
|
|||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.designsystem.atomic.atoms.SelectedIndicatorAtom
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarData
|
||||
import io.element.android.libraries.designsystem.components.avatar.AvatarSize
|
||||
import io.element.android.libraries.designsystem.preview.ElementThemedPreview
|
||||
import io.element.android.libraries.designsystem.theme.components.Checkbox
|
||||
import io.element.android.libraries.designsystem.theme.components.HorizontalDivider
|
||||
import io.element.android.libraries.matrix.ui.model.getAvatarData
|
||||
|
||||
|
|
@ -63,11 +64,12 @@ fun CheckableUserRow(
|
|||
)
|
||||
}
|
||||
}
|
||||
SelectedIndicatorAtom(
|
||||
modifier = Modifier.padding(end = 24.dp),
|
||||
Checkbox(
|
||||
onCheckedChange = onCheckedChange,
|
||||
checked = checked,
|
||||
enabled = enabled,
|
||||
)
|
||||
Spacer(modifier = Modifier.width(4.dp))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ fun SpaceHeaderRootView(
|
|||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||
) {
|
||||
BigIcon(
|
||||
style = BigIcon.Style.Default(CompoundIcons.WorkspaceSolid())
|
||||
style = BigIcon.Style.Default(CompoundIcons.SpaceSolid())
|
||||
)
|
||||
Text(
|
||||
text = stringResource(CommonStrings.screen_space_list_title),
|
||||
|
|
|
|||
|
|
@ -108,7 +108,7 @@ internal fun SpaceInfoRowPreview() = ElementPreview {
|
|||
SpaceInfoRow(
|
||||
leftText = "Element space",
|
||||
rightText = numberOfRooms(16),
|
||||
iconVector = CompoundIcons.Workspace(),
|
||||
iconVector = CompoundIcons.Space(),
|
||||
)
|
||||
SpaceInfoRow(
|
||||
visibility = SpaceRoomVisibility.Private,
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import androidx.compose.foundation.layout.Arrangement
|
|||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -45,8 +44,7 @@ fun UnresolvedUserRow(
|
|||
Row(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.heightIn(min = 56.dp)
|
||||
.padding(start = 16.dp, top = 8.dp, end = 16.dp, bottom = 8.dp),
|
||||
.padding(start = 16.dp, top = 12.dp, end = 16.dp, bottom = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Avatar(
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ package io.element.android.libraries.matrix.ui.components
|
|||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
|
|
@ -37,8 +36,7 @@ internal fun UserRow(
|
|||
Row(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.heightIn(min = 56.dp)
|
||||
.padding(start = 16.dp, top = 4.dp, end = 16.dp, bottom = 4.dp),
|
||||
.padding(start = 16.dp, top = 12.dp, end = 16.dp, bottom = 12.dp),
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Avatar(
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ val SpaceRoomVisibility.icon: ImageVector
|
|||
return when (this) {
|
||||
SpaceRoomVisibility.Private -> CompoundIcons.LockSolid()
|
||||
SpaceRoomVisibility.Public -> CompoundIcons.Public()
|
||||
SpaceRoomVisibility.Restricted -> CompoundIcons.Workspace()
|
||||
SpaceRoomVisibility.Restricted -> CompoundIcons.Space()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue