diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 2e252b07e..b31f3abd7 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -233,6 +233,7 @@ dependencies { } implementation(libs.insetter) implementation(libs.bundles.richtext) + implementation(libs.richeditor.compose) implementation(libs.aboutLibraries.compose) implementation(libs.bundles.voyager) implementation(libs.compose.materialmotion) diff --git a/app/src/main/java/eu/kanade/presentation/manga/MangaNotesScreen.kt b/app/src/main/java/eu/kanade/presentation/manga/MangaNotesScreen.kt index 2c35b5a72..77c678f7c 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/MangaNotesScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/MangaNotesScreen.kt @@ -1,52 +1,28 @@ package eu.kanade.presentation.manga -import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsetsSides -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.navigationBars import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.windowInsetsPadding -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.text.selection.SelectionContainer -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 -import androidx.compose.material.icons.filled.EditNote -import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.text.SpanStyle -import com.halilibo.richtext.markdown.Markdown -import com.halilibo.richtext.ui.RichTextStyle -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 kotlinx.collections.immutable.persistentListOf import tachiyomi.i18n.MR -import tachiyomi.presentation.core.components.material.ExtendedFloatingActionButton import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.padding import tachiyomi.presentation.core.i18n.stringResource -import tachiyomi.presentation.core.screens.EmptyScreen -import tachiyomi.presentation.core.screens.EmptyScreenAction @Composable fun MangaNotesScreen( state: MangaNotesScreenState.Success, navigateUp: () -> Unit, - beginEditing: () -> Unit, - endEditing: () -> Unit, onSave: (String) -> Unit, modifier: Modifier = Modifier, ) { @@ -60,98 +36,22 @@ fun MangaNotesScreen( scrollBehavior = scrollBehavior, ) }, - floatingActionButton = { - AnimatedVisibility( - 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, - ) - }, - onClick = { if (state.editing) endEditing() else beginEditing() }, - expanded = true, - ) - } - }, modifier = modifier .imePadding(), ) { paddingValues -> - AnimatedVisibility( - state.editing, - enter = fadeIn(), - exit = fadeOut(), - ) { - MangaNotesTextArea( - state = state, - onSave = onSave, - modifier = Modifier - .padding( - top = paddingValues.calculateTopPadding() + MaterialTheme.padding.small, - bottom = MaterialTheme.padding.small, - ) - .padding(horizontal = MaterialTheme.padding.small) - .windowInsetsPadding( - WindowInsets.navigationBars - .only(WindowInsetsSides.Bottom), - ), - ) - } - - AnimatedVisibility( - !state.editing && state.notes.isNullOrBlank(), - enter = fadeIn(), - exit = fadeOut(), - ) { - EmptyScreen( - stringRes = MR.strings.information_no_notes, - modifier = Modifier.padding(paddingValues), - actions = persistentListOf( - EmptyScreenAction( - MR.strings.action_add_notes, - Icons.Filled.EditNote, - beginEditing, - ), + MangaNotesTextArea( + state = state, + onSave = onSave, + modifier = Modifier + .padding( + top = paddingValues.calculateTopPadding() + MaterialTheme.padding.small, + bottom = MaterialTheme.padding.small, + ) + .padding(horizontal = MaterialTheme.padding.small) + .windowInsetsPadding( + WindowInsets.navigationBars + .only(WindowInsetsSides.Bottom), ), - ) - } - - AnimatedVisibility( - !state.editing && !state.notes.isNullOrBlank(), - enter = fadeIn(), - exit = fadeOut(), - ) { - SelectionContainer { - RichText( - modifier = Modifier - .verticalScroll(rememberScrollState()) - .fillMaxWidth() - .padding( - horizontal = MaterialTheme.padding.medium, - vertical = paddingValues.calculateTopPadding() + MaterialTheme.padding.medium, - ), - style = RichTextStyle( - stringStyle = RichTextStringStyle( - linkStyle = SpanStyle(color = MaterialTheme.colorScheme.primary), - ), - ), - ) { - Markdown(content = state.notes.orEmpty()) - } - } - } + ) } } diff --git a/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt b/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt index 0cd952be9..0ddfc267e 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt @@ -113,7 +113,6 @@ fun MangaScreen( onEditFetchIntervalClicked: (() -> Unit)?, onMigrateClicked: (() -> Unit)?, onNotesClicked: () -> Unit, - onNotesEditClicked: () -> Unit, // For bottom action menu onMultiBookmarkClicked: (List, bookmarked: Boolean) -> Unit, @@ -163,7 +162,6 @@ fun MangaScreen( onEditIntervalClicked = onEditFetchIntervalClicked, onMigrateClicked = onMigrateClicked, onNotesClicked = onNotesClicked, - onNotesEditClicked = onNotesEditClicked, onMultiBookmarkClicked = onMultiBookmarkClicked, onMultiMarkAsReadClicked = onMultiMarkAsReadClicked, onMarkPreviousAsReadClicked = onMarkPreviousAsReadClicked, @@ -200,7 +198,6 @@ fun MangaScreen( onEditIntervalClicked = onEditFetchIntervalClicked, onMigrateClicked = onMigrateClicked, onNotesClicked = onNotesClicked, - onNotesEditClicked = onNotesEditClicked, onMultiBookmarkClicked = onMultiBookmarkClicked, onMultiMarkAsReadClicked = onMultiMarkAsReadClicked, onMarkPreviousAsReadClicked = onMarkPreviousAsReadClicked, @@ -247,7 +244,6 @@ private fun MangaScreenSmallImpl( onEditIntervalClicked: (() -> Unit)?, onMigrateClicked: (() -> Unit)?, onNotesClicked: () -> Unit, - onNotesEditClicked: () -> Unit, // For bottom action menu onMultiBookmarkClicked: (List, bookmarked: Boolean) -> Unit, @@ -428,7 +424,7 @@ private fun MangaScreenSmallImpl( noteContent = state.manga.notes, onTagSearch = onTagSearch, onCopyTagToClipboard = onCopyTagToClipboard, - onClickNotes = onNotesEditClicked, + onClickNotes = onNotesClicked, ) } @@ -498,7 +494,6 @@ fun MangaScreenLargeImpl( onEditIntervalClicked: (() -> Unit)?, onMigrateClicked: (() -> Unit)?, onNotesClicked: () -> Unit, - onNotesEditClicked: () -> Unit, // For bottom action menu onMultiBookmarkClicked: (List, bookmarked: Boolean) -> Unit, @@ -659,7 +654,7 @@ fun MangaScreenLargeImpl( noteContent = state.manga.notes, onTagSearch = onTagSearch, onCopyTagToClipboard = onCopyTagToClipboard, - onClickNotes = onNotesEditClicked, + onClickNotes = onNotesClicked, ) } }, diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/MangaNotesDisplay.kt b/app/src/main/java/eu/kanade/presentation/manga/components/MangaNotesDisplay.kt new file mode 100644 index 000000000..7f3325b1e --- /dev/null +++ b/app/src/main/java/eu/kanade/presentation/manga/components/MangaNotesDisplay.kt @@ -0,0 +1,28 @@ +package eu.kanade.presentation.manga.components + +import androidx.compose.foundation.text.selection.SelectionContainer +import androidx.compose.material3.MaterialTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.mohamedrejeb.richeditor.annotation.ExperimentalRichTextApi +import com.mohamedrejeb.richeditor.model.rememberRichTextState +import com.mohamedrejeb.richeditor.ui.material3.RichText + +@OptIn(ExperimentalRichTextApi::class) +@Composable +fun MangaNotesDisplay( + content: String, + modifier: Modifier, +) { + val richTextState = rememberRichTextState().setHtml(html = content) + richTextState.config.linkColor = MaterialTheme.colorScheme.primary + richTextState.config.listIndent = 15 + + SelectionContainer { + RichText( + modifier = modifier, + style = MaterialTheme.typography.bodyMedium, + state = richTextState, + ) + } +} diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/MangaNotesSection.kt b/app/src/main/java/eu/kanade/presentation/manga/components/MangaNotesSection.kt index d665c433a..68e3d4e86 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/components/MangaNotesSection.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/components/MangaNotesSection.kt @@ -14,7 +14,6 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.foundation.text.selection.SelectionContainer import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.EditNote import androidx.compose.material3.HorizontalDivider @@ -25,13 +24,8 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.SpanStyle import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.unit.dp -import com.halilibo.richtext.markdown.Markdown -import com.halilibo.richtext.ui.RichTextStyle -import com.halilibo.richtext.ui.material3.RichText -import com.halilibo.richtext.ui.string.RichTextStringStyle import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.Button import tachiyomi.presentation.core.components.material.ButtonDefaults @@ -50,19 +44,10 @@ fun MangaNotesSection( horizontalAlignment = Alignment.CenterHorizontally, ) { if (!content.isNullOrBlank()) { - SelectionContainer { - RichText( - modifier = Modifier - .fillMaxWidth(), - style = RichTextStyle( - stringStyle = RichTextStringStyle( - linkStyle = SpanStyle(color = MaterialTheme.colorScheme.primary), - ), - ), - ) { - Markdown(content = content) - } - } + MangaNotesDisplay( + content = content, + modifier = modifier.fillMaxWidth(), + ) AnimatedVisibility( visible = expanded, diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/MangaNotesTextArea.kt b/app/src/main/java/eu/kanade/presentation/manga/components/MangaNotesTextArea.kt index 7737f08ac..564b7606b 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/components/MangaNotesTextArea.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/components/MangaNotesTextArea.kt @@ -1,26 +1,52 @@ package eu.kanade.presentation.manga.components import androidx.compose.animation.AnimatedVisibility -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material3.OutlinedTextField +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.isImeVisible +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.automirrored.outlined.FormatListBulleted +import androidx.compose.material.icons.outlined.FormatBold +import androidx.compose.material.icons.outlined.FormatItalic +import androidx.compose.material.icons.outlined.FormatListNumbered +import androidx.compose.material.icons.outlined.FormatSize +import androidx.compose.material.icons.outlined.FormatUnderlined +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text +import androidx.compose.material3.VerticalDivider 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.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha +import androidx.compose.ui.draw.clip import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester -import androidx.compose.ui.text.TextRange -import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.semantics.Role +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.font.FontStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.unit.dp +import com.mohamedrejeb.richeditor.model.rememberRichTextState +import com.mohamedrejeb.richeditor.ui.material3.RichTextEditor import eu.kanade.tachiyomi.ui.manga.notes.MangaNotesScreenState +import tachiyomi.i18n.MR +import tachiyomi.presentation.core.i18n.stringResource private const val MAX_LENGTH = 10_000 @@ -30,49 +56,135 @@ fun MangaNotesTextArea( onSave: (String) -> Unit, modifier: Modifier = Modifier, ) { - var text by remember { - mutableStateOf(TextFieldValue(state.notes.orEmpty(), TextRange(Int.MAX_VALUE))) - } + val richTextState = rememberRichTextState() + richTextState.config.linkColor = MaterialTheme.colorScheme.primary + richTextState.config.listIndent = 15 val focusRequester = remember { FocusRequester() } - Box( + val largeFontSize = MaterialTheme.typography.headlineMedium.fontSize + + Column( modifier = modifier .fillMaxSize(), ) { - OutlinedTextField( - value = text, - onValueChange = { if (it.text.length <= MAX_LENGTH) text = it }, - modifier = Modifier - .fillMaxSize() - .focusRequester(focusRequester), - supportingText = { - val displayWarning = text.text.length > MAX_LENGTH / 10 * 9 - if (!displayWarning) { - Text( - text = "0", - modifier = Modifier.alpha(0f), - ) - } - AnimatedVisibility( - displayWarning, - enter = fadeIn(), - exit = fadeOut(), - ) { - Text( - text = "${text.text.length} / $MAX_LENGTH", - ) - } + RichTextEditor( + state = richTextState, + textStyle = MaterialTheme.typography.bodyMedium, + maxLength = MAX_LENGTH, + placeholder = { + Text(text = stringResource(MR.strings.notes_placeholder)) }, + modifier = Modifier + .weight(1f) + .fillMaxWidth() + .focusRequester(focusRequester), ) + AnimatedVisibility( + visible = WindowInsets.isImeVisible, + ) { + LazyRow( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(2.dp), + modifier = Modifier + .padding(top = 4.dp), + ) { + item { + SlackDemoPanelButton( + onClick = { richTextState.toggleSpanStyle(SpanStyle(fontWeight = FontWeight.Bold)) }, + isSelected = richTextState.currentSpanStyle.fontWeight == FontWeight.Bold, + icon = Icons.Outlined.FormatBold, + ) + } + item { + SlackDemoPanelButton( + onClick = { richTextState.toggleSpanStyle(SpanStyle(fontStyle = FontStyle.Italic)) }, + isSelected = richTextState.currentSpanStyle.fontStyle == FontStyle.Italic, + icon = Icons.Outlined.FormatItalic, + ) + } + item { + SlackDemoPanelButton( + onClick = { + richTextState.toggleSpanStyle(SpanStyle(textDecoration = TextDecoration.Underline)) + }, + isSelected = + richTextState.currentSpanStyle.textDecoration?.contains(TextDecoration.Underline) == true, + icon = Icons.Outlined.FormatUnderlined, + ) + } + item { + VerticalDivider( + modifier = Modifier + .height(24.dp), + ) + } + item { + SlackDemoPanelButton( + onClick = { richTextState.toggleUnorderedList() }, + isSelected = richTextState.isUnorderedList, + icon = Icons.AutoMirrored.Outlined.FormatListBulleted, + ) + } + item { + SlackDemoPanelButton( + onClick = { richTextState.toggleOrderedList() }, + isSelected = richTextState.isOrderedList, + icon = Icons.Outlined.FormatListNumbered, + ) + } + item { + VerticalDivider( + modifier = Modifier + .height(24.dp), + ) + } + item { + SlackDemoPanelButton( + onClick = { richTextState.toggleSpanStyle(SpanStyle(fontSize = largeFontSize)) }, + isSelected = richTextState.currentSpanStyle.fontSize == largeFontSize, + icon = Icons.Outlined.FormatSize, + ) + } + } + } } LaunchedEffect(focusRequester) { + state.notes?.let { richTextState.setHtml(it) } focusRequester.requestFocus() } DisposableEffect(Unit) { onDispose { - onSave(text.text) + onSave(richTextState.toHtml()) } } } + +@Composable +fun SlackDemoPanelButton( + onClick: () -> Unit, + icon: ImageVector, + isSelected: Boolean, + modifier: Modifier = Modifier, +) { + Box( + modifier = modifier + .clip(RoundedCornerShape(10.dp)) + .clickable( + onClick = onClick, + enabled = true, + role = Role.Button, + ), + contentAlignment = Alignment.Center, + ) { + Icon( + icon, + contentDescription = icon.name, + tint = if (isSelected) MaterialTheme.colorScheme.onPrimary else MaterialTheme.colorScheme.primary, + modifier = Modifier + .background(color = if (isSelected) MaterialTheme.colorScheme.onBackground else Color.Transparent) + .padding(6.dp), + ) + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt index 3106cfdb0..46b7ea4c5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt @@ -166,7 +166,6 @@ class MangaScreen( navigator.push(MigrateSearchScreen(successState.manga.id)) }.takeIf { successState.manga.favorite }, onNotesClicked = { navigator.push(MangaNotesScreen(manga = successState.manga)) }, - onNotesEditClicked = { navigator.push(MangaNotesScreen(manga = successState.manga, editing = true)) }, onMultiBookmarkClicked = screenModel::bookmarkChapters, onMultiMarkAsReadClicked = screenModel::markChaptersRead, onMarkPreviousAsReadClicked = screenModel::markPreviousChapterRead, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/notes/MangaNotesScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/notes/MangaNotesScreen.kt index ea7f88db4..d97325b8e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/notes/MangaNotesScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/notes/MangaNotesScreen.kt @@ -1,6 +1,5 @@ package eu.kanade.tachiyomi.ui.manga.notes -import androidx.activity.compose.BackHandler import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue @@ -14,7 +13,6 @@ import tachiyomi.presentation.core.screens.LoadingScreen class MangaNotesScreen( private val manga: Manga, - private val editing: Boolean = false, ) : Screen() { @Composable override fun Content() { @@ -23,7 +21,6 @@ class MangaNotesScreen( val screenModel = rememberScreenModel { MangaNotesScreenModel( manga = manga, - editing = editing, ) } val state by screenModel.state.collectAsState() @@ -35,22 +32,9 @@ class MangaNotesScreen( 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) }, ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/notes/MangaNotesScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/notes/MangaNotesScreenModel.kt index ea3b9f680..af38396d9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/notes/MangaNotesScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/notes/MangaNotesScreenModel.kt @@ -12,7 +12,6 @@ import uy.kohesive.injekt.api.get class MangaNotesScreenModel( val manga: Manga, - editing: Boolean, private val setMangaNotes: SetMangaNotes = Injekt.get(), ) : StateScreenModel(MangaNotesScreenState.Loading) { @@ -24,29 +23,10 @@ class MangaNotesScreenModel( MangaNotesScreenState.Success( manga = manga, notes = manga.notes, - editing = editing, ) } } - fun beginEditing() { - mutableState.update { - when (it) { - MangaNotesScreenState.Loading -> it - is MangaNotesScreenState.Success -> it.copy(editing = true) - } - } - } - - fun endEditing() { - mutableState.update { - when (it) { - MangaNotesScreenState.Loading -> it - is MangaNotesScreenState.Success -> it.copy(editing = false) - } - } - } - fun saveText(content: String) { // don't save what isn't modified if (content == successState?.notes) return @@ -75,7 +55,5 @@ sealed interface MangaNotesScreenState { data class Success( val manga: Manga, val notes: String?, - - val editing: Boolean = false, ) : MangaNotesScreenState } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7fd313312..f160218fa 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -56,6 +56,8 @@ natural-comparator = "com.github.gpanther:java-nat-sort:natural-comparator-1.1" richtext-commonmark = { module = "com.halilibo.compose-richtext:richtext-commonmark", version.ref = "richtext" } richtext-m3 = { module = "com.halilibo.compose-richtext:richtext-ui-material3", version.ref = "richtext" } +richeditor-compose = "com.mohamedrejeb.richeditor:richeditor-compose:1.0.0-rc06" + material = "com.google.android.material:material:1.12.0" flexible-adapter-core = "com.github.arkon.FlexibleAdapter:flexible-adapter:c8013533" photoview = "com.github.chrisbanes:PhotoView:2.3.0" diff --git a/i18n/src/commonMain/moko-resources/base/strings.xml b/i18n/src/commonMain/moko-resources/base/strings.xml index 65bd59ffc..5ea7267d1 100644 --- a/i18n/src/commonMain/moko-resources/base/strings.xml +++ b/i18n/src/commonMain/moko-resources/base/strings.xml @@ -146,9 +146,9 @@ Move series to top Move to bottom Move series to bottom - Notes - Add Notes - Edit Notes + Note + Add Note + Edit Note Install Share Save @@ -915,7 +915,7 @@ Failed to bypass Cloudflare Tap here for help with Cloudflare *required - There are no notes here yet! + No notes WebView is required for the app to function @@ -956,4 +956,7 @@ HTTP %d, check website in WebView No Internet connection Couldn\'t reach %s + + + My analysis of the story begins with ontological antirealism, that is to say...