Merge branch 'develop' into feature/bma/scroll-to-unread-messages
This commit is contained in:
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2026 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.system
|
||||
|
||||
import android.content.Context
|
||||
import dev.zacsweers.metro.Inject
|
||||
import io.element.android.libraries.di.annotations.ApplicationContext
|
||||
|
||||
private const val VULKAN_VERSION_1_0 = 0x400003
|
||||
|
||||
/**
|
||||
* Checks if the device supports Vulkan 1.0.
|
||||
*
|
||||
* This is needed for the location screens that contain maps using MapLibre UI components.
|
||||
*
|
||||
* Needed until https://github.com/maplibre/maplibre-native/issues/3079 is resolved and we can automatically choose between OpenGL and Vulkan renderers,
|
||||
* or no devices support OpenGL anymore.
|
||||
*/
|
||||
@Inject
|
||||
class DeviceHasVulkanSupport(
|
||||
@ApplicationContext private val context: Context,
|
||||
) {
|
||||
operator fun invoke(): Boolean {
|
||||
return context.packageManager.hasSystemFeature("android.hardware.vulkan.version", VULKAN_VERSION_1_0)
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:7901fea2f578c8ed796160c9c08f417c61f4fb21580f958844fdf0cb794adf8a
|
||||
size 239731
|
||||
oid sha256:78386a58e91be3213485f60909ec8d83cd535aabcec775aadf7b36e77d8542f0
|
||||
size 245853
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:245f012d419817f6557d92a71729b3b70092f24f0eba37f2f1fc431ad27592be
|
||||
size 252969
|
||||
oid sha256:477ab18ffa1ca81ca5e4c9f30f4466b19e14fcaddf641fc860c6be19a0e33d4f
|
||||
size 259185
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:2d15c52b21cc279d306fa187cd0c318820109b5ec66270e6447e1b02e800eeba
|
||||
size 254206
|
||||
oid sha256:7edeebf9876aecd262fceb7d55a4bfd30a859a69b708af8dd4538ffc0f9be419
|
||||
size 260400
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:85ef188fa3a27e42f4beafc899c1f3e7e8bcfad980ed76af6a03f76d70d6a511
|
||||
size 93807
|
||||
oid sha256:cc6cc2d2e89c7460217c2075046e41bef727407ee422dcdea23f161f48441904
|
||||
size 97346
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f6e38386e95dc0c50384f06fca122ce14851ceff8ffc7865e394c1b4fccc5db6
|
||||
size 100555
|
||||
oid sha256:4df16aee4a3a8b10c33e9724904c72b8dc502725204d2f86cf62cc381b35f4a1
|
||||
size 103870
|
||||
|
||||
File diff suppressed because one or more lines are too long
+45
@@ -130,6 +130,9 @@ object CompoundIcons {
|
||||
@Composable fun Collapse(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_collapse)
|
||||
}
|
||||
@Composable fun CollapseAll(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_collapse_all)
|
||||
}
|
||||
@Composable fun Company(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_company)
|
||||
}
|
||||
@@ -142,6 +145,9 @@ object CompoundIcons {
|
||||
@Composable fun Copy(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_copy)
|
||||
}
|
||||
@Composable fun Crop(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_crop)
|
||||
}
|
||||
@Composable fun DarkMode(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_dark_mode)
|
||||
}
|
||||
@@ -202,6 +208,9 @@ object CompoundIcons {
|
||||
@Composable fun Expand(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_expand)
|
||||
}
|
||||
@Composable fun ExpandAll(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_expand_all)
|
||||
}
|
||||
@Composable fun Explore(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_explore)
|
||||
}
|
||||
@@ -229,6 +238,15 @@ object CompoundIcons {
|
||||
@Composable fun Filter(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_filter)
|
||||
}
|
||||
@Composable fun FlipHorizontal(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_flip_horizontal)
|
||||
}
|
||||
@Composable fun FlipVertical(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_flip_vertical)
|
||||
}
|
||||
@Composable fun Folder(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_folder)
|
||||
}
|
||||
@Composable fun Forward(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_forward)
|
||||
}
|
||||
@@ -496,6 +514,12 @@ object CompoundIcons {
|
||||
@Composable fun RotateRight(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_rotate_right)
|
||||
}
|
||||
@Composable fun Save(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_save)
|
||||
}
|
||||
@Composable fun SaveSolid(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_save_solid)
|
||||
}
|
||||
@Composable fun Search(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_search)
|
||||
}
|
||||
@@ -607,6 +631,9 @@ object CompoundIcons {
|
||||
@Composable fun Unpin(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_unpin)
|
||||
}
|
||||
@Composable fun Unsave(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_unsave)
|
||||
}
|
||||
@Composable fun User(): ImageVector {
|
||||
return ImageVector.vectorResource(R.drawable.ic_compound_user)
|
||||
}
|
||||
@@ -735,10 +762,12 @@ object CompoundIcons {
|
||||
CloudSolid(),
|
||||
Code(),
|
||||
Collapse(),
|
||||
CollapseAll(),
|
||||
Company(),
|
||||
Compose(),
|
||||
Computer(),
|
||||
Copy(),
|
||||
Crop(),
|
||||
DarkMode(),
|
||||
Delete(),
|
||||
DevicePasskey(),
|
||||
@@ -759,6 +788,7 @@ object CompoundIcons {
|
||||
ErrorSolid(),
|
||||
ExitFullScreen(),
|
||||
Expand(),
|
||||
ExpandAll(),
|
||||
Explore(),
|
||||
ExportArchive(),
|
||||
Extensions(),
|
||||
@@ -768,6 +798,9 @@ object CompoundIcons {
|
||||
FileError(),
|
||||
Files(),
|
||||
Filter(),
|
||||
FlipHorizontal(),
|
||||
FlipVertical(),
|
||||
Folder(),
|
||||
Forward(),
|
||||
FullScreen(),
|
||||
Grid(),
|
||||
@@ -857,6 +890,8 @@ object CompoundIcons {
|
||||
Room(),
|
||||
RotateLeft(),
|
||||
RotateRight(),
|
||||
Save(),
|
||||
SaveSolid(),
|
||||
Search(),
|
||||
Section(),
|
||||
Send(),
|
||||
@@ -894,6 +929,7 @@ object CompoundIcons {
|
||||
Unknown(),
|
||||
UnknownSolid(),
|
||||
Unpin(),
|
||||
Unsave(),
|
||||
User(),
|
||||
UserAdd(),
|
||||
UserAddSolid(),
|
||||
@@ -963,10 +999,12 @@ object CompoundIcons {
|
||||
R.drawable.ic_compound_cloud_solid,
|
||||
R.drawable.ic_compound_code,
|
||||
R.drawable.ic_compound_collapse,
|
||||
R.drawable.ic_compound_collapse_all,
|
||||
R.drawable.ic_compound_company,
|
||||
R.drawable.ic_compound_compose,
|
||||
R.drawable.ic_compound_computer,
|
||||
R.drawable.ic_compound_copy,
|
||||
R.drawable.ic_compound_crop,
|
||||
R.drawable.ic_compound_dark_mode,
|
||||
R.drawable.ic_compound_delete,
|
||||
R.drawable.ic_compound_device_passkey,
|
||||
@@ -987,6 +1025,7 @@ object CompoundIcons {
|
||||
R.drawable.ic_compound_error_solid,
|
||||
R.drawable.ic_compound_exit_full_screen,
|
||||
R.drawable.ic_compound_expand,
|
||||
R.drawable.ic_compound_expand_all,
|
||||
R.drawable.ic_compound_explore,
|
||||
R.drawable.ic_compound_export_archive,
|
||||
R.drawable.ic_compound_extensions,
|
||||
@@ -996,6 +1035,9 @@ object CompoundIcons {
|
||||
R.drawable.ic_compound_file_error,
|
||||
R.drawable.ic_compound_files,
|
||||
R.drawable.ic_compound_filter,
|
||||
R.drawable.ic_compound_flip_horizontal,
|
||||
R.drawable.ic_compound_flip_vertical,
|
||||
R.drawable.ic_compound_folder,
|
||||
R.drawable.ic_compound_forward,
|
||||
R.drawable.ic_compound_full_screen,
|
||||
R.drawable.ic_compound_grid,
|
||||
@@ -1085,6 +1127,8 @@ object CompoundIcons {
|
||||
R.drawable.ic_compound_room,
|
||||
R.drawable.ic_compound_rotate_left,
|
||||
R.drawable.ic_compound_rotate_right,
|
||||
R.drawable.ic_compound_save,
|
||||
R.drawable.ic_compound_save_solid,
|
||||
R.drawable.ic_compound_search,
|
||||
R.drawable.ic_compound_section,
|
||||
R.drawable.ic_compound_send,
|
||||
@@ -1122,6 +1166,7 @@ object CompoundIcons {
|
||||
R.drawable.ic_compound_unknown,
|
||||
R.drawable.ic_compound_unknown_solid,
|
||||
R.drawable.ic_compound_unpin,
|
||||
R.drawable.ic_compound_unsave,
|
||||
R.drawable.ic_compound_user,
|
||||
R.drawable.ic_compound_user_add,
|
||||
R.drawable.ic_compound_user_add_solid,
|
||||
|
||||
+2
@@ -175,6 +175,8 @@ data class SemanticColors(
|
||||
val iconTertiaryAlpha: Color,
|
||||
/** Used to separate core sections of the UI as well as containers */
|
||||
val separatorPrimary: Color,
|
||||
/** Secondary shade for separating sections of components or list items */
|
||||
val separatorSecondary: Color,
|
||||
/** Accent text colour for plain actions. */
|
||||
val textActionAccent: Color,
|
||||
/** Default text colour for plain actions. */
|
||||
|
||||
+1
@@ -103,6 +103,7 @@ val compoundColorsDark = SemanticColors(
|
||||
iconTertiary = DarkColorTokens.colorGray800,
|
||||
iconTertiaryAlpha = DarkColorTokens.colorAlphaGray800,
|
||||
separatorPrimary = DarkColorTokens.colorGray400,
|
||||
separatorSecondary = DarkColorTokens.colorGray300,
|
||||
textActionAccent = DarkColorTokens.colorGreen900,
|
||||
textActionPrimary = DarkColorTokens.colorGray1400,
|
||||
textBadgeAccent = DarkColorTokens.colorGreen1100,
|
||||
|
||||
+1
@@ -103,6 +103,7 @@ val compoundColorsHcDark = SemanticColors(
|
||||
iconTertiary = DarkHcColorTokens.colorGray800,
|
||||
iconTertiaryAlpha = DarkHcColorTokens.colorAlphaGray800,
|
||||
separatorPrimary = DarkHcColorTokens.colorGray400,
|
||||
separatorSecondary = DarkHcColorTokens.colorGray300,
|
||||
textActionAccent = DarkHcColorTokens.colorGreen900,
|
||||
textActionPrimary = DarkHcColorTokens.colorGray1400,
|
||||
textBadgeAccent = DarkHcColorTokens.colorGreen1100,
|
||||
|
||||
+1
@@ -103,6 +103,7 @@ val compoundColorsLight = SemanticColors(
|
||||
iconTertiary = LightColorTokens.colorGray800,
|
||||
iconTertiaryAlpha = LightColorTokens.colorAlphaGray800,
|
||||
separatorPrimary = LightColorTokens.colorGray400,
|
||||
separatorSecondary = LightColorTokens.colorGray300,
|
||||
textActionAccent = LightColorTokens.colorGreen900,
|
||||
textActionPrimary = LightColorTokens.colorGray1400,
|
||||
textBadgeAccent = LightColorTokens.colorGreen1100,
|
||||
|
||||
+1
@@ -103,6 +103,7 @@ val compoundColorsHcLight = SemanticColors(
|
||||
iconTertiary = LightHcColorTokens.colorGray800,
|
||||
iconTertiaryAlpha = LightHcColorTokens.colorAlphaGray800,
|
||||
separatorPrimary = LightHcColorTokens.colorGray400,
|
||||
separatorSecondary = LightHcColorTokens.colorGray300,
|
||||
textActionAccent = LightHcColorTokens.colorGreen900,
|
||||
textActionPrimary = LightHcColorTokens.colorGray1400,
|
||||
textBadgeAccent = LightHcColorTokens.colorGreen1100,
|
||||
|
||||
@@ -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="m12,16.975 l-3.9,3.9a0.95,0.95 0,0 1,-0.7 0.275,0.95 0.95,0 0,1 -0.7,-0.275 0.95,0.95 0,0 1,-0.275 -0.7q0,-0.425 0.275,-0.7l3.875,-3.875q0.575,-0.575 1.425,-0.575t1.425,0.575l3.875,3.875a0.95,0.95 0,0 1,0.275 0.7,0.95 0.95,0 0,1 -0.275,0.7 0.95,0.95 0,0 1,-0.7 0.275,0.95 0.95,0 0,1 -0.7,-0.275zM12,7.175 L15.9,3.275A0.95,0.95 0,0 1,16.6 3q0.425,0 0.7,0.275a0.95,0.95 0,0 1,0.275 0.7,0.95 0.95,0 0,1 -0.275,0.7L13.425,8.55q-0.575,0.575 -1.425,0.575t-1.425,-0.575L6.7,4.675a0.95,0.95 0,0 1,-0.275 -0.7q0,-0.425 0.275,-0.7A0.95,0.95 0,0 1,7.4 3q0.425,0 0.7,0.275z"
|
||||
android:fillColor="#FF000000"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,13 @@
|
||||
<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,4a1,1 0,0 0,-1 1v2H3a1,1 0,1 0,0 2h2v8a3,3 0,0 0,3 3h8v2a1,1 0,0 0,2 0v-2h2a1,1 0,1 0,0 -2h-2v-8a3,3 0,0 0,-3 -3H7V5a1,1 0,0 0,-1 -1m9,5a1,1 0,0 1,1 1v8H8a1,1 0,0 1,-1 -1V9z"
|
||||
android:fillColor="#FF000000"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M15.707,0.293a1,1 0,0 0,-1.414 0l-2,2a1,1 0,0 0,0 1.414l2,2a1,1 0,1 0,1.414 -1.414l-0.275,-0.276A6,6 0,0 1,21 10a1,1 0,1 0,2 0,8 8,0 0,0 -7.596,-7.99l0.303,-0.303a1,1 0,0 0,0 -1.414"
|
||||
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="m12,19.2 l3.9,-3.9a0.95,0.95 0,0 1,0.7 -0.275q0.425,0 0.7,0.275a0.95,0.95 0,0 1,0.275 0.7,0.95 0.95,0 0,1 -0.275,0.7l-3.875,3.875q-0.575,0.575 -1.425,0.575t-1.425,-0.575L6.7,16.7a0.95,0.95 0,0 1,-0.275 -0.7q0,-0.425 0.275,-0.7a0.95,0.95 0,0 1,0.7 -0.275q0.425,0 0.7,0.275zM12,4.95 L8.1,8.85a0.95,0.95 0,0 1,-0.7 0.275,0.95 0.95,0 0,1 -0.7,-0.275 0.95,0.95 0,0 1,-0.275 -0.7q0,-0.425 0.275,-0.7l3.875,-3.875Q11.15,3 12,3t1.425,0.575L17.3,7.45a0.95,0.95 0,0 1,0.275 0.7,0.95 0.95,0 0,1 -0.275,0.7 0.95,0.95 0,0 1,-0.7 0.275,0.95 0.95,0 0,1 -0.7,-0.275z"
|
||||
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="M12,2a1,1 0,0 1,1 1v18a1,1 0,1 1,-2 0L11,3a1,1 0,0 1,1 -1M2,8a1,1 0,0 1,1.6 -0.8l5.334,4a1,1 0,0 1,0 1.6l-5.334,4A1,1 0,0 1,2 16zM20.4,7.2A1,1 0,0 1,22 8v8a1,1 0,0 1,-1.6 0.8l-5.334,-4a1,1 0,0 1,0 -1.6z"
|
||||
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="M11.2,15.066a1,1 0,0 1,1.6 0l4,5.334A1,1 0,0 1,16 22L8,22a1,1 0,0 1,-0.8 -1.6zM21,11a1,1 0,1 1,0 2L3,13a1,1 0,1 1,0 -2zM16,2a1,1 0,0 1,0.8 1.6l-4,5.334a1,1 0,0 1,-1.6 0L7.2,3.6A1,1 0,0 1,8 2z"
|
||||
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="M9.837,17.869a4,4 0,0 1,4.326 0L18,20.336V4H6v16.336zM20,20.336c0,1.582 -1.751,2.538 -3.082,1.682l-3.836,-2.466a2,2 0,0 0,-2.164 0l-3.836,2.466 -0.126,0.076C5.643,22.814 4,21.869 4,20.336V4a2,2 0,0 1,2 -2h12a2,2 0,0 1,2 2z"
|
||||
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="M18,2H6a2,2 0,0 0,-2 2v16.336c0,1.583 1.75,2.538 3.082,1.683l3.836,-2.467a2,2 0,0 1,2.164 0l3.836,2.467c1.331,0.855 3.082,-0.1 3.082,-1.683V4a2,2 0,0 0,-2 -2"
|
||||
android:fillColor="#FF000000"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,13 @@
|
||||
<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.503,2.083a1,1 0,0 1,1.414 0l17,17a1,1 0,1 1,-1.414 1.414L20,19.994v0.342c0,1.582 -1.75,2.538 -3.082,1.683l-3.836,-2.467a2,2 0,0 0,-2.164 0l-3.836,2.467 -0.126,0.075C5.643,22.814 4,21.869 4,20.336V3.994l-0.497,-0.497a1,1 0,0 1,0 -1.414M6,20.336l3.837,-2.467a4,4 0,0 1,4.326 0L18,20.336v-2.342l-12,-12z"
|
||||
android:fillColor="#FF000000"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M18,2a2,2 0,0 1,2 2v10.35l-2,-2V4H9.65l-2,-2z"
|
||||
android:fillColor="#FF000000"/>
|
||||
</vector>
|
||||
+8
-2
@@ -18,6 +18,7 @@ import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.rememberTextMeasurer
|
||||
import androidx.compose.ui.unit.dp
|
||||
@@ -37,13 +38,18 @@ private const val MAX_COUNT_STRING = "+$MAX_COUNT"
|
||||
* @param count The number to display. If the number is greater than [MAX_COUNT], the counter will display [MAX_COUNT_STRING].
|
||||
* If the number is less than 1, the counter will not be displayed.
|
||||
* @param modifier The modifier to apply to this layout.
|
||||
* @param containerColor The background color of the counter. When null, uses [isCritical] to pick a default.
|
||||
* @param contentColor The text color inside the counter. When null, uses [textOnSolidPrimary].
|
||||
* @param textStyle The style to apply to the text inside the counter.
|
||||
* @param isCritical If true, the counter will use a critical color scheme, otherwise it will use an accent color scheme.
|
||||
* Only used when [containerColor] is null.
|
||||
*/
|
||||
@Composable
|
||||
fun CounterAtom(
|
||||
count: Int,
|
||||
modifier: Modifier = Modifier,
|
||||
containerColor: Color? = null,
|
||||
contentColor: Color? = null,
|
||||
textStyle: TextStyle = CounterAtomDefaults.textStyle,
|
||||
isCritical: Boolean = false,
|
||||
) {
|
||||
@@ -65,7 +71,7 @@ fun CounterAtom(
|
||||
.size(squareSize.toDp() + 1.dp)
|
||||
.clip(CircleShape)
|
||||
.background(
|
||||
if (isCritical) {
|
||||
containerColor ?: if (isCritical) {
|
||||
ElementTheme.colors.iconCriticalPrimary
|
||||
} else {
|
||||
ElementTheme.colors.iconAccentPrimary
|
||||
@@ -76,7 +82,7 @@ fun CounterAtom(
|
||||
modifier = Modifier.align(Alignment.Center),
|
||||
text = countAsText,
|
||||
style = textStyle,
|
||||
color = ElementTheme.colors.textOnSolidPrimary,
|
||||
color = contentColor ?: ElementTheme.colors.textOnSolidPrimary,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+26
-10
@@ -12,6 +12,7 @@ import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.runtime.Composable
|
||||
@@ -31,21 +32,36 @@ import io.element.android.libraries.designsystem.theme.unreadIndicator
|
||||
fun UnreadIndicatorAtom(
|
||||
modifier: Modifier = Modifier,
|
||||
size: Dp = 12.dp,
|
||||
count: Long? = null,
|
||||
color: Color = ElementTheme.colors.unreadIndicator,
|
||||
isVisible: Boolean = true,
|
||||
contentDescription: String? = null,
|
||||
border: BorderStroke? = null,
|
||||
) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.semantics {
|
||||
contentDescription?.let { this.contentDescription = it }
|
||||
}
|
||||
.size(size)
|
||||
.clip(CircleShape)
|
||||
.background(if (isVisible) color else Color.Transparent)
|
||||
.then(if (border != null) Modifier.border(border, CircleShape) else Modifier)
|
||||
)
|
||||
when {
|
||||
!isVisible -> Spacer(modifier = modifier.size(size))
|
||||
count != null && count >= 1 -> CounterAtom(
|
||||
count = count.toInt(),
|
||||
modifier = modifier
|
||||
.semantics {
|
||||
contentDescription?.let { this.contentDescription = it }
|
||||
}
|
||||
.then(if (border != null) Modifier.border(border, CircleShape) else Modifier),
|
||||
containerColor = color,
|
||||
contentColor = ElementTheme.colors.bgCanvasDefault,
|
||||
textStyle = ElementTheme.typography.fontBodySmMedium,
|
||||
)
|
||||
else -> Box(
|
||||
modifier = modifier
|
||||
.semantics {
|
||||
contentDescription?.let { this.contentDescription = it }
|
||||
}
|
||||
.size(size)
|
||||
.clip(CircleShape)
|
||||
.background(color)
|
||||
.then(if (border != null) Modifier.border(border, CircleShape) else Modifier),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewsDayNight
|
||||
|
||||
+7
-7
@@ -108,13 +108,6 @@ enum class FeatureFlags(
|
||||
defaultValue = { true },
|
||||
isFinished = false,
|
||||
),
|
||||
FloatingDateBadge(
|
||||
key = "feature.floating_date_badge",
|
||||
title = "Display sticky date headers in the timeline",
|
||||
description = "When scrolling, a sticky date badge will be displayed so you can easily know on which date the messages you're seeing were sent.",
|
||||
defaultValue = { false },
|
||||
isFinished = false,
|
||||
),
|
||||
JumpToUnread(
|
||||
key = "feature.jump_to_unread",
|
||||
title = "Jump to unread messages",
|
||||
@@ -145,4 +138,11 @@ enum class FeatureFlags(
|
||||
defaultValue = { false },
|
||||
isFinished = false,
|
||||
),
|
||||
UnreadIndicatorCount(
|
||||
key = "feature.unread_indicator_count",
|
||||
title = "Unread indicator count",
|
||||
description = "Show the number of unread messages on the unread indicator in the room list.",
|
||||
defaultValue = { false },
|
||||
isFinished = false,
|
||||
),
|
||||
}
|
||||
|
||||
+7
@@ -212,4 +212,11 @@ interface JoinedRoom : BaseRoom {
|
||||
* @return Result indicating success or failure.
|
||||
*/
|
||||
suspend fun sendLiveLocation(geoUri: String): Result<Unit>
|
||||
|
||||
/**
|
||||
* Sets the display name of the current user within this room.
|
||||
* This is different from the global setDisplayName which updates
|
||||
* the user's display name across all of their rooms.
|
||||
*/
|
||||
suspend fun setOwnMemberDisplayName(displayName: String): Result<Unit>
|
||||
}
|
||||
|
||||
+6
@@ -548,6 +548,12 @@ class JoinedRustRoom(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun setOwnMemberDisplayName(displayName: String): Result<Unit> = withContext(roomDispatcher) {
|
||||
runCatchingExceptions {
|
||||
innerRoom.setOwnMemberDisplayName(displayName)
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() = destroy()
|
||||
|
||||
override fun destroy() {
|
||||
|
||||
+5
@@ -92,6 +92,7 @@ class FakeJoinedRoom(
|
||||
private val startLiveLocationShareResult: (Long) -> Result<EventId> = { lambdaError() },
|
||||
private val stopLiveLocationShareResult: () -> Result<Unit> = { lambdaError() },
|
||||
private val sendLiveLocationResult: (String) -> Result<Unit> = { lambdaError() },
|
||||
private val setOwnMemberDisplayNameResult: (String) -> Result<Unit> = { lambdaError() },
|
||||
) : JoinedRoom, BaseRoom by baseRoom {
|
||||
private val sendQueueUpdates = MutableSharedFlow<SendQueueUpdate>(extraBufferCapacity = 10)
|
||||
|
||||
@@ -255,6 +256,10 @@ class FakeJoinedRoom(
|
||||
sendLiveLocationResult(geoUri)
|
||||
}
|
||||
|
||||
override suspend fun setOwnMemberDisplayName(displayName: String): Result<Unit> = simulateLongTask {
|
||||
setOwnMemberDisplayNameResult(displayName)
|
||||
}
|
||||
|
||||
private suspend fun simulateSendMediaProgress(progressCallback: ProgressCallback?) {
|
||||
progressCallbackValues.forEach { (current, total) ->
|
||||
progressCallback?.onProgress(current, total)
|
||||
|
||||
+3
-4
@@ -13,6 +13,7 @@ import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.room.BaseRoom
|
||||
@@ -42,10 +43,8 @@ fun getRoomMemberAsState(roomMembersState: RoomMembersState, userId: UserId): St
|
||||
@Composable
|
||||
fun BaseRoom.getDirectRoomMember(roomMembersState: RoomMembersState): State<RoomMember?> {
|
||||
val roomInfo by roomInfoFlow.collectAsState()
|
||||
return remember {
|
||||
derivedStateOf {
|
||||
roomMembersState.getDirectRoomMember(roomInfo, sessionId)
|
||||
}
|
||||
return remember(roomInfo.isDm) {
|
||||
mutableStateOf(roomMembersState.getDirectRoomMember(roomInfo, sessionId))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,5 +3,7 @@
|
||||
<string name="screen_bottom_sheet_create_dm_confirmation_button_title">"초대장 보내기"</string>
|
||||
<string name="screen_bottom_sheet_create_dm_message">"%1$s 와 채팅을 시작하시겠습니까?"</string>
|
||||
<string name="screen_bottom_sheet_create_dm_title">"초대장을 보내시겠습니까?"</string>
|
||||
<string name="screen_bottom_sheet_create_dm_unknown_user_content">"이 사용자와의 대화 내역이 없습니다. 계속하려면 먼저 초대를 확인해 주세요."</string>
|
||||
<string name="screen_bottom_sheet_create_dm_unknown_user_title">"이 사용자와 대화를 시작하시겠습니까?"</string>
|
||||
<string name="screen_invites_invited_you">"%1$s (%2$s) 당신을 초대했습니다"</string>
|
||||
</resources>
|
||||
|
||||
+16
@@ -33,10 +33,13 @@ import androidx.compose.ui.platform.LocalInspectionMode
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.media3.common.MediaItem
|
||||
import androidx.media3.common.ParserException
|
||||
import androidx.media3.common.PlaybackException
|
||||
import androidx.media3.common.Player
|
||||
import androidx.media3.common.Player.STATE_READY
|
||||
import androidx.media3.common.Timeline
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.exoplayer.ExoPlaybackException
|
||||
import androidx.media3.exoplayer.ExoPlayer
|
||||
import androidx.media3.ui.AspectRatioFrameLayout
|
||||
import androidx.media3.ui.PlayerView
|
||||
@@ -158,6 +161,19 @@ private fun ExoPlayerMediaVideoView(
|
||||
isReady = playbackState == STATE_READY,
|
||||
)
|
||||
}
|
||||
|
||||
override fun onPlayerError(error: PlaybackException) {
|
||||
super.onPlayerError(error)
|
||||
Timber.w(error, "Player error")
|
||||
if (error is ExoPlaybackException && error.cause is ParserException) {
|
||||
// The cause can be:
|
||||
// androidx.media3.common.ParserException: Invalid NAL length {contentIsMalformed=true, dataType=1}
|
||||
// This has been observed when the user wants to play a second time a recorded video.
|
||||
// Workaround the issue #6956, start the playback again
|
||||
exoPlayer.prepare()
|
||||
exoPlayer.play()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
<string name="screen_media_details_filename">"파일 명"</string>
|
||||
<string name="screen_media_details_no_more_files_to_show">"더 이상 표시할 파일이 없습니다"</string>
|
||||
<string name="screen_media_details_no_more_media_to_show">"더 이상 보여줄 미디어가 없습니다"</string>
|
||||
<string name="screen_media_details_title">"파일 정보"</string>
|
||||
<string name="screen_media_details_uploaded_by">"에 의해 업로드됨"</string>
|
||||
<string name="screen_media_details_uploaded_on">"에 업로드됨"</string>
|
||||
</resources>
|
||||
|
||||
+3
-2
@@ -29,8 +29,9 @@ class DefaultUnifiedPushGatewayUrlResolver(
|
||||
): String {
|
||||
return when (gatewayResult) {
|
||||
is UnifiedPushGatewayResolverResult.Error -> {
|
||||
// Use previous gateway if any, or the provided one
|
||||
unifiedPushStore.getPushGateway(instance) ?: gatewayResult.gateway
|
||||
// Use previous gateway if any, or the default one
|
||||
unifiedPushStore.getPushGateway(instance)
|
||||
?: defaultPushGatewayHttpUrlProvider.provide()
|
||||
}
|
||||
UnifiedPushGatewayResolverResult.ErrorInvalidUrl,
|
||||
UnifiedPushGatewayResolverResult.NoMatrixGateway -> {
|
||||
|
||||
+2
-2
@@ -60,7 +60,7 @@ class DefaultUnifiedPushGatewayUrlResolverTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `resolve Error returns the url if no current url is available`() {
|
||||
fun `resolve Error returns the default gateway url if no current url is available`() {
|
||||
val sut = createDefaultUnifiedPushGatewayUrlResolver(
|
||||
unifiedPushStore = FakeUnifiedPushStore(
|
||||
getPushGatewayResult = { instance ->
|
||||
@@ -73,7 +73,7 @@ class DefaultUnifiedPushGatewayUrlResolverTest {
|
||||
gatewayResult = UnifiedPushGatewayResolverResult.Error("aUrl"),
|
||||
instance = "instance",
|
||||
)
|
||||
assertThat(result).isEqualTo("aUrl")
|
||||
assertThat(result).isEqualTo(FakeDefaultPushGatewayHttpUrlProvider().provide())
|
||||
}
|
||||
|
||||
private fun createDefaultUnifiedPushGatewayUrlResolver(
|
||||
|
||||
+1
-1
@@ -109,7 +109,7 @@ enum class Command(
|
||||
parameters = "<display-name>",
|
||||
description = R.string.slash_command_description_nick_for_room,
|
||||
isAllowedInThread = false,
|
||||
isSupported = false,
|
||||
isSupported = true,
|
||||
),
|
||||
ROOM_AVATAR(
|
||||
command = "/roomavatar",
|
||||
|
||||
+3
-3
@@ -47,7 +47,7 @@ class CommandExecutor(
|
||||
is SlashCommand.ChangeAvatar -> changeAvatar()
|
||||
is SlashCommand.ChangeAvatarForRoom -> changeAvatarForRoom()
|
||||
is SlashCommand.ChangeDisplayName -> changeDisplayName(slashCommand)
|
||||
is SlashCommand.ChangeDisplayNameForRoom -> changeDisplayNameForRoom()
|
||||
is SlashCommand.ChangeDisplayNameForRoom -> changeDisplayNameForRoom(slashCommand)
|
||||
is SlashCommand.ChangeRoomAvatar -> changeRoomAvatar()
|
||||
is SlashCommand.ChangeRoomName -> changeRoomName(slashCommand)
|
||||
is SlashCommand.ChangeTopic -> changeTopic(slashCommand)
|
||||
@@ -171,8 +171,8 @@ class CommandExecutor(
|
||||
return Result.failure(Exception("Not yet implemented"))
|
||||
}
|
||||
|
||||
private fun changeDisplayNameForRoom(): Result<Unit> {
|
||||
return Result.failure(Exception("Not yet implemented"))
|
||||
private suspend fun changeDisplayNameForRoom(slashCommand: SlashCommand.ChangeDisplayNameForRoom): Result<Unit> {
|
||||
return joinedRoom.setOwnMemberDisplayName(slashCommand.displayName)
|
||||
}
|
||||
|
||||
private suspend fun changeDisplayName(slashCommand: SlashCommand.ChangeDisplayName): Result<Unit> {
|
||||
|
||||
+12
-5
@@ -14,7 +14,6 @@ import io.element.android.libraries.matrix.api.timeline.MsgType
|
||||
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
|
||||
import io.element.android.libraries.matrix.test.A_MESSAGE
|
||||
import io.element.android.libraries.matrix.test.A_USER_ID
|
||||
import io.element.android.libraries.matrix.test.A_USER_NAME
|
||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||
import io.element.android.libraries.matrix.test.room.FakeBaseRoom
|
||||
import io.element.android.libraries.matrix.test.room.FakeJoinedRoom
|
||||
@@ -185,10 +184,18 @@ class CommandExecutorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `change display name for room is not supported`() = runTest {
|
||||
val sut = createCommandExecutor()
|
||||
val res = sut.proceedAdmin(SlashCommand.ChangeDisplayNameForRoom(A_USER_NAME))
|
||||
assertThat(res.isFailure).isTrue()
|
||||
fun `change display name for room delegates to joined room`() = runTest {
|
||||
var capturedDisplayName: String? = null
|
||||
val joinedRoom = FakeJoinedRoom(
|
||||
setOwnMemberDisplayNameResult = { displayName ->
|
||||
capturedDisplayName = displayName
|
||||
Result.success(Unit)
|
||||
}
|
||||
)
|
||||
val sut = createCommandExecutor(joinedRoom = joinedRoom)
|
||||
val res = sut.proceedAdmin(SlashCommand.ChangeDisplayNameForRoom("room nick"))
|
||||
assertThat(res.isSuccess).isTrue()
|
||||
assertThat(capturedDisplayName).isEqualTo("room nick")
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -50,12 +50,15 @@
|
||||
<string name="a11y_room_avatar">"Avatar místnosti"</string>
|
||||
<string name="a11y_send_files">"Odeslat soubory"</string>
|
||||
<string name="a11y_sender_location">"Poloha odesílatele"</string>
|
||||
<string name="a11y_sent_by_sender_at_date">"Odesláno %1$s v %2$s"</string>
|
||||
<string name="a11y_session_verification_time_limited_action_required">"Vyžaduje se časově omezená akce, na ověření máte jednu minutu"</string>
|
||||
<string name="a11y_settings_with_required_action">"Nastavení, vyžaduje akci"</string>
|
||||
<string name="a11y_show_password">"Zobrazit heslo"</string>
|
||||
<string name="a11y_start_call">"Zahájit hovor"</string>
|
||||
<string name="a11y_start_video_call">"Zahájit videohovor"</string>
|
||||
<string name="a11y_start_voice_call">"Zahájit hlasový hovor"</string>
|
||||
<string name="a11y_thread_in_room">"Vlákno v %1$s"</string>
|
||||
<string name="a11y_threads_in_room">"Vlákna v %1$s"</string>
|
||||
<string name="a11y_tombstoned_room">"Místnost s náhrobkem"</string>
|
||||
<string name="a11y_user_avatar">"Avatar uživatele"</string>
|
||||
<string name="a11y_user_menu">"Uživatelské menu"</string>
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
<string name="a11y_session_verification_time_limited_action_required">"Απαιτείται ενέργεια περιορισμένης χρονικής διάρκειας, έχετε ένα λεπτό για επαλήθευση."</string>
|
||||
<string name="a11y_show_password">"Εμφάνιση κωδικού πρόσβασης"</string>
|
||||
<string name="a11y_start_call">"Ξεκίνησε μια κλήση"</string>
|
||||
<string name="a11y_start_video_call">"Ξεκινήστε μια βιντεοκλήση"</string>
|
||||
<string name="a11y_start_voice_call">"Έναρξη φωνητικής κλήσης"</string>
|
||||
<string name="a11y_tombstoned_room">"Θαμένη αίθουσα"</string>
|
||||
<string name="a11y_user_avatar">"Άβαταρ χρήστη"</string>
|
||||
|
||||
@@ -545,4 +545,6 @@ Kas sa oled kindel, et soovid jätkata?"</string>
|
||||
<string name="timeline_decryption_failure_historical_event_user_not_joined">"Sul pole ligipääsu antud sõnumile"</string>
|
||||
<string name="timeline_decryption_failure_unable_to_decrypt">"Sõnumi dekrüptimine ei õnnestu"</string>
|
||||
<string name="timeline_decryption_failure_withheld_unverified">"Kuna seade on verifitseerimata või saatja pole sinu digitaalset identiteeti verifitseerinud, siis sõnumi näitamine on blokeeritud."</string>
|
||||
<string name="vulkan_not_supported_dialog_content_android">"Sinu nutiseadme tarkvara on liiga vana, vajalik on Android 8 või uuem."</string>
|
||||
<string name="vulkan_not_supported_dialog_title_android">"Kaartide joonistamine pole toetatud"</string>
|
||||
</resources>
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
<string name="action_decline_and_block">"Hylkää ja estä"</string>
|
||||
<string name="action_delete">"Poista"</string>
|
||||
<string name="action_delete_account">"Poista tili"</string>
|
||||
<string name="action_delete_file">"Poista tiedosto"</string>
|
||||
<string name="action_delete_poll">"Poista kysely"</string>
|
||||
<string name="action_deselect_all">"Poista kaikki valinnat"</string>
|
||||
<string name="action_disable">"Poista käytöstä"</string>
|
||||
@@ -304,6 +305,7 @@ Syy: %1$s."</string>
|
||||
<string name="common_please_wait">"Odota hetki…"</string>
|
||||
<string name="common_poll_end_confirmation">"Haluatko varmasti lopettaa tämän kyselyn?"</string>
|
||||
<string name="common_poll_summary">"Kysely: %1$s"</string>
|
||||
<string name="common_poll_summary_prefix">"Kysely"</string>
|
||||
<string name="common_poll_total_votes">"Ääniä yhteensä: %1$s"</string>
|
||||
<string name="common_poll_undisclosed_text">"Tulokset näkyvät kyselyn päätyttyä"</string>
|
||||
<plurals name="common_poll_votes_count">
|
||||
@@ -543,4 +545,6 @@ Haluatko varmasti jatkaa?"</string>
|
||||
<string name="timeline_decryption_failure_historical_event_user_not_joined">"Sinulla ei ole oikeutta lukea tätä viestiä"</string>
|
||||
<string name="timeline_decryption_failure_unable_to_decrypt">"Viestin salauksen purkaminen ei onnistu"</string>
|
||||
<string name="timeline_decryption_failure_withheld_unverified">"Tämä viesti estettiin, koska et ole vahvistanut laitettasi tai koska lähettäjän on vahvistettava diigitaalinen identiteettisi."</string>
|
||||
<string name="vulkan_not_supported_dialog_content_android">"Laitteesi on liian vanha, tarvitset laitteen, jossa on Android 8 tai uudempi."</string>
|
||||
<string name="vulkan_not_supported_dialog_title_android">"Karttojen renderöintiä ei tueta"</string>
|
||||
</resources>
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
<string name="a11y_info">"Információ"</string>
|
||||
<string name="a11y_join_call">"Csatlakozás a híváshoz"</string>
|
||||
<string name="a11y_jump_to_bottom">"Ugrás az aljára"</string>
|
||||
<string name="a11y_jump_to_unread">"Ugrás az olvasatlanhoz"</string>
|
||||
<string name="a11y_move_the_map_to_my_location">"Térkép áthelyezése a jelenlegi helyre"</string>
|
||||
<string name="a11y_notifications_mentions_only">"Csak megemlítések"</string>
|
||||
<string name="a11y_notifications_muted">"Némítva"</string>
|
||||
@@ -98,6 +99,7 @@
|
||||
<string name="action_decline_and_block">"Elutasítás és letiltás"</string>
|
||||
<string name="action_delete">"Törlés"</string>
|
||||
<string name="action_delete_account">"Fiók törlése"</string>
|
||||
<string name="action_delete_file">"Fájl törlése"</string>
|
||||
<string name="action_delete_poll">"Szavazás törlése"</string>
|
||||
<string name="action_deselect_all">"Kijelölés megszüntetése"</string>
|
||||
<string name="action_disable">"Letiltás"</string>
|
||||
@@ -303,6 +305,7 @@ Ok: %1$s."</string>
|
||||
<string name="common_please_wait">"Kis türelmet…"</string>
|
||||
<string name="common_poll_end_confirmation">"Biztos, hogy befejezi ezt a szavazást?"</string>
|
||||
<string name="common_poll_summary">"Szavazás: %1$s"</string>
|
||||
<string name="common_poll_summary_prefix">"Szavazás"</string>
|
||||
<string name="common_poll_total_votes">"Összes szavazat: %1$s"</string>
|
||||
<string name="common_poll_undisclosed_text">"Az eredmények a szavazás befejezése után jelennek meg"</string>
|
||||
<plurals name="common_poll_votes_count">
|
||||
@@ -541,4 +544,6 @@ Biztos, hogy folytatja?"</string>
|
||||
<string name="timeline_decryption_failure_historical_event_user_not_joined">"Nincs hozzáférése ehhez az üzenethez"</string>
|
||||
<string name="timeline_decryption_failure_unable_to_decrypt">"Nem sikerült visszafejteni az üzenetet"</string>
|
||||
<string name="timeline_decryption_failure_withheld_unverified">"Ez az üzenet azért lett blokkolva, mert vagy nem ellenőrizte az eszközt, vagy a feladónak ellenőriznie kell az Ön digitális személyazonosságát."</string>
|
||||
<string name="vulkan_not_supported_dialog_content_android">"Az Ön eszköze túl régi, Android 8 vagy újabb verziójú eszközre van szükség."</string>
|
||||
<string name="vulkan_not_supported_dialog_title_android">"A térképek megjelenítése nem támogatott"</string>
|
||||
</resources>
|
||||
|
||||
@@ -97,6 +97,7 @@
|
||||
<string name="action_decline_and_block">"拒否してブロック"</string>
|
||||
<string name="action_delete">"削除"</string>
|
||||
<string name="action_delete_account">"アカウントを削除"</string>
|
||||
<string name="action_delete_file">"ファイルを削除"</string>
|
||||
<string name="action_delete_poll">"投票を削除"</string>
|
||||
<string name="action_deselect_all">"全ての選択を解除"</string>
|
||||
<string name="action_disable">"無効化"</string>
|
||||
@@ -292,7 +293,7 @@
|
||||
<string name="common_or">"または"</string>
|
||||
<string name="common_other_options">"他のオプション"</string>
|
||||
<string name="common_password">"パスワード"</string>
|
||||
<string name="common_people">"人々"</string>
|
||||
<string name="common_people">"ユーザー"</string>
|
||||
<string name="common_permalink">"固定リンク"</string>
|
||||
<string name="common_permission">"権限"</string>
|
||||
<string name="common_pinned">"ピン留め"</string>
|
||||
@@ -300,6 +301,7 @@
|
||||
<string name="common_please_wait">"お待ちください…"</string>
|
||||
<string name="common_poll_end_confirmation">"本当に投票を終了しますか?"</string>
|
||||
<string name="common_poll_summary">"投票: %1$s"</string>
|
||||
<string name="common_poll_summary_prefix">"投票"</string>
|
||||
<string name="common_poll_total_votes">"総投票数:%1$s"</string>
|
||||
<string name="common_poll_undisclosed_text">"結果は投票終了後に表示されます"</string>
|
||||
<plurals name="common_poll_votes_count">
|
||||
|
||||
@@ -8,13 +8,16 @@
|
||||
<plurals name="a11y_digits_entered">
|
||||
<item quantity="other">"%1$d자리 입력됨"</item>
|
||||
</plurals>
|
||||
<string name="a11y_duration">"소요 시간: %1$s"</string>
|
||||
<string name="a11y_edit_avatar">"아바타 편집"</string>
|
||||
<string name="a11y_edit_room_address_hint">"전체 주소는 다음과 같습니다 %1$s"</string>
|
||||
<string name="a11y_encryption_details">"암호화 세부 정보"</string>
|
||||
<string name="a11y_expand_message_text_field">"메시지 텍스트 필드 확장"</string>
|
||||
<string name="a11y_hide_password">"비밀번호 숨기기"</string>
|
||||
<string name="a11y_info">"정보"</string>
|
||||
<string name="a11y_join_call">"통화 참가"</string>
|
||||
<string name="a11y_jump_to_bottom">"맨 아래로 이동"</string>
|
||||
<string name="a11y_jump_to_unread">"읽지 않은 항목으로 이동"</string>
|
||||
<string name="a11y_move_the_map_to_my_location">"지도를 내 위치로 이동"</string>
|
||||
<string name="a11y_notifications_mentions_only">"멘션만"</string>
|
||||
<string name="a11y_notifications_muted">"음소거함"</string>
|
||||
@@ -31,6 +34,7 @@
|
||||
<string name="a11y_playback_speed">"재생 속도"</string>
|
||||
<string name="a11y_poll">"투표"</string>
|
||||
<string name="a11y_poll_end">"종료된 투표"</string>
|
||||
<string name="a11y_position">"위치: %1$s"</string>
|
||||
<string name="a11y_qr_code">"QR 코드"</string>
|
||||
<string name="a11y_react_with">"%1$s에 반응하세요"</string>
|
||||
<string name="a11y_react_with_other_emojis">"다른 이모지로 반응하세요"</string>
|
||||
@@ -45,10 +49,15 @@
|
||||
<string name="a11y_room_avatar">"방 아바타"</string>
|
||||
<string name="a11y_send_files">"파일 보내기"</string>
|
||||
<string name="a11y_sender_location">"발신자 위치"</string>
|
||||
<string name="a11y_sent_by_sender_at_date">"%1$s님이 %2$s에 보냈습니다."</string>
|
||||
<string name="a11y_session_verification_time_limited_action_required">"제한 시간 내 인증이 필요합니다.1분 안에 확인해 주세요."</string>
|
||||
<string name="a11y_settings_with_required_action">"설정,조치 필요"</string>
|
||||
<string name="a11y_show_password">"비밀번호 표시"</string>
|
||||
<string name="a11y_start_call">"통화 시작"</string>
|
||||
<string name="a11y_start_video_call">"영상 통화 시작"</string>
|
||||
<string name="a11y_start_voice_call">"음성 통화 시작"</string>
|
||||
<string name="a11y_thread_in_room">"%1$s 내 스레드"</string>
|
||||
<string name="a11y_threads_in_room">"%1$s 내 스레드 목록"</string>
|
||||
<string name="a11y_tombstoned_room">"묘비 방"</string>
|
||||
<string name="a11y_user_avatar">"사용자 아바타"</string>
|
||||
<string name="a11y_user_menu">"사용자 메뉴"</string>
|
||||
@@ -66,6 +75,7 @@
|
||||
<string name="action_call">"통화"</string>
|
||||
<string name="action_cancel">"취소"</string>
|
||||
<string name="action_cancel_for_now">"현재 취소"</string>
|
||||
<string name="action_choose_file">"파일 선택"</string>
|
||||
<string name="action_choose_photo">"사진 선택"</string>
|
||||
<string name="action_clear">"지우기"</string>
|
||||
<string name="action_close">"닫기"</string>
|
||||
@@ -85,12 +95,16 @@
|
||||
<string name="action_deactivate_account">"계정 비활성화"</string>
|
||||
<string name="action_decline">"거절"</string>
|
||||
<string name="action_decline_and_block">"거부 및 차단"</string>
|
||||
<string name="action_delete">"삭제"</string>
|
||||
<string name="action_delete_account">"계정 삭제"</string>
|
||||
<string name="action_delete_file">"파일 삭제"</string>
|
||||
<string name="action_delete_poll">"투표 삭제"</string>
|
||||
<string name="action_deselect_all">"전체 선택 해제"</string>
|
||||
<string name="action_disable">"비활성화"</string>
|
||||
<string name="action_discard">"취소"</string>
|
||||
<string name="action_dismiss">"닫기"</string>
|
||||
<string name="action_done">"완료"</string>
|
||||
<string name="action_download">"다운로드"</string>
|
||||
<string name="action_edit">"편집"</string>
|
||||
<string name="action_edit_caption">"캡션 편집"</string>
|
||||
<string name="action_edit_poll">"투표 수정"</string>
|
||||
@@ -197,7 +211,9 @@
|
||||
<string name="common_beta">"베타"</string>
|
||||
<string name="common_blocked_users">"차단한 사용자"</string>
|
||||
<string name="common_bubbles">"버블"</string>
|
||||
<string name="common_call_declined">"통화 거절"</string>
|
||||
<string name="common_call_started">"통화 시작"</string>
|
||||
<string name="common_call_you_declined">"통화를 거절하셨습니다"</string>
|
||||
<string name="common_chat_backup">"채팅 백업"</string>
|
||||
<string name="common_copied_to_clipboard">"클립보드에 복사됨"</string>
|
||||
<string name="common_copyright">"저작권"</string>
|
||||
@@ -285,6 +301,7 @@
|
||||
<string name="common_please_wait">"기다려 주세요…"</string>
|
||||
<string name="common_poll_end_confirmation">"정말로 이 투표를 종료하시겠어요?"</string>
|
||||
<string name="common_poll_summary">"투표: %1$s"</string>
|
||||
<string name="common_poll_summary_prefix">"투표"</string>
|
||||
<string name="common_poll_total_votes">"총 투표수: %1$s"</string>
|
||||
<string name="common_poll_undisclosed_text">"결과는 투표가 끝난 이후에 공개됨"</string>
|
||||
<plurals name="common_poll_votes_count">
|
||||
@@ -448,6 +465,9 @@
|
||||
<string name="error_unknown">"이런, 오류가 발생했어요"</string>
|
||||
<string name="invite_friends_rich_title">"🔐️ %1$s에 참여하기"</string>
|
||||
<string name="invite_friends_text">"%1$s에서 대화해요: %2$s"</string>
|
||||
<string name="live_location_sharing_foreground_service_channel_title_android">"실시간 위치 공유"</string>
|
||||
<string name="live_location_sharing_foreground_service_message_android">"위치 공유 중"</string>
|
||||
<string name="live_location_sharing_foreground_service_title_android">"%1$s님의 실시간 위치"</string>
|
||||
<string name="login_initial_device_name_android">"%1$s Android"</string>
|
||||
<string name="preference_rageshake">"강하게 흔들어서 오류 보고하기"</string>
|
||||
<string name="screen_bug_report_a11y_screenshot">"스크린샷"</string>
|
||||
@@ -455,6 +475,12 @@
|
||||
<string name="screen_create_poll_options_section_title">"옵션"</string>
|
||||
<string name="screen_create_poll_remove_accessibility_label">"%1$s 제거"</string>
|
||||
<string name="screen_create_poll_settings_section_title">"설정"</string>
|
||||
<string name="screen_live_location_sheet_nobody_sharing">"위치를 공유 중인 사용자가 없습니다."</string>
|
||||
<string name="screen_live_location_sheet_sharing_live_location">"실시간 위치 공유 중"</string>
|
||||
<plurals name="screen_live_location_sheet_subtitle">
|
||||
<item quantity="other">"%1$d명"</item>
|
||||
</plurals>
|
||||
<string name="screen_live_location_sheet_title">"지도 보기"</string>
|
||||
<string name="screen_media_picker_error_failed_selection">"미디어 선택에 실패했습니다. 다시 시도해 주세요."</string>
|
||||
<string name="screen_pinned_timeline_empty_state_description">"메시지를 누르고 \"%1$s\" 를 선택하여 여기에 포함합니다."</string>
|
||||
<string name="screen_pinned_timeline_empty_state_headline">"중요한 메시지를 고정하여 쉽게 찾을 수 있도록 합니다"</string>
|
||||
@@ -478,6 +504,7 @@
|
||||
<string name="screen_room_event_pill">"메시지 %1$s"</string>
|
||||
<string name="screen_room_grouped_state_events_expand">"펼치기"</string>
|
||||
<string name="screen_room_grouped_state_events_reduce">"줄이다"</string>
|
||||
<string name="screen_room_live_location_banner">"실시간 위치 공유 중"</string>
|
||||
<string name="screen_room_permalink_same_room_android">"이 방을 이미 보고 있습니다!"</string>
|
||||
<string name="screen_room_pinned_banner_indicator">"%2$s 의 %1$s"</string>
|
||||
<string name="screen_room_pinned_banner_indicator_description">"%1$s 고정된 메시지"</string>
|
||||
|
||||
@@ -101,6 +101,7 @@
|
||||
<string name="action_decline_and_block">"Odrzuć i zablokuj"</string>
|
||||
<string name="action_delete">"Usuń"</string>
|
||||
<string name="action_delete_account">"Usuń konto"</string>
|
||||
<string name="action_delete_file">"Usuń plik"</string>
|
||||
<string name="action_delete_poll">"Usuń ankietę"</string>
|
||||
<string name="action_deselect_all">"Odznacz wszystko"</string>
|
||||
<string name="action_disable">"Wyłącz"</string>
|
||||
@@ -555,4 +556,6 @@ Czy na pewno chcesz kontynuować?"</string>
|
||||
<string name="timeline_decryption_failure_historical_event_user_not_joined">"Nie masz uprawnień do tej wiadomości"</string>
|
||||
<string name="timeline_decryption_failure_unable_to_decrypt">"Nie można odszyfrować wiadomości"</string>
|
||||
<string name="timeline_decryption_failure_withheld_unverified">"Ta wiadomość została zablokowana, ponieważ urządzenie nie zostało zweryfikowane lub nadawca musi zweryfikować Twoją tożsamość."</string>
|
||||
<string name="vulkan_not_supported_dialog_content_android">"Twoje urządzenie jest przestarzałe, wymagany system Android 8 lub nowszy."</string>
|
||||
<string name="vulkan_not_supported_dialog_title_android">"Renderowanie map nie jest obsługiwane"</string>
|
||||
</resources>
|
||||
|
||||
@@ -532,4 +532,6 @@
|
||||
<string name="timeline_decryption_failure_historical_event_user_not_joined">"无权访问此消息"</string>
|
||||
<string name="timeline_decryption_failure_unable_to_decrypt">"无法解密消息"</string>
|
||||
<string name="timeline_decryption_failure_withheld_unverified">"此消息已被阻止,因为你未验证你的设备,或发送者需要验证你的数字身份。"</string>
|
||||
<string name="vulkan_not_supported_dialog_content_android">"你的设备过旧,需要 Android 8 或更高版本的设备。"</string>
|
||||
<string name="vulkan_not_supported_dialog_title_android">"地图渲染不受支持。"</string>
|
||||
</resources>
|
||||
|
||||
@@ -546,4 +546,6 @@ Are you sure you want to continue?"</string>
|
||||
<string name="timeline_decryption_failure_historical_event_user_not_joined">"You don\'t have access to this message"</string>
|
||||
<string name="timeline_decryption_failure_unable_to_decrypt">"Unable to decrypt message"</string>
|
||||
<string name="timeline_decryption_failure_withheld_unverified">"This message was blocked either because you did not verify your device or because the sender needs to verify your digital identity."</string>
|
||||
<string name="vulkan_not_supported_dialog_content_android">"Your device is too old, a device with Android 8 or newer is required."</string>
|
||||
<string name="vulkan_not_supported_dialog_title_android">"Rendering maps is not supported"</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user