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.fadeIn
import androidx.compose.animation.fadeOut import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding 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.Icons
import androidx.compose.material.icons.filled.Check import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Edit 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 com.halilibo.richtext.ui.string.RichTextStringStyle
import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.components.AppBarTitle import eu.kanade.presentation.components.AppBarTitle
import eu.kanade.presentation.manga.components.MangaNotesTextArea
import eu.kanade.tachiyomi.ui.manga.notes.MangaNotesScreenState import eu.kanade.tachiyomi.ui.manga.notes.MangaNotesScreenState
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton
@ -34,6 +38,7 @@ fun MangaNotesScreen(
navigateUp: () -> Unit, navigateUp: () -> Unit,
beginEditing: () -> Unit, beginEditing: () -> Unit,
endEditing: () -> Unit, endEditing: () -> Unit,
onSave: (String) -> Unit,
) { ) {
Scaffold( Scaffold(
topBar = { scrollBehavior -> topBar = { scrollBehavior ->
@ -50,19 +55,40 @@ fun MangaNotesScreen(
true, true,
enter = fadeIn(), enter = fadeIn(),
exit = fadeOut(), exit = fadeOut(),
modifier = Modifier
.imePadding(),
) { ) {
ExtendedFloatingActionButton( ExtendedFloatingActionButton(
text = { text = {
Text(text = stringResource(if (state.editing) MR.strings.action_apply else MR.strings.action_edit)) 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() }, onClick = { if (state.editing) endEditing() else beginEditing() },
expanded = true, expanded = true,
) )
} }
}, },
) { paddingValues -> ) { 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( EmptyScreen(
stringRes = MR.strings.information_no_notes, stringRes = MR.strings.information_no_notes,
modifier = Modifier.padding(paddingValues), modifier = Modifier.padding(paddingValues),
@ -72,6 +98,7 @@ fun MangaNotesScreen(
RichText( RichText(
modifier = Modifier modifier = Modifier
.verticalScroll(rememberScrollState())
.fillMaxWidth() .fillMaxWidth()
.padding( .padding(
horizontal = MaterialTheme.padding.small, horizontal = MaterialTheme.padding.small,
@ -85,5 +112,7 @@ fun MangaNotesScreen(
) { ) {
Markdown(content = state.content) 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 package eu.kanade.tachiyomi.ui.manga.notes
import androidx.activity.compose.BackHandler
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
@ -32,11 +33,23 @@ class MangaNotesScreen(private val mangaId: Long) : Screen() {
val successState = state as MangaNotesScreenState.Success val successState = state as MangaNotesScreenState.Success
BackHandler(
onBack = {
if (!successState.editing) {
navigator.pop()
return@BackHandler
}
screenModel.endEditing()
},
)
MangaNotesScreen( MangaNotesScreen(
state = successState, state = successState,
navigateUp = navigator::pop, navigateUp = navigator::pop,
beginEditing = { screenModel.beginEditing() }, beginEditing = { screenModel.beginEditing() },
endEditing = { screenModel.endEditing() }, 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 { sealed interface MangaNotesScreenState {
@ -66,10 +77,5 @@ sealed interface MangaNotesScreenState {
val title: String, val title: String,
val editing: Boolean = false, val editing: Boolean = false,
) : MangaNotesScreenState { ) : MangaNotesScreenState
val isEmpty: Boolean
get() = content.isNullOrEmpty()
}
} }