First Commit

This commit is contained in:
2025-12-18 16:28:50 +07:00
commit 8c3e4f491f
9974 changed files with 396488 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
/build
+25
View File
@@ -0,0 +1,25 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2022-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.
*/
plugins {
id("io.element.android-compose-library")
id("kotlin-parcelize")
}
android {
namespace = "io.element.android.features.messages.api"
}
dependencies {
implementation(projects.libraries.architecture)
implementation(projects.libraries.designsystem)
implementation(projects.libraries.matrix.api)
implementation(projects.libraries.mediaviewer.api)
implementation(projects.libraries.preferences.api)
api(projects.libraries.textcomposer.impl)
}
@@ -0,0 +1,21 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.
*/
package io.element.android.features.messages.api
import io.element.android.libraries.textcomposer.model.MessageComposerMode
/**
* Hoist-able state of the message composer.
*
* Typical use case is inside other presenters, to know if
* the composer is in a thread, if it's editing a message, etc.
*/
interface MessageComposerContext {
val composerMode: MessageComposerMode
}
@@ -0,0 +1,55 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.
*/
package io.element.android.features.messages.api
import android.os.Parcelable
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.plugin.Plugin
import io.element.android.libraries.architecture.FeatureEntryPoint
import io.element.android.libraries.architecture.NodeInputs
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.ThreadId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.permalink.PermalinkData
import kotlinx.parcelize.Parcelize
interface MessagesEntryPoint : FeatureEntryPoint {
sealed interface InitialTarget : Parcelable {
@Parcelize
data class Messages(
val focusedEventId: EventId?,
) : InitialTarget
@Parcelize
data object PinnedMessages : InitialTarget
}
interface Callback : Plugin {
fun navigateToRoomDetails()
fun navigateToRoomMemberDetails(userId: UserId)
fun handlePermalinkClick(data: PermalinkData, pushToBackstack: Boolean)
fun forwardEvent(eventId: EventId, fromPinnedEvents: Boolean)
fun navigateToRoom(roomId: RoomId)
}
data class Params(val initialTarget: InitialTarget) : NodeInputs
fun createNode(
parentNode: Node,
buildContext: BuildContext,
params: Params,
callback: Callback,
): Node
interface NodeProxy {
suspend fun attachThread(threadId: ThreadId, focusedEventId: EventId?)
}
}
@@ -0,0 +1,13 @@
/*
* 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.
*/
package io.element.android.features.messages.api.pinned
import io.element.android.libraries.matrix.api.timeline.TimelineProvider
interface PinnedEventsTimelineProvider : TimelineProvider
@@ -0,0 +1,19 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.
*/
package io.element.android.features.messages.api.timeline
import androidx.compose.runtime.Composable
import io.element.android.wysiwyg.utils.HtmlConverter
interface HtmlConverterProvider {
@Composable
fun Update()
fun provide(): HtmlConverter
}
@@ -0,0 +1,28 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.
*/
package io.element.android.features.messages.api.timeline.voicemessages.composer
import androidx.lifecycle.Lifecycle
import io.element.android.libraries.textcomposer.model.VoiceMessagePlayerEvent
import io.element.android.libraries.textcomposer.model.VoiceMessageRecorderEvent
sealed interface VoiceMessageComposerEvent {
data class RecorderEvent(
val recorderEvent: VoiceMessageRecorderEvent
) : VoiceMessageComposerEvent
data class PlayerEvent(
val playerEvent: VoiceMessagePlayerEvent,
) : VoiceMessageComposerEvent
data object SendVoiceMessage : VoiceMessageComposerEvent
data object DeleteVoiceMessage : VoiceMessageComposerEvent
data object AcceptPermissionRationale : VoiceMessageComposerEvent
data object DismissPermissionsRationale : VoiceMessageComposerEvent
data class LifecycleEvent(val event: Lifecycle.Event) : VoiceMessageComposerEvent
data object DismissSendFailureDialog : VoiceMessageComposerEvent
}
@@ -0,0 +1,18 @@
/*
* 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.
*/
package io.element.android.features.messages.api.timeline.voicemessages.composer
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.timeline.Timeline
fun interface VoiceMessageComposerPresenter : Presenter<VoiceMessageComposerState> {
interface Factory {
fun create(timelineMode: Timeline.Mode): VoiceMessageComposerPresenter
}
}
@@ -0,0 +1,21 @@
/*
* Copyright (c) 2025 Element Creations Ltd.
* Copyright 2023-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.
*/
package io.element.android.features.messages.api.timeline.voicemessages.composer
import androidx.compose.runtime.Stable
import io.element.android.libraries.textcomposer.model.VoiceMessageState
@Stable
data class VoiceMessageComposerState(
val voiceMessageState: VoiceMessageState,
val showPermissionRationaleDialog: Boolean,
val showSendFailureDialog: Boolean,
val keepScreenOn: Boolean,
val eventSink: (VoiceMessageComposerEvent) -> Unit,
)
@@ -0,0 +1,43 @@
/*
* 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.
*/
package io.element.android.features.messages.api.timeline.voicemessages.composer
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.libraries.designsystem.components.media.WaveFormSamples
import io.element.android.libraries.textcomposer.model.VoiceMessageState
import kotlin.time.Duration.Companion.seconds
open class VoiceMessageComposerStateProvider : PreviewParameterProvider<VoiceMessageComposerState> {
override val values: Sequence<VoiceMessageComposerState>
get() = sequenceOf(
aVoiceMessageComposerState(voiceMessageState = VoiceMessageState.Recording(duration = 61.seconds, levels = WaveFormSamples.allRangeWaveForm)),
)
}
fun aVoiceMessageComposerState(
voiceMessageState: VoiceMessageState = VoiceMessageState.Idle,
keepScreenOn: Boolean = false,
showPermissionRationaleDialog: Boolean = false,
showSendFailureDialog: Boolean = false,
) = VoiceMessageComposerState(
voiceMessageState = voiceMessageState,
showPermissionRationaleDialog = showPermissionRationaleDialog,
showSendFailureDialog = showSendFailureDialog,
keepScreenOn = keepScreenOn,
eventSink = {},
)
fun aVoiceMessagePreviewState() = VoiceMessageState.Preview(
isSending = false,
isPlaying = false,
showCursor = false,
playbackProgress = 0f,
time = 10.seconds,
waveform = WaveFormSamples.realisticWaveForm,
)