Skip to content

Commit 464a54c

Browse files
Merge pull request #10192 from rafaeltonholo/chore/10190/add-message-list-event-effect
refactor(message-list): create message list events and effects
2 parents bc6b0ad + 7fa9803 commit 464a54c

File tree

6 files changed

+405
-0
lines changed

6 files changed

+405
-0
lines changed
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package net.thunderbird.feature.mail.message.list.ui.effect
2+
3+
import net.thunderbird.feature.account.AccountId
4+
5+
/**
6+
* Represents one-time side effects that can be triggered from the message list screen.
7+
* These effects are intended to be consumed by the UI to perform actions like navigation
8+
* or showing transient messages.
9+
*/
10+
sealed interface MessageListEffect {
11+
/**
12+
* Effect to navigate back from the current screen.
13+
*/
14+
data object NavigateBack : MessageListEffect
15+
16+
/**
17+
* Effect to navigate to the "Move To" screen, allowing the user to select a destination
18+
* folder for the given messages.
19+
*
20+
* @param messagesIds The unique identifiers of the messages to be moved.
21+
* @param accountId The identifier of the account to which the messages belong.
22+
*/
23+
data class NavigateToMoveToScreen(val messagesIds: List<Long>, val accountId: AccountId) : MessageListEffect
24+
25+
/**
26+
* Represents the effect of messages being successfully archived.
27+
* This is typically used to show a notification or a snackbar to the user.
28+
*
29+
* @param messagesIdByAccountId A map where keys are account IDs and values are lists of message IDs
30+
* that have been archived for that account.
31+
*/
32+
data class ArchivedMessages(val messagesIdByAccountId: Map<AccountId, List<Long>>) : MessageListEffect
33+
34+
/**
35+
* Represents an effect for when pending (outbox) messages have been successfully sent.
36+
*
37+
* This effect is triggered after messages residing in the outbox are processed and sent,
38+
* typically resulting in them being moved to the Sent folder, if any configured.
39+
*
40+
* @param messagesIdByAccountId A map where each key is an [AccountId] and the value is a list of
41+
* message IDs that have been sent for that account.
42+
*/
43+
data class PendingMessagesSent(val messagesIdByAccountId: Map<AccountId, List<Long>>) : MessageListEffect
44+
45+
/**
46+
* Represents an effect for when messages have been permanently removed (expunged) from a folder.
47+
*
48+
* This typically happens after messages marked for deletion are purged from the server,
49+
* particularly with IMAP accounts. The UI should reflect this by removing these messages
50+
* or updating its state accordingly.
51+
*
52+
* @param messagesIdByAccountId A map where keys are account IDs and values are lists of message IDs
53+
* that have been expunged. This structure supports handling expunged messages from multiple accounts
54+
* in a single operation.
55+
*/
56+
data class ExpungedMessages(val messagesIdByAccountId: Map<AccountId, List<Long>>) : MessageListEffect
57+
58+
/**
59+
* Represents the side effect that messages have been marked for deletion.
60+
*
61+
* This effect is typically triggered after a user performs a delete action. The UI can use this
62+
* to show a confirmation, such as a snackbar, indicating the successful deletion.
63+
*
64+
* @param messagesIdByAccountId A map where each key is an [AccountId] and the corresponding value
65+
* is a list of message IDs that have been deleted for that account.
66+
*/
67+
data class DeletedMessages(val messagesIdByAccountId: Map<AccountId, List<Long>>) : MessageListEffect
68+
69+
/**
70+
* Represents the effect of one or more draft messages being discarded (deleted).
71+
*
72+
* @param messagesIdByAccountId A map where each key is an [AccountId] and the value is a list of message IDs
73+
* that have been discarded for that account.
74+
*/
75+
data class DraftsDiscarded(val messagesIdByAccountId: Map<AccountId, List<Long>>) : MessageListEffect
76+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package net.thunderbird.feature.mail.message.list.ui.event
2+
3+
import net.thunderbird.feature.mail.message.list.ui.state.Folder
4+
5+
/**
6+
* Represents UI events related to folder actions, extending [MessageListEvent].
7+
* These events are typically triggered by user interactions within a specific folder view.
8+
*
9+
* @see MessageListEvent
10+
*/
11+
sealed interface FolderEvent : MessageListEvent {
12+
/**
13+
* Event to expunge (permanently delete) messages marked for deletion in a specific folder.
14+
*
15+
* @param folder The folder from which to expunge messages.
16+
*/
17+
data class Expunge(val folder: Folder) : FolderEvent
18+
19+
/**
20+
* Event to create a new folder to be used as the archive folder.
21+
*
22+
* @param name The name of the folder to be created.
23+
*/
24+
data class CreateArchiveFolder(val name: String) : FolderEvent
25+
26+
/**
27+
* Event to assign an existing folder as the archive folder.
28+
*
29+
* @param folder The folder to be designated as the archive folder.
30+
*/
31+
data class AssignArchiveFolder(val folder: Folder) : FolderEvent
32+
33+
/**
34+
* Event to mark all messages within a specific folder as read.
35+
*
36+
* @param folder The folder in which all messages should be marked as read.
37+
*/
38+
data class MarkAllMessagesAsRead(val folder: Folder) : FolderEvent
39+
}
40+
41+
/**
42+
* Represents events that are specific to the Trash folder.
43+
*/
44+
sealed interface TrashFolderEvent : FolderEvent {
45+
/**
46+
* Event to permanently delete all messages in the Trash folder.
47+
*/
48+
data object EmptyTrash : FolderEvent
49+
}
50+
51+
/**
52+
* Represents events that are specific to the Outbox folder.
53+
*/
54+
sealed interface OutboxFolderEvent : FolderEvent {
55+
/**
56+
* Event to trigger sending all pending messages in the Outbox.
57+
*/
58+
data object SendPendingMessages : FolderEvent
59+
}
60+
61+
/**
62+
* Represents events that are specific to the Spam folder.
63+
*/
64+
sealed interface SpamFolderEvent : FolderEvent {
65+
/**
66+
* Event to permanently delete all messages in the spam folder.
67+
*/
68+
data object EmptySpamFolder : FolderEvent
69+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package net.thunderbird.feature.mail.message.list.ui.event
2+
3+
import net.thunderbird.core.common.action.SwipeAction
4+
import net.thunderbird.core.common.mail.Flag
5+
import net.thunderbird.feature.mail.message.list.ui.state.MessageItemUi
6+
7+
/**
8+
* Represents events that can be triggered on a single message item in the message list, extending [MessageListEvent].
9+
*
10+
* @see MessageListEvent
11+
*/
12+
sealed interface MessageItemEvent : MessageListEvent.UserEvent {
13+
/**
14+
* Represents an event triggered when a user clicks on a single message item in the list.
15+
*
16+
* @param message The [MessageItemUi] that was clicked.
17+
*/
18+
data class OnMessageClick(val message: MessageItemUi) : MessageItemEvent
19+
20+
/**
21+
* Event to toggle the selection state of one or more messages.
22+
*
23+
* @param messages The list of messages whose selection state should be toggled.
24+
*/
25+
data class ToggleSelectMessages(val messages: List<MessageItemUi>) : MessageItemEvent {
26+
constructor(message: MessageItemUi) : this(messages = listOf(message))
27+
}
28+
29+
/**
30+
* Event to toggle the 'favourite' (starred) state of one or more messages.
31+
*
32+
* @param messages The list of [MessageItemUi]s to be toggled.
33+
*/
34+
data class ToggleFavourite(val messages: List<MessageItemUi>) : MessageItemEvent {
35+
constructor(message: MessageItemUi) : this(messages = listOf(message))
36+
}
37+
38+
/**
39+
* An event to toggle the read/unread status of one or more messages.
40+
*
41+
* @param messages The list of messages whose read/unread status should be toggled.
42+
*/
43+
data class ToggleReadUnread(val messages: List<MessageItemUi>) : MessageItemEvent {
44+
constructor(message: MessageItemUi) : this(messages = listOf(message))
45+
}
46+
47+
/**
48+
* Flags a list of messages with the given [Flag].
49+
*
50+
* @param messages The list of messages to flag.
51+
* @param flag The flag to apply to the messages.
52+
*/
53+
data class FlagMessages(val messages: List<MessageItemUi>, val flag: Flag) : MessageItemEvent {
54+
constructor(message: MessageItemUi, flag: Flag) : this(messages = listOf(message), flag = flag)
55+
}
56+
57+
/**
58+
* Represents a swipe action on a message item.
59+
*
60+
* @property message The message item that was swiped.
61+
*/
62+
data class OnSwipeMessage(val message: MessageItemUi, val swipeAction: SwipeAction) : MessageItemEvent
63+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package net.thunderbird.feature.mail.message.list.ui.event
2+
3+
import net.thunderbird.core.common.action.SwipeActions
4+
import net.thunderbird.feature.account.AccountId
5+
import net.thunderbird.feature.mail.message.list.preferences.MessageListPreferences
6+
import net.thunderbird.feature.mail.message.list.ui.state.MessageItemUi
7+
import net.thunderbird.feature.mail.message.list.ui.state.SortType
8+
9+
/**
10+
* Represents the events that can be triggered from the message list screen.
11+
* These events are handled by the [MessageListViewModel] to update the UI state.
12+
*/
13+
sealed interface MessageListEvent {
14+
sealed interface SystemEvent : MessageListEvent
15+
sealed interface UserEvent : MessageListEvent
16+
17+
/**
18+
* A system event to trigger the loading of initial configurations for the message list.
19+
* This includes loading swipe actions, user preferences, and available sort types.
20+
*/
21+
data object LoadConfigurations : SystemEvent
22+
23+
/**
24+
* A system event indicating that the swipe actions for one or more accounts have been loaded.
25+
*
26+
* @param swipeActions A map where the key is the [AccountId] and the value is the corresponding [SwipeActions]
27+
* configuration for that account.
28+
*/
29+
data class SwipeActionsLoaded(val swipeActions: Map<AccountId, SwipeActions>) : SystemEvent
30+
31+
/**
32+
* A system event to update the message list preferences.
33+
* This is typically triggered when preferences change from an external source, like the settings screen.
34+
*
35+
* @param preferences The new [MessageListPreferences] to apply.
36+
*/
37+
data class UpdatePreferences(val preferences: MessageListPreferences) : SystemEvent
38+
39+
/**
40+
* A system event indicating that the sort types for various accounts have been loaded.
41+
*
42+
* @param sortTypes A map where the key is the [AccountId] and the value is the corresponding [SortType].
43+
* A `null` key represents the global or default sort type.
44+
*/
45+
data class SortTypesLoaded(val sortTypes: Map<AccountId?, SortType>) : SystemEvent
46+
47+
/**
48+
* Signals that all initial configurations, such as preferences, swipe actions, and sort types,
49+
* have been successfully loaded and applied. This event indicates that the system is ready
50+
* to proceed with loading the actual message list content.
51+
*/
52+
data object AllConfigsReady : SystemEvent
53+
54+
/**
55+
* A system event to update the progress of the loading indicator.
56+
*
57+
* @param progress A float value between 0.0 and 1.0 representing the loading completion percentage.
58+
*/
59+
data class UpdateLoadingProgress(val progress: Float) : SystemEvent
60+
61+
/**
62+
* A system event indicating that a list of messages has been successfully loaded.
63+
*
64+
* @param messages The list of [MessageItemUi] objects to be displayed.
65+
*/
66+
data class MessagesLoaded(val messages: List<MessageItemUi>) : SystemEvent
67+
68+
/**
69+
* Event triggered when the user initiates selection mode, usually through a long press on a message item.
70+
*/
71+
data object EnterSelectionMode : UserEvent
72+
73+
/**
74+
* Event triggered when the user exits the message selection mode.
75+
* This typically happens when the user deselects all messages or cancels the selection action.
76+
*/
77+
data object ExitSelectionMode : UserEvent
78+
79+
/**
80+
* Represents the event of a user requesting to load more messages in the list.
81+
*/
82+
data object LoadMore : UserEvent
83+
84+
/**
85+
* Triggers a refresh of the message list, fetching the latest messages from the server.
86+
*/
87+
data object Refresh : UserEvent
88+
89+
/**
90+
* An event that is triggered when the user changes the sort order of the message list.
91+
*
92+
* @param sortType The new [SortType] to apply to the message list.
93+
*/
94+
data class ChangeSortType(val sortType: SortType) : UserEvent
95+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package net.thunderbird.feature.mail.message.list.ui.event
2+
3+
/**
4+
* Defines the events related to searching, extending [MessageListEvent].
5+
* These events are typically triggered by user interactions or specific conditions.
6+
*
7+
* @see MessageListEvent
8+
*/
9+
sealed interface MessageListSearchEvent : MessageListEvent.UserEvent {
10+
/**
11+
* Event triggered when a user performs a search with a specific query.
12+
*
13+
* @param query The text string to search for within the message list.
14+
*/
15+
data class UpdateSearchQuery(val query: String) : MessageListSearchEvent
16+
17+
/**
18+
* Represents an event to trigger a "search everywhere" action.
19+
* This typically expands the search scope to include all folders or accounts,
20+
* not just the currently viewed one.
21+
*/
22+
data object SearchEverywhere : MessageListSearchEvent
23+
24+
/**
25+
* Event to trigger a remote search on the server for the current query.
26+
*/
27+
data object SearchRemotely : MessageListSearchEvent
28+
29+
/**
30+
* Event triggered to enter in the search mode.
31+
*/
32+
data object EnterSearchMode : MessageListSearchEvent
33+
34+
/**
35+
* Event triggered to clear the current search query and exit the search mode.
36+
*/
37+
data object ExitSearchMode : MessageListSearchEvent
38+
}

0 commit comments

Comments
 (0)