Add the text editor

pending work is to save the notes and make it work with the backup
This commit is contained in:
imkunet 2024-02-18 18:07:40 -05:00 committed by imkunet
parent 28c23d184a
commit 309086920c
No known key found for this signature in database
GPG Key ID: 32E0ECFB90A68C42
4 changed files with 109 additions and 8 deletions

View File

@ -4,7 +4,10 @@ import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Edit
@ -20,6 +23,7 @@ import com.halilibo.richtext.ui.material3.RichText
import com.halilibo.richtext.ui.string.RichTextStringStyle
import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.components.AppBarTitle
import eu.kanade.presentation.manga.components.MangaNotesTextArea
import eu.kanade.tachiyomi.ui.manga.notes.MangaNotesScreenState
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton
@ -34,6 +38,7 @@ fun MangaNotesScreen(
navigateUp: () -> Unit,
beginEditing: () -> Unit,
endEditing: () -> Unit,
onSave: (String) -> Unit,
) {
Scaffold(
topBar = { scrollBehavior ->
@ -50,19 +55,40 @@ fun MangaNotesScreen(
true,
enter = fadeIn(),
exit = fadeOut(),
modifier = Modifier
.imePadding(),
) {
ExtendedFloatingActionButton(
text = {
Text(text = stringResource(if (state.editing) MR.strings.action_apply else MR.strings.action_edit))
},
icon = { Icon(imageVector = if (state.editing) Icons.Filled.Check else Icons.Filled.Edit, contentDescription = null) },
icon = {
Icon(
imageVector = if (state.editing) Icons.Filled.Check else Icons.Filled.Edit,
contentDescription = null,
)
},
onClick = { if (state.editing) endEditing() else beginEditing() },
expanded = true,
)
}
},
) { paddingValues ->
if (state.isEmpty || state.content == null) {
if (state.editing) {
MangaNotesTextArea(
modifier = Modifier
.padding(
top = paddingValues.calculateTopPadding() + MaterialTheme.padding.small,
bottom = MaterialTheme.padding.large,
)
.padding(horizontal = MaterialTheme.padding.small),
state = state,
onSave = onSave,
)
return@Scaffold
}
if (state.content == null) {
EmptyScreen(
stringRes = MR.strings.information_no_notes,
modifier = Modifier.padding(paddingValues),
@ -72,6 +98,7 @@ fun MangaNotesScreen(
RichText(
modifier = Modifier
.verticalScroll(rememberScrollState())
.fillMaxWidth()
.padding(
horizontal = MaterialTheme.padding.small,
@ -85,5 +112,7 @@ fun MangaNotesScreen(
) {
Markdown(content = state.content)
}
return@Scaffold
}
}

View File

@ -0,0 +1,53 @@
package eu.kanade.presentation.manga.components
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.imePadding
import androidx.compose.material3.OutlinedTextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import eu.kanade.tachiyomi.ui.manga.notes.MangaNotesScreenState
@Composable
fun MangaNotesTextArea(
modifier: Modifier = Modifier,
state: MangaNotesScreenState.Success,
onSave: (String) -> Unit,
) {
var text by remember { mutableStateOf(state.content.orEmpty()) }
val focusRequester = remember { FocusRequester() }
Column(
modifier = modifier
.fillMaxSize()
.imePadding(),
) {
OutlinedTextField(
value = text,
onValueChange = { text = it },
modifier = Modifier
.fillMaxWidth()
.weight(1f)
.focusRequester(focusRequester),
)
}
LaunchedEffect(focusRequester) {
focusRequester.requestFocus()
}
DisposableEffect(Unit) {
onDispose {
onSave(text)
}
}
}

View File

@ -1,5 +1,6 @@
package eu.kanade.tachiyomi.ui.manga.notes
import androidx.activity.compose.BackHandler
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.collectAsState
@ -32,11 +33,23 @@ class MangaNotesScreen(private val mangaId: Long) : Screen() {
val successState = state as MangaNotesScreenState.Success
BackHandler(
onBack = {
if (!successState.editing) {
navigator.pop()
return@BackHandler
}
screenModel.endEditing()
},
)
MangaNotesScreen(
state = successState,
navigateUp = navigator::pop,
beginEditing = { screenModel.beginEditing() },
endEditing = { screenModel.endEditing() },
onSave = { screenModel.saveText(it) }
)
}
}

View File

@ -53,6 +53,17 @@ class MangaNotesScreenModel(
}
}
}
fun saveText(content: String) {
mutableState.update {
when (it) {
MangaNotesScreenState.Loading -> it
is MangaNotesScreenState.Success -> it.copy(content = content)
}
}
// do the magic to set it backend
}
}
sealed interface MangaNotesScreenState {
@ -66,10 +77,5 @@ sealed interface MangaNotesScreenState {
val title: String,
val editing: Boolean = false,
) : MangaNotesScreenState {
val isEmpty: Boolean
get() = content.isNullOrEmpty()
}
) : MangaNotesScreenState
}