Merge branch 'claude/admiring-mahavira-a862d1' into artifacts
This commit is contained in:
@@ -14,4 +14,7 @@ interface MantraArtifactVersionDao {
|
||||
|
||||
@Query("SELECT * FROM MantraArtifactVersion WHERE artifactId = :artifactId ORDER BY createdAt DESC")
|
||||
suspend fun getArtifactVersionsByArtifactId(artifactId: String): List<MantraArtifactVersion>
|
||||
|
||||
@Query("SELECT * FROM MantraArtifactVersion WHERE id = :id")
|
||||
suspend fun getArtifactVersionById(id: String): MantraArtifactVersion?
|
||||
}
|
||||
@@ -14,4 +14,7 @@ interface MantraTranslationChapterDao {
|
||||
|
||||
@Query("SELECT * FROM MantraTranslationChapter WHERE translationArtifactVersionId = :translationArtifactVersionId ORDER BY `index` ASC")
|
||||
suspend fun getTranslationChaptersByTranslationArtifactVersionId(translationArtifactVersionId: String): List<MantraTranslationChapter>
|
||||
|
||||
@Query("SELECT * FROM MantraTranslationChapter WHERE id = :id")
|
||||
suspend fun getTranslationChapterById(id: String): MantraTranslationChapter?
|
||||
}
|
||||
@@ -41,6 +41,9 @@ class DatabaseMantraRepository(
|
||||
override suspend fun getArtifactVersions(artifactId: String): List<MantraArtifactVersion> =
|
||||
database.mantraArtifactVersionDao().getArtifactVersionsByArtifactId(artifactId)
|
||||
|
||||
override suspend fun getArtifactVersion(id: String): MantraArtifactVersion? =
|
||||
database.mantraArtifactVersionDao().getArtifactVersionById(id)
|
||||
|
||||
override suspend fun getChaptersForArtifact(artifactId: String): List<MantraChapter> =
|
||||
database.mantraChapterDao().getChaptersByArtifactId(artifactId)
|
||||
|
||||
@@ -161,6 +164,9 @@ class DatabaseMantraRepository(
|
||||
override suspend fun getTranslation(id: String): MantraTranslationArtifactVersion? =
|
||||
database.mantraTranslationArtifactVersionDao().getTranslationById(id)
|
||||
|
||||
override suspend fun getTranslationChapter(id: String): MantraTranslationChapter? =
|
||||
database.mantraTranslationChapterDao().getTranslationChapterById(id)
|
||||
|
||||
override suspend fun getTranslationChapters(translationArtifactVersionId: String): List<MantraTranslationChapter> =
|
||||
database.mantraTranslationChapterDao().getTranslationChaptersByTranslationArtifactVersionId(translationArtifactVersionId)
|
||||
|
||||
@@ -251,6 +257,9 @@ class DatabaseMantraRepository(
|
||||
override suspend fun getDialects(chatRoomId: String): List<MantraDialect> =
|
||||
database.mantraDialectDao().getDialectsByChatRoomId(chatRoomId)
|
||||
|
||||
override suspend fun getDialect(id: String): MantraDialect? =
|
||||
database.mantraDialectDao().getDialectById(id)
|
||||
|
||||
override suspend fun addDialect(
|
||||
name: String,
|
||||
country: String,
|
||||
|
||||
@@ -18,6 +18,8 @@ interface MantraRepository {
|
||||
|
||||
suspend fun getArtifactVersions(artifactId: String): List<MantraArtifactVersion>
|
||||
|
||||
suspend fun getArtifactVersion(id: String): MantraArtifactVersion?
|
||||
|
||||
suspend fun getChaptersForArtifact(artifactId: String): List<MantraChapter>
|
||||
|
||||
suspend fun getChapter(id: String): MantraChapter?
|
||||
@@ -28,6 +30,8 @@ interface MantraRepository {
|
||||
|
||||
suspend fun getTranslation(id: String): MantraTranslationArtifactVersion?
|
||||
|
||||
suspend fun getTranslationChapter(id: String): MantraTranslationChapter?
|
||||
|
||||
suspend fun getTranslationChapters(translationArtifactVersionId: String): List<MantraTranslationChapter>
|
||||
|
||||
suspend fun getTranslationChunks(translationChapterId: String): List<MantraTranslationChunk>
|
||||
@@ -62,6 +66,8 @@ interface MantraRepository {
|
||||
|
||||
suspend fun getDialects(chatRoomId: String): List<MantraDialect>
|
||||
|
||||
suspend fun getDialect(id: String): MantraDialect?
|
||||
|
||||
suspend fun addDialect(
|
||||
name: String,
|
||||
country: String,
|
||||
@@ -99,6 +105,8 @@ interface MantraRepository {
|
||||
|
||||
override suspend fun getArtifactVersions(artifactId: String): List<MantraArtifactVersion> = emptyList()
|
||||
|
||||
override suspend fun getArtifactVersion(id: String): MantraArtifactVersion? = null
|
||||
|
||||
override suspend fun getChaptersForArtifact(artifactId: String): List<MantraChapter> = emptyList()
|
||||
|
||||
override suspend fun getChapter(id: String): MantraChapter? = null
|
||||
@@ -109,6 +117,8 @@ interface MantraRepository {
|
||||
|
||||
override suspend fun getTranslation(id: String): MantraTranslationArtifactVersion? = null
|
||||
|
||||
override suspend fun getTranslationChapter(id: String): MantraTranslationChapter? = null
|
||||
|
||||
override suspend fun getTranslationChapters(translationArtifactVersionId: String): List<MantraTranslationChapter> = emptyList()
|
||||
|
||||
override suspend fun getTranslationChunks(translationChapterId: String): List<MantraTranslationChunk> = emptyList()
|
||||
@@ -130,6 +140,8 @@ interface MantraRepository {
|
||||
|
||||
override suspend fun getDialects(chatRoomId: String): List<MantraDialect> = emptyList()
|
||||
|
||||
override suspend fun getDialect(id: String): MantraDialect? = null
|
||||
|
||||
override suspend fun addDialect(
|
||||
name: String,
|
||||
country: String,
|
||||
|
||||
@@ -0,0 +1,238 @@
|
||||
package press.mantra.compose.ui.composable
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.IntrinsicSize
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxHeight
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.VerticalDivider
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import press.mantra.compose.database.model.MantraChunk
|
||||
import press.mantra.compose.repository.MantraRepository
|
||||
import press.mantra.compose.ui.composable.widgets.LoadingDataIndicator
|
||||
import press.mantra.compose.ui.theme.TorchTheme
|
||||
import press.mantra.compose.ui.view.model.TranslationChapterViewModel
|
||||
import press.mantra.compose.ui.view.state.ChunkTranslationPair
|
||||
import press.mantra.compose.ui.view.state.TranslationChapterUIState
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun TranslationChapterScreen(
|
||||
activeUserPublicKey: HexKey,
|
||||
translationChapterId: String,
|
||||
chatRoomId: String,
|
||||
relayHint: String?,
|
||||
initialTranslationChapterUIState: TranslationChapterUIState = TranslationChapterUIState.Loading,
|
||||
mantraRepository: MantraRepository,
|
||||
onNavigateBack: () -> Unit,
|
||||
) {
|
||||
val translationChapterViewModel: TranslationChapterViewModel = viewModel(
|
||||
factory = TranslationChapterViewModel.factory(
|
||||
activeUserPublicKey = activeUserPublicKey,
|
||||
translationChapterId = translationChapterId,
|
||||
chatRoomId = chatRoomId,
|
||||
relayHint = relayHint,
|
||||
initialTranslationChapterUIState = initialTranslationChapterUIState,
|
||||
mantraRepository = mantraRepository,
|
||||
)
|
||||
)
|
||||
|
||||
when (val translationChapterUIState = translationChapterViewModel.translationChapterUIState) {
|
||||
is TranslationChapterUIState.Error -> {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Spacer(modifier = Modifier.height(50.dp))
|
||||
Text(text = translationChapterUIState.message)
|
||||
}
|
||||
}
|
||||
|
||||
is TranslationChapterUIState.Loaded -> {
|
||||
Scaffold(
|
||||
topBar = {
|
||||
TopAppBar(
|
||||
title = { Text("Chapter translation") },
|
||||
navigationIcon = {
|
||||
IconButton(onClick = onNavigateBack) {
|
||||
Icon(
|
||||
Icons.AutoMirrored.Filled.ArrowBack,
|
||||
contentDescription = "Back"
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
) { innerPadding ->
|
||||
LazyColumn(
|
||||
modifier = Modifier.padding(innerPadding).fillMaxSize()
|
||||
) {
|
||||
// Header row: dialect names.
|
||||
item {
|
||||
TableRow(
|
||||
left = {
|
||||
Text(
|
||||
text = translationChapterUIState.originalDialectName,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
},
|
||||
right = {
|
||||
Text(
|
||||
text = translationChapterUIState.translationDialectName,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
},
|
||||
)
|
||||
HorizontalDivider()
|
||||
}
|
||||
|
||||
if (translationChapterUIState.rows.isEmpty()) {
|
||||
item {
|
||||
Box(
|
||||
modifier = Modifier.fillMaxWidth().padding(16.dp),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text("This chapter has no chunks.")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
items(
|
||||
items = translationChapterUIState.rows,
|
||||
key = { pair -> pair.originalChunk.id }
|
||||
) { pair ->
|
||||
ChunkTranslationRow(pair)
|
||||
HorizontalDivider()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TranslationChapterUIState.Loading -> {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth().padding(20.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(20.dp)
|
||||
) {
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
Text(
|
||||
text = "Chapter Translation",
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
LoadingDataIndicator(fillScreen = false)
|
||||
Spacer(modifier = Modifier.weight(2f))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(true) {
|
||||
if (initialTranslationChapterUIState == TranslationChapterUIState.Loading) {
|
||||
translationChapterViewModel.initiateTranslationChapter()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ChunkTranslationRow(pair: ChunkTranslationPair) {
|
||||
val translated = pair.translationChunk?.text?.takeIf { it.isNotBlank() }
|
||||
TableRow(
|
||||
left = { Text(pair.originalChunk.text) },
|
||||
right = {
|
||||
if (translated != null) {
|
||||
Text(translated)
|
||||
} else {
|
||||
// No translation yet: show the original as a greyed-out placeholder.
|
||||
Text(
|
||||
text = pair.originalChunk.text,
|
||||
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f)
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TableRow(
|
||||
left: @Composable () -> Unit,
|
||||
right: @Composable () -> Unit,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth().height(IntrinsicSize.Min)
|
||||
) {
|
||||
Box(modifier = Modifier.weight(1f).padding(12.dp)) { left() }
|
||||
VerticalDivider(modifier = Modifier.fillMaxHeight())
|
||||
Box(modifier = Modifier.weight(1f).padding(12.dp)) { right() }
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun TranslationChapterScreenPreview() {
|
||||
TorchTheme {
|
||||
Surface(modifier = Modifier.fillMaxSize()) {
|
||||
TranslationChapterScreen(
|
||||
activeUserPublicKey = "",
|
||||
translationChapterId = "translationChapterId",
|
||||
chatRoomId = "chatRoomId",
|
||||
relayHint = null,
|
||||
initialTranslationChapterUIState = TranslationChapterUIState.Loaded(
|
||||
originalDialectName = "English",
|
||||
translationDialectName = "Sesotho",
|
||||
rows = listOf(
|
||||
ChunkTranslationPair(
|
||||
originalChunk = sampleChunk("c1", "When he was nearly thirteen, my brother Jem got his arm badly broken."),
|
||||
translationChunk = null
|
||||
),
|
||||
ChunkTranslationPair(
|
||||
originalChunk = sampleChunk("c2", "When enough years had gone by to enable us to look back on them..."),
|
||||
translationChunk = null
|
||||
),
|
||||
)
|
||||
),
|
||||
mantraRepository = MantraRepository.NO_OP_MANTRA_REPOSITORY,
|
||||
onNavigateBack = {}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun sampleChunk(id: String, text: String) = MantraChunk(
|
||||
id = id,
|
||||
chapterId = "chapterId",
|
||||
publicKey = "author",
|
||||
text = text,
|
||||
index = 0,
|
||||
wordCount = 0,
|
||||
characterCount = 0,
|
||||
signature = "",
|
||||
chatRoomId = "chatRoomId"
|
||||
)
|
||||
@@ -34,6 +34,8 @@ import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import press.mantra.compose.database.model.MantraTranslationArtifactVersion
|
||||
import press.mantra.compose.repository.MantraRepository
|
||||
import press.mantra.compose.ui.composable.navigation.routes.Route
|
||||
import press.mantra.compose.ui.composable.navigation.routes.TranslationChapterRoute
|
||||
import press.mantra.compose.ui.composable.widgets.DetailRow
|
||||
import press.mantra.compose.ui.composable.widgets.LoadingDataIndicator
|
||||
import press.mantra.compose.ui.theme.TorchTheme
|
||||
@@ -49,6 +51,7 @@ fun TranslationDetailScreen(
|
||||
relayHint: String?,
|
||||
initialTranslationDetailUIState: TranslationDetailUIState = TranslationDetailUIState.Loading,
|
||||
mantraRepository: MantraRepository,
|
||||
onNavigateToRoute: (Route) -> Unit,
|
||||
onNavigateBack: () -> Unit,
|
||||
) {
|
||||
val translationDetailViewModel: TranslationDetailViewModel = viewModel(
|
||||
@@ -129,7 +132,18 @@ fun TranslationDetailScreen(
|
||||
items = translationDetailUIState.chapters,
|
||||
key = { progress -> progress.chapter.id }
|
||||
) { progress ->
|
||||
Card {
|
||||
Card(
|
||||
onClick = {
|
||||
onNavigateToRoute.invoke(
|
||||
TranslationChapterRoute(
|
||||
activeUserPublicKey = activeUserPublicKey,
|
||||
translationChapterId = progress.chapter.id,
|
||||
chatRoomId = chatRoomId,
|
||||
relayHint = relayHint
|
||||
)
|
||||
)
|
||||
}
|
||||
) {
|
||||
ListItem(
|
||||
leadingContent = {
|
||||
Icon(
|
||||
@@ -198,6 +212,7 @@ private fun TranslationDetailScreenPreview() {
|
||||
)
|
||||
),
|
||||
mantraRepository = MantraRepository.NO_OP_MANTRA_REPOSITORY,
|
||||
onNavigateToRoute = {},
|
||||
onNavigateBack = {}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -93,11 +93,13 @@ import press.mantra.compose.ui.composable.navigation.routes.AddChapterRoute
|
||||
import press.mantra.compose.ui.composable.navigation.routes.AddTranslationRoute
|
||||
import press.mantra.compose.ui.composable.navigation.routes.ArtifactDetailRoute
|
||||
import press.mantra.compose.ui.composable.navigation.routes.ChapterDetailRoute
|
||||
import press.mantra.compose.ui.composable.navigation.routes.TranslationChapterRoute
|
||||
import press.mantra.compose.ui.composable.navigation.routes.TranslationDetailRoute
|
||||
import press.mantra.compose.ui.composable.ArtifactDetailScreen
|
||||
import press.mantra.compose.ui.composable.AddChapterScreen
|
||||
import press.mantra.compose.ui.composable.AddTranslationScreen
|
||||
import press.mantra.compose.ui.composable.ChapterDetailScreen
|
||||
import press.mantra.compose.ui.composable.TranslationChapterScreen
|
||||
import press.mantra.compose.ui.composable.TranslationDetailScreen
|
||||
|
||||
@Composable
|
||||
@@ -727,6 +729,25 @@ fun MantraNavHost(
|
||||
chatRoomId = route.chatRoomId,
|
||||
relayHint = route.relayHint,
|
||||
mantraRepository = databaseMantraRepository,
|
||||
onNavigateToRoute = { actionRoute ->
|
||||
navController.navigate(
|
||||
route = actionRoute
|
||||
)
|
||||
},
|
||||
onNavigateBack = {
|
||||
navController.popBackStack()
|
||||
}
|
||||
)
|
||||
}
|
||||
composable<TranslationChapterRoute> { backStackEntry ->
|
||||
val route = backStackEntry.toRoute<TranslationChapterRoute>()
|
||||
|
||||
TranslationChapterScreen(
|
||||
activeUserPublicKey = route.activeUserPublicKey,
|
||||
translationChapterId = route.translationChapterId,
|
||||
chatRoomId = route.chatRoomId,
|
||||
relayHint = route.relayHint,
|
||||
mantraRepository = databaseMantraRepository,
|
||||
onNavigateBack = {
|
||||
navController.popBackStack()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package press.mantra.compose.ui.composable.navigation.routes
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class TranslationChapterRoute(
|
||||
val activeUserPublicKey: String,
|
||||
val translationChapterId: String,
|
||||
val chatRoomId: String,
|
||||
val relayHint: String?
|
||||
): Route()
|
||||
@@ -0,0 +1,98 @@
|
||||
package press.mantra.compose.ui.view.model
|
||||
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.viewmodel.initializer
|
||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||
import co.touchlab.kermit.Logger
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.IO
|
||||
import kotlinx.coroutines.launch
|
||||
import press.mantra.compose.repository.MantraRepository
|
||||
import press.mantra.compose.ui.view.state.ChunkTranslationPair
|
||||
import press.mantra.compose.ui.view.state.TranslationChapterUIState
|
||||
|
||||
class TranslationChapterViewModel(
|
||||
val translationChapterId: String,
|
||||
val chatRoomId: String,
|
||||
val activeUserPublicKey: HexKey,
|
||||
val relayHint: String?,
|
||||
initialTranslationChapterUIState: TranslationChapterUIState,
|
||||
val mantraRepository: MantraRepository,
|
||||
): ViewModel() {
|
||||
|
||||
var translationChapterUIState: TranslationChapterUIState by mutableStateOf(initialTranslationChapterUIState)
|
||||
private set
|
||||
|
||||
private val logger = Logger.withTag(TAG)
|
||||
|
||||
fun initiateTranslationChapter() {
|
||||
logger.d("initiateTranslationChapter: $translationChapterId")
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
val translationChapter = mantraRepository.getTranslationChapter(translationChapterId)
|
||||
val sourceChapter = translationChapter?.let { mantraRepository.getChapter(it.chapterId) }
|
||||
|
||||
translationChapterUIState = if (translationChapter == null || sourceChapter == null) {
|
||||
TranslationChapterUIState.Error("Couldn't find the translation chapter")
|
||||
} else {
|
||||
// Original dialect: source chapter -> version -> artifact -> dialect.
|
||||
val originalDialectName = mantraRepository.getArtifactVersion(sourceChapter.artifactVersionId)
|
||||
?.let { mantraRepository.getArtifact(it.artifactId) }
|
||||
?.let { mantraRepository.getDialect(it.dialectId) }
|
||||
?.name ?: "Original"
|
||||
|
||||
// Translation dialect: translation version -> dialect.
|
||||
val translationDialectName = mantraRepository.getTranslation(translationChapter.translationArtifactVersionId)
|
||||
?.let { mantraRepository.getDialect(it.dialectId) }
|
||||
?.name ?: "Translation"
|
||||
|
||||
// Pair each original chunk with its translation chunk (by chunkId).
|
||||
val translationChunksByChunkId = mantraRepository
|
||||
.getTranslationChunks(translationChapter.id)
|
||||
.associateBy { it.chunkId }
|
||||
|
||||
val rows = mantraRepository.getChunksForChapter(sourceChapter.id).map { originalChunk ->
|
||||
ChunkTranslationPair(
|
||||
originalChunk = originalChunk,
|
||||
translationChunk = translationChunksByChunkId[originalChunk.id],
|
||||
)
|
||||
}
|
||||
|
||||
TranslationChapterUIState.Loaded(
|
||||
originalDialectName = originalDialectName,
|
||||
translationDialectName = translationDialectName,
|
||||
rows = rows,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "TranslationChapterViewModel"
|
||||
|
||||
fun factory(
|
||||
activeUserPublicKey: HexKey,
|
||||
translationChapterId: String,
|
||||
chatRoomId: String,
|
||||
relayHint: String?,
|
||||
initialTranslationChapterUIState: TranslationChapterUIState = TranslationChapterUIState.Loading,
|
||||
mantraRepository: MantraRepository,
|
||||
): ViewModelProvider.Factory = viewModelFactory {
|
||||
initializer {
|
||||
TranslationChapterViewModel(
|
||||
activeUserPublicKey = activeUserPublicKey,
|
||||
translationChapterId = translationChapterId,
|
||||
chatRoomId = chatRoomId,
|
||||
relayHint = relayHint,
|
||||
initialTranslationChapterUIState = initialTranslationChapterUIState,
|
||||
mantraRepository = mantraRepository,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package press.mantra.compose.ui.view.state
|
||||
|
||||
import press.mantra.compose.database.model.MantraChunk
|
||||
import press.mantra.compose.database.model.MantraTranslationChunk
|
||||
|
||||
/**
|
||||
* An original chunk paired with its translation chunk. [translationChunk] is
|
||||
* null (or has blank text) when the chunk hasn't been translated yet, in which
|
||||
* case the UI shows the original text as a greyed-out placeholder.
|
||||
*/
|
||||
data class ChunkTranslationPair(
|
||||
val originalChunk: MantraChunk,
|
||||
val translationChunk: MantraTranslationChunk?,
|
||||
)
|
||||
|
||||
sealed interface TranslationChapterUIState {
|
||||
data class Loaded(
|
||||
val originalDialectName: String,
|
||||
val translationDialectName: String,
|
||||
val rows: List<ChunkTranslationPair> = emptyList(),
|
||||
): TranslationChapterUIState
|
||||
|
||||
data class Error(
|
||||
val message: String
|
||||
): TranslationChapterUIState
|
||||
|
||||
data object Loading: TranslationChapterUIState
|
||||
}
|
||||
Reference in New Issue
Block a user