Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ class SystemMessageContentMapper @Inject constructor(
content,
members
)

is MessageContent.AdminlessDeleteReminder ->
UIMessageContent.SystemMessage.AdminlessDeleteReminder(content.deletionScheduledFor)
}

private fun mapConversationConversationAppsAccessChanged(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

package com.wire.android.ui.home.conversations.messages.item

import android.text.format.DateFormat
import androidx.annotation.DrawableRes
import androidx.annotation.PluralsRes
import androidx.annotation.StringRes
Expand Down Expand Up @@ -63,6 +64,7 @@ import com.wire.android.ui.theme.wireDimensions
import com.wire.android.ui.theme.wireTypography
import com.wire.android.util.CustomTabsHelper
import com.wire.android.util.SupportPage
import com.wire.android.util.formatMonthDayShortTime
import com.wire.android.util.supportUrlResource
import com.wire.android.util.ui.MarkdownTextStyle
import com.wire.android.util.ui.UIText
Expand Down Expand Up @@ -641,6 +643,26 @@ private fun SystemMessage.buildContent(isWireCellsEnabled: Boolean) = when (this
}
}
}

is SystemMessage.AdminlessDeleteReminder -> buildContent(
iconResId = commonR.drawable.ic_info,
iconTintColor = MaterialTheme.wireColorScheme.error,
learnMorePage = SupportPage.ADMINLESS_GROUP_DELETE,
) {
val is24Hour = DateFormat.is24HourFormat(LocalContext.current)
val markdownTextStyle = DefaultMarkdownTextStyle.copy(
normalColor = MaterialTheme.wireColorScheme.error,
boldColor = MaterialTheme.wireColorScheme.error
)
buildAnnotatedString {
append(
stringResource(
id = R.string.label_system_message_adminless_delete_reminder,
formatArgs = arrayOf(deletionScheduledFor.formatMonthDayShortTime(is24Hour))
).toMarkdownAnnotatedString(markdownTextStyle)
)
}
}
}

private fun AnnotatedString.Builder.appendVerticalSpace() = withStyle(ParagraphStyle()) { append(" ") }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import com.wire.android.util.ui.PreviewMultipleThemes
import com.wire.android.util.ui.UIText
import com.wire.android.util.ui.toUIText
import com.wire.kalium.logic.data.conversation.Conversation
import kotlinx.datetime.Instant

@PreviewMultipleThemes
@Composable
Expand Down Expand Up @@ -486,3 +487,17 @@ fun PreviewSystemMessageConversationMessageAppsAccessEnabled() {
)
}
}

@PreviewMultipleThemes
@Composable
fun PreviewSystemMessageAdminlessDeleteReminder() {
WireTheme {
SystemMessageItem(
message = mockMessageWithKnock.copy(
messageContent = UIMessageContent.SystemMessage.AdminlessDeleteReminder(
deletionScheduledFor = Instant.parse("2026-04-23T12:00:00Z")
)
)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,11 @@ sealed interface UIMessageContent {
val isAuthorSelfUser: Boolean = false,
val isAccessEnabled: Boolean
) : SystemMessage

@Serializable
data class AdminlessDeleteReminder(
val deletionScheduledFor: Instant
) : SystemMessage
}
}

Expand Down
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1951,6 +1951,7 @@ In group conversations, the group admin can overwrite this setting.</string>
<string name="label_system_message_apps_access_disabled_by_other">%1$s disabled **apps** for this conversation</string>
<string name="label_system_message_apps_access_enabled_disclaimer">Added apps have access to the content of this conversation.</string>
<string name="label_system_message_admin_role_assigned">You were promoted to group admin</string>
<string name="label_system_message_adminless_delete_reminder">This group will be automatically deleted on %1$s, as there are no eligible group admins.</string>
<string name="more_information_about_this_server">More information about this backend</string>

<!-- Pending messages service notification -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import java.util.Locale
import kotlinx.datetime.Instant

@OptIn(ExperimentalCoroutinesApi::class)
@ExtendWith(CoroutineTestExtension::class)
Expand Down Expand Up @@ -75,6 +76,18 @@ class SystemMessageContentMapperTest {
assertTrue(uiContent is SystemMessage.ConversationMessageTimerDeactivated)
}

@Test
fun givenAdminlessDeleteReminder_whenMappingToSystemMessage_thenScheduledDeletionIsPreserved() = runTest {
val (_, mapper) = Arrangement().arrange()
val scheduledDeletion = Instant.parse("2026-04-23T12:00:00Z")
val content = MessageContent.AdminlessDeleteReminder(scheduledDeletion)

val uiContent = mapper.mapMessage(TestMessage.SYSTEM_MESSAGE.copy(content = content), emptyList())

assertIs<SystemMessage.AdminlessDeleteReminder>(uiContent!!)
assertEquals(scheduledDeletion, uiContent.deletionScheduledFor)
}

@Test
fun givenMemberDetails_whenMappingToSystemMessageMemberName_thenCorrectValuesShouldBeReturned() = runTest {
// Given
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@
*/
package com.wire.android.util

import android.text.format.DateFormat
import androidx.compose.runtime.Stable
import kotlinx.datetime.Instant
import kotlinx.datetime.toJavaInstant
import java.text.SimpleDateFormat
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle
Expand All @@ -39,6 +41,10 @@ fun Instant.formatMediumDateTime(): String = DateAndTimeParsers.formatMediumDate
@Stable
fun Instant.formatFullDateShortTime(): String = DateAndTimeParsers.formatFullDateShortTime(this)

@Stable
fun Instant.formatMonthDayShortTime(is24Hour: Boolean): String =
DateAndTimeParsers.formatMonthDayShortTime(this, is24Hour)

@Stable
fun Instant.uiMessageDateTime(): String = DateAndTimeParsers.uiMessageDateTime(this)

Expand Down Expand Up @@ -107,6 +113,16 @@ class DateAndTimeParsers private constructor() {

fun formatFullDateShortTime(instant: Instant): String = fullDateShortTimeFormatter.format(instant.toJavaInstant())

fun formatMonthDayShortTime(instant: Instant, is24Hour: Boolean): String {
val locale = Locale.getDefault()
val date = Date.from(instant.toJavaInstant())
val datePattern = DateFormat.getBestDateTimePattern(locale, "MMMMd")
val timePattern = DateFormat.getBestDateTimePattern(locale, if (is24Hour) "Hm" else "hm")
val formattedDate = SimpleDateFormat(datePattern, locale).format(date)
val formattedTime = SimpleDateFormat(timePattern, locale).format(date)
return "$formattedDate, $formattedTime"
}

fun cellTimeFormat(instant: Instant): String {
val timeFormatter = java.text.DateFormat.getTimeInstance(
java.text.DateFormat.SHORT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,6 @@ enum class SupportPage(
SEARCH("search", R.string.url_learn_about_search),
CELLS_CONVERSATION("cells_conversation", R.string.empty_screen_learn_more_link_conversation),
CELLS_ALL_FILES("cells_all_files", R.string.empty_screen_learn_more_link_all_files_screen),
FILE_PERMISSIONS_IN_SHARED_DRIVE("file_permissions_in_shared_drive", R.string.file_permissions_in_shared_drive)
FILE_PERMISSIONS_IN_SHARED_DRIVE("file_permissions_in_shared_drive", R.string.file_permissions_in_shared_drive),
ADMINLESS_GROUP_DELETE("adminless_group_delete", R.string.url_system_message_adminless_group_delete),
}
1 change: 1 addition & 0 deletions core/ui-common/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
<string name="url_legal_hold_learn_more" translatable="false">https://support.wire.com/hc/articles/360002018278</string>
<string name="empty_screen_learn_more_link_conversation" translatable="false">https://support.wire.com/hc/articles/32207745256221</string>
<string name="empty_screen_learn_more_link_all_files_screen" translatable="false">https://support.wire.com/hc/articles/32207800433309</string>
<string name="url_system_message_adminless_group_delete" translatable="false">https://support.wire.com/hc/en-us/articles/37518608388125-Prevent-adminless-groups</string>
<string name="file_permissions_in_shared_drive" translatable="false">https://support.wire.com/hc/articles/36679600377373</string>
<string name="legal_hold_learn_more_button">Learn more about legal hold</string>
<string name="legal_hold_connection_failed_dialog_title">Connecting not possible</string>
Expand Down
2 changes: 1 addition & 1 deletion kalium
Submodule kalium updated 39 files
+2 −1 core/data/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/Conversation.kt
+49 −0 ...twork-model/src/commonMain/kotlin/com/wire/kalium/network/api/authenticated/notification/EventContentDTO.kt
+128 −0 ...lin/com/wire/kalium/network/api/authenticated/notification/AdminlessDeleteReminderEventSerializationTest.kt
+117 −0 ...t/kotlin/com/wire/kalium/network/api/authenticated/notification/SystemConversationEventSerializationTest.kt
+5 −3 data/persistence/src/commonMain/db_user/com/wire/kalium/persistence/ConversationDetails.sq
+15 −1 data/persistence/src/commonMain/db_user/com/wire/kalium/persistence/Conversations.sq
+0 −1 data/persistence/src/commonMain/db_user/com/wire/kalium/persistence/MessageDetailsView.sq
+222 −0 data/persistence/src/commonMain/db_user/migrations/144.sqm
+1 −0 data/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/conversation/ConversationDAO.kt
+7 −0 data/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/conversation/ConversationDAOImpl.kt
+2 −0 ...e/src/commonMain/kotlin/com/wire/kalium/persistence/dao/conversation/ConversationDetailsWithEventsMapper.kt
+2 −0 data/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/conversation/ConversationMapper.kt
+1 −0 data/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/conversation/ConversationViewEntity.kt
+1 −1 data/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/message/MessageEntity.kt
+1 −0 data/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/message/MessageInsertExtension.kt
+6 −0 data/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/db/TableMapper.kt
+1 −0 data/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/db/UserDatabaseBuilder.kt
+16 −0 data/persistence/src/commonTest/kotlin/com/wire/kalium/persistence/conversation/ConversationExtensionsTest.kt
+70 −0 data/persistence/src/commonTest/kotlin/com/wire/kalium/persistence/dao/ConversationDAOTest.kt
+1 −0 data/persistence/src/commonTest/kotlin/com/wire/kalium/persistence/dao/LastMessageListTest.kt
+33 −0 ...ence/src/commonTest/kotlin/com/wire/kalium/persistence/dao/conversation/folder/ConversationFolderDAOTest.kt
+18 −0 ...alium/logic/feature/conversation/GetPaginatedFlowOfConversationDetailsWithEventsBySearchQueryUseCaseTest.kt
+4 −2 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationMapper.kt
+1 −1 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/conversation/ConversationRepository.kt
+21 −2 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/event/Event.kt
+107 −18 logic/src/commonMain/kotlin/com/wire/kalium/logic/data/event/EventMapper.kt
+9 −0 logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/UserSessionScope.kt
+1 −2 ...re/kalium/logic/feature/conversation/GetPaginatedFlowOfConversationDetailsWithEventsBySearchQueryUseCase.kt
+2 −1 ...in/kotlin/com/wire/kalium/logic/feature/conversation/ObserveConversationListDetailsWithEventsUseCaseImpl.kt
+7 −0 logic/src/commonMain/kotlin/com/wire/kalium/logic/sync/receiver/ConversationEventReceiver.kt
+49 −0 ...ommonMain/kotlin/com/wire/kalium/logic/sync/receiver/conversation/DeleteConversationReminderEventHandler.kt
+1 −1 ...c/src/commonMain/kotlin/com/wire/kalium/logic/sync/receiver/conversation/DeletedConversationEventHandler.kt
+19 −0 logic/src/commonTest/kotlin/com/wire/kalium/logic/data/conversation/ConversationMapperTest.kt
+115 −0 logic/src/commonTest/kotlin/com/wire/kalium/logic/data/event/EventMapperTest.kt
+1 −0 ...otlin/com/wire/kalium/logic/feature/conversation/ObserveConversationListDetailsWithEventsUseCaseImplTest.kt
+8 −0 logic/src/commonTest/kotlin/com/wire/kalium/logic/framework/TestEvent.kt
+21 −0 logic/src/commonTest/kotlin/com/wire/kalium/logic/sync/receiver/ConversationEventReceiverTest.kt
+79 −0 ...nTest/kotlin/com/wire/kalium/logic/sync/receiver/conversation/DeleteConversationReminderEventHandlerTest.kt
+38 −7 ...c/commonTest/kotlin/com/wire/kalium/logic/sync/receiver/conversation/DeletedConversationEventHandlerTest.kt
Loading