diff --git a/app/src/main/java/org/zotero/android/pdf/annotation/PdfAnnotationComponents.kt b/app/src/main/java/org/zotero/android/pdf/annotation/PdfAnnotationComponents.kt new file mode 100644 index 00000000..f2eb6a04 --- /dev/null +++ b/app/src/main/java/org/zotero/android/pdf/annotation/PdfAnnotationComponents.kt @@ -0,0 +1,174 @@ +package org.zotero.android.pdf.annotation + +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.FlowRow +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Text +import androidx.compose.material.ripple.rememberRipple +import androidx.compose.material3.Slider +import androidx.compose.material3.SliderDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.drawscope.Stroke +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import org.zotero.android.architecture.ui.CustomLayoutSize +import org.zotero.android.uicomponents.Strings +import org.zotero.android.uicomponents.foundation.safeClickable +import org.zotero.android.uicomponents.theme.CustomPalette +import org.zotero.android.uicomponents.theme.CustomTheme + +@Composable +internal fun ColorPicker( + viewState: PdfAnnotationViewState, + viewModel: PdfAnnotationViewModel +) { + val selectedColor = viewState.color + FlowRow( + modifier = Modifier.padding(horizontal = 10.dp), + ) { + viewState.colors.forEach { listColorHex -> + FilterCircle( + hex = listColorHex, + isSelected = listColorHex == selectedColor, + onClick = { viewModel.onColorSelected(listColorHex) }) + } + } +} + +@Composable +internal fun FilterCircle(hex: String, isSelected: Boolean, onClick: () -> Unit) { + val color = android.graphics.Color.parseColor(hex) + Canvas(modifier = Modifier + .padding(4.dp) + .size(32.dp) + .clickable( + interactionSource = remember { MutableInteractionSource() }, + indication = null, + onClick = onClick + ), onDraw = { + drawCircle(color = Color(color)) + if (isSelected) { + drawCircle( + color = CustomPalette.White, + radius = 12.dp.toPx(), + style = Stroke(width = 3.dp.toPx()) + ) + } + }) +} + +@Composable +internal fun SizeSelector( + viewState: PdfAnnotationViewState, + viewModel: PdfAnnotationViewModel, + layoutType: CustomLayoutSize.LayoutType, +) { + Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { + Text( + modifier = Modifier.padding(horizontal = 10.dp), + text = stringResource(id = Strings.size), + color = CustomTheme.colors.pdfSizePickerColor, + style = CustomTheme.typography.default, + fontSize = layoutType.calculatePdfSidebarTextSize(), + ) + Slider( + modifier = Modifier.weight(1f), + value = viewState.size, + onValueChange = { viewModel.onSizeChanged(it) }, + colors = SliderDefaults.colors( + activeTrackColor = CustomTheme.colors.zoteroDefaultBlue, + thumbColor = CustomTheme.colors.zoteroDefaultBlue, + ), + valueRange = 0.5f..25f + ) + Text( + modifier = Modifier.padding(horizontal = 10.dp), + text = String.format("%.1f", viewState.size), + color = CustomTheme.colors.pdfSizePickerColor, + style = CustomTheme.typography.default, + fontSize = layoutType.calculatePdfSidebarTextSize(), + ) + } +} + +@Composable +internal fun FontSizeSelector( + fontSize: Float, + onFontSizeDecrease: () -> Unit, + onFontSizeIncrease: () -> Unit, +) { + Box( + modifier = Modifier + .fillMaxWidth() + .height(38.dp) + .padding(horizontal = 16.dp), + ) { + Row(modifier = Modifier.align(Alignment.CenterStart), verticalAlignment = Alignment.CenterVertically) { + Text( + text = String.format("%.1f", fontSize), + color = CustomTheme.colors.defaultTextColor, + style = CustomTheme.typography.default, + fontSize = 16.sp, + ) + Spacer(modifier = Modifier.width(2.dp)) + Text( + text = "pt", + color = CustomTheme.colors.pdfSizePickerColor, + style = CustomTheme.typography.default, + fontSize = 16.sp, + ) + } + + Row(modifier = Modifier.align(Alignment.CenterEnd)) { + FontSizeChangeButton(text = "-", onClick = onFontSizeDecrease) + Spacer(modifier = Modifier.width(2.dp)) + FontSizeChangeButton(text = "+", onClick = onFontSizeIncrease) + } + } +} + +@Composable +private fun FontSizeChangeButton(text: String, onClick: (() -> Unit)) { + val roundCornerShape = RoundedCornerShape(size = 8.dp) + + Box( + modifier = Modifier + .width(46.dp) + .height(28.dp) + .background( + color = CustomTheme.colors.pdfAnnotationsFormBackground, + shape = roundCornerShape + ) + .clip(roundCornerShape) + .safeClickable( + interactionSource = remember { MutableInteractionSource() }, + indication = rememberRipple(bounded = true), + onClick = onClick, + ) + ) { + Text( + modifier = Modifier.align(Alignment.Center), + text = text, + color = CustomTheme.colors.defaultTextColor, + style = CustomTheme.typography.default, + fontSize = 22.sp, + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/zotero/android/pdf/annotation/PdfAnnotationRows.kt b/app/src/main/java/org/zotero/android/pdf/annotation/PdfAnnotationRows.kt deleted file mode 100644 index 44b33d5d..00000000 --- a/app/src/main/java/org/zotero/android/pdf/annotation/PdfAnnotationRows.kt +++ /dev/null @@ -1,274 +0,0 @@ -package org.zotero.android.pdf.annotation - -import androidx.compose.foundation.Image -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width -import androidx.compose.material.Text -import androidx.compose.material3.Slider -import androidx.compose.material3.SliderDefaults -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.graphics.ColorFilter -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import org.zotero.android.R -import org.zotero.android.architecture.ui.CustomLayoutSize -import org.zotero.android.database.objects.AnnotationType -import org.zotero.android.pdf.data.PDFAnnotation -import org.zotero.android.pdf.reader.sidebar.SidebarDivider -import org.zotero.android.uicomponents.Drawables -import org.zotero.android.uicomponents.Strings -import org.zotero.android.uicomponents.theme.CustomTheme -import org.zotero.android.uicomponents.topbar.HeadingTextButton - -@Composable -internal fun PdfAnnotationHeaderRow( - annotation: PDFAnnotation, - annotationColor: Color, - layoutType: CustomLayoutSize.LayoutType, - onBack: () -> Unit, -) { - val title = stringResource(R.string.page) + " " + annotation.pageLabel - val icon = when (annotation.type) { - AnnotationType.note -> Drawables.annotate_note - AnnotationType.highlight -> Drawables.annotate_highlight - AnnotationType.image -> Drawables.annotate_area - AnnotationType.ink -> Drawables.annotate_ink - AnnotationType.underline -> Drawables.annotate_underline - AnnotationType.text -> Drawables.annotate_text - } - Box(modifier = Modifier.fillMaxWidth()) { - Row( - modifier = Modifier.align(Alignment.CenterStart), - verticalAlignment = Alignment.CenterVertically - ) { - Spacer(modifier = Modifier.width(8.dp)) - Image( - modifier = Modifier.size(layoutType.calculatePdfSidebarHeaderIconSize()), - painter = painterResource(id = icon), - contentDescription = null, - colorFilter = ColorFilter.tint(annotationColor), - ) - Spacer(modifier = Modifier.width(8.dp)) - Text( - text = title, - color = CustomTheme.colors.primaryContent, - style = CustomTheme.typography.defaultBold, - fontSize = layoutType.calculatePdfSidebarTextSize(), - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) - } - - Row(modifier = Modifier.align(Alignment.CenterEnd)) { - HeadingTextButton( - onClick = onBack, - text = stringResource(Strings.done) - ) - Spacer(modifier = Modifier.width(8.dp)) - } - - } -} - -@Composable -internal fun PdfAnnotationNoteRow( - viewState: PdfAnnotationViewState, - viewModel: PdfAnnotationViewModel, - layoutType: CustomLayoutSize.LayoutType -) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(top = 0.dp, bottom = 8.dp) - ) { - CommentSection(viewState, layoutType, viewModel) - Spacer(modifier = Modifier.height(4.dp)) - SidebarDivider() - Spacer(modifier = Modifier.height(4.dp)) - ColorPicker(viewState, viewModel) - Spacer(modifier = Modifier.height(4.dp)) - SidebarDivider() - Spacer(modifier = Modifier.height(4.dp)) - TagsSection(viewModel = viewModel, viewState = viewState, layoutType = layoutType) - - - } -} - -@Composable -internal fun PdfAnnotationHighlightRow( - viewState: PdfAnnotationViewState, - viewModel: PdfAnnotationViewModel, - layoutType: CustomLayoutSize.LayoutType, -) { - - Column( - modifier = Modifier - .fillMaxWidth() - .padding(top = 0.dp, bottom = 8.dp) - ) { - CommentSection(viewState, layoutType, viewModel) - Spacer(modifier = Modifier.height(4.dp)) - SidebarDivider( - modifier = Modifier - .height(1.dp) - .fillMaxWidth() - ) - Spacer(modifier = Modifier.height(4.dp)) - ColorPicker(viewState, viewModel) - Spacer(modifier = Modifier.height(4.dp)) - SidebarDivider( - modifier = Modifier - .height(1.dp) - .fillMaxWidth() - ) - Spacer(modifier = Modifier.height(4.dp)) - TagsSection(viewModel = viewModel, viewState = viewState, layoutType = layoutType) - } -} - -@Composable -internal fun PdfAnnotationInkRow( - viewState: PdfAnnotationViewState, - viewModel: PdfAnnotationViewModel, - layoutType: CustomLayoutSize.LayoutType, -) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(top = 0.dp, bottom = 8.dp) - ) { - CommentSection(viewState, layoutType, viewModel) - Spacer(modifier = Modifier.height(4.dp)) - SidebarDivider( - modifier = Modifier - .height(1.dp) - .fillMaxWidth() - ) - Spacer(modifier = Modifier.height(4.dp)) - SizeSelector( - viewState = viewState, - viewModel = viewModel, - layoutType = layoutType - ) - Spacer(modifier = Modifier.height(4.dp)) - SidebarDivider( - modifier = Modifier - .height(1.dp) - .fillMaxWidth() - ) - Spacer(modifier = Modifier.height(4.dp)) - TagsSection(viewModel = viewModel, viewState = viewState, layoutType = layoutType) - } -} - -@Composable -private fun SizeSelector( - viewState: PdfAnnotationViewState, - viewModel: PdfAnnotationViewModel, - layoutType: CustomLayoutSize.LayoutType, -) { - Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { - Text( - modifier = Modifier.padding(horizontal = 10.dp), - text = stringResource(id = Strings.size), - color = CustomTheme.colors.pdfSizePickerColor, - style = CustomTheme.typography.default, - fontSize = layoutType.calculatePdfSidebarTextSize(), - ) - Slider( - modifier = Modifier.weight(1f), - value = viewState.size, - onValueChange = { viewModel.onSizeChanged(it) }, - colors = SliderDefaults.colors( - activeTrackColor = CustomTheme.colors.zoteroDefaultBlue, - thumbColor = CustomTheme.colors.zoteroDefaultBlue, - ), - valueRange = 0.5f..25f - ) - Text( - modifier = Modifier.padding(horizontal = 10.dp), - text = String.format("%.1f", viewState.size), - color = CustomTheme.colors.pdfSizePickerColor, - style = CustomTheme.typography.default, - fontSize = layoutType.calculatePdfSidebarTextSize(), - ) - } -} - -@Composable -internal fun PdfAnnotationImageRow( - viewState: PdfAnnotationViewState, - viewModel: PdfAnnotationViewModel, - layoutType: CustomLayoutSize.LayoutType, -) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(top = 0.dp, bottom = 8.dp) - ) { - CommentSection(viewState, layoutType, viewModel) - Spacer(modifier = Modifier.height(4.dp)) - SidebarDivider( - modifier = Modifier - .height(1.dp) - .fillMaxWidth() - ) - Spacer(modifier = Modifier.height(4.dp)) - ColorPicker(viewState, viewModel) - Spacer(modifier = Modifier.height(4.dp)) - SidebarDivider( - modifier = Modifier - .height(1.dp) - .fillMaxWidth() - ) - Spacer(modifier = Modifier.height(4.dp)) - TagsSection(viewModel = viewModel, viewState = viewState, layoutType = layoutType) - } -} - -@Composable -internal fun PdfAnnotationUnderlineRow( - viewState: PdfAnnotationViewState, - viewModel: PdfAnnotationViewModel, - layoutType: CustomLayoutSize.LayoutType, -) { - - Column( - modifier = Modifier - .fillMaxWidth() - .padding(top = 0.dp, bottom = 8.dp) - ) { - CommentSection(viewState, layoutType, viewModel) - Spacer(modifier = Modifier.height(4.dp)) - SidebarDivider( - modifier = Modifier - .height(1.dp) - .fillMaxWidth() - ) - Spacer(modifier = Modifier.height(4.dp)) - ColorPicker(viewState, viewModel) - Spacer(modifier = Modifier.height(4.dp)) - SidebarDivider( - modifier = Modifier - .height(1.dp) - .fillMaxWidth() - ) - Spacer(modifier = Modifier.height(4.dp)) - TagsSection(viewModel = viewModel, viewState = viewState, layoutType = layoutType) - } -} - - diff --git a/app/src/main/java/org/zotero/android/pdf/annotation/PdfAnnotationScreen.kt b/app/src/main/java/org/zotero/android/pdf/annotation/PdfAnnotationScreen.kt index fced0aec..c6ff41c5 100644 --- a/app/src/main/java/org/zotero/android/pdf/annotation/PdfAnnotationScreen.kt +++ b/app/src/main/java/org/zotero/android/pdf/annotation/PdfAnnotationScreen.kt @@ -18,6 +18,13 @@ import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import org.zotero.android.architecture.ui.CustomLayoutSize import org.zotero.android.database.objects.AnnotationType +import org.zotero.android.pdf.annotation.row.PdfAnnotationHeaderRow +import org.zotero.android.pdf.annotation.row.PdfAnnotationHighlightRow +import org.zotero.android.pdf.annotation.row.PdfAnnotationImageRow +import org.zotero.android.pdf.annotation.row.PdfAnnotationInkRow +import org.zotero.android.pdf.annotation.row.PdfAnnotationNoteRow +import org.zotero.android.pdf.annotation.row.PdfAnnotationTextRow +import org.zotero.android.pdf.annotation.row.PdfAnnotationUnderlineRow import org.zotero.android.pdf.reader.sidebar.SidebarDivider import org.zotero.android.uicomponents.Strings import org.zotero.android.uicomponents.theme.CustomPalette @@ -78,8 +85,10 @@ internal fun PdfAnnotationPart( layoutType = layoutType, onBack = onBack, ) - SidebarDivider(modifier = Modifier.fillMaxWidth()) - Spacer(modifier = Modifier.height(4.dp)) + if (annotation.type != AnnotationType.text) { + SidebarDivider(modifier = Modifier.fillMaxWidth()) + Spacer(modifier = Modifier.height(4.dp)) + } } @@ -113,19 +122,22 @@ internal fun PdfAnnotationPart( viewState = viewState, viewModel = viewModel, ) - - else -> { - //no-op - } + AnnotationType.text -> PdfAnnotationTextRow( + layoutType = layoutType, + viewState = viewState, + viewModel = viewModel, + ) } } item { - SidebarDivider( - modifier = Modifier - .height(1.dp) - .fillMaxWidth() - ) - Spacer(modifier = Modifier.height(4.dp)) + if (annotation.type != AnnotationType.text) { + SidebarDivider( + modifier = Modifier + .height(1.dp) + .fillMaxWidth() + ) + Spacer(modifier = Modifier.height(4.dp)) + } HeadingTextButton( modifier = Modifier.fillMaxWidth(), onClick = viewModel::onDeleteAnnotation, @@ -134,7 +146,5 @@ internal fun PdfAnnotationPart( ) } - - } } \ No newline at end of file diff --git a/app/src/main/java/org/zotero/android/pdf/annotation/PdfAnnotationSections.kt b/app/src/main/java/org/zotero/android/pdf/annotation/PdfAnnotationSections.kt index b7b5df88..d696c136 100644 --- a/app/src/main/java/org/zotero/android/pdf/annotation/PdfAnnotationSections.kt +++ b/app/src/main/java/org/zotero/android/pdf/annotation/PdfAnnotationSections.kt @@ -1,23 +1,17 @@ package org.zotero.android.pdf.annotation -import androidx.compose.foundation.Canvas import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import org.zotero.android.architecture.ui.CustomLayoutSize import org.zotero.android.uicomponents.Strings import org.zotero.android.uicomponents.textinput.CustomTextField -import org.zotero.android.uicomponents.theme.CustomPalette import org.zotero.android.uicomponents.theme.CustomTheme @Composable @@ -72,46 +66,4 @@ internal fun TagsSection( fontSize = layoutType.calculatePdfSidebarTextSize(), ) } -} - -@Composable -internal fun ColorPicker( - viewState: PdfAnnotationViewState, - viewModel: PdfAnnotationViewModel -) { - val selectedColor = viewState.color - FlowRow( - modifier = Modifier.padding(horizontal = 10.dp), - ) { - viewState.colors.forEach { listColorHex -> - FilterCircle( - hex = listColorHex, - isSelected = listColorHex == selectedColor, - onClick = { viewModel.onColorSelected(listColorHex) }) - } - } -} - -@Composable -private fun FilterCircle(hex: String, isSelected: Boolean, onClick: () -> Unit) { - val color = android.graphics.Color.parseColor(hex) - Canvas(modifier = Modifier - .padding(4.dp) - .size(32.dp) - .clickable( - interactionSource = remember { MutableInteractionSource() }, - indication = null, - onClick = onClick - ), onDraw = { - drawCircle(color = Color(color)) - if (isSelected) { - drawCircle( - color = CustomPalette.White, - radius = 12.dp.toPx(), - style = Stroke(width = 3.dp.toPx()) - ) - } - }) -} - - +} \ No newline at end of file diff --git a/app/src/main/java/org/zotero/android/pdf/annotation/PdfAnnotationViewModel.kt b/app/src/main/java/org/zotero/android/pdf/annotation/PdfAnnotationViewModel.kt index d128c942..1787a102 100644 --- a/app/src/main/java/org/zotero/android/pdf/annotation/PdfAnnotationViewModel.kt +++ b/app/src/main/java/org/zotero/android/pdf/annotation/PdfAnnotationViewModel.kt @@ -16,6 +16,7 @@ import org.zotero.android.database.objects.AnnotationsConfig import org.zotero.android.pdf.annotation.data.PdfAnnotationColorResult import org.zotero.android.pdf.annotation.data.PdfAnnotationCommentResult import org.zotero.android.pdf.annotation.data.PdfAnnotationDeleteResult +import org.zotero.android.pdf.annotation.data.PdfAnnotationFontSizeResult import org.zotero.android.pdf.annotation.data.PdfAnnotationSizeResult import org.zotero.android.pdf.data.PdfReaderCurrentThemeEventStream import org.zotero.android.pdf.data.PdfReaderThemeDecider @@ -36,7 +37,6 @@ internal class PdfAnnotationViewModel @Inject constructor( updateState { copy(tags = tagPickerResult.tags) } - EventBus.getDefault().post(TagPickerResult(tagPickerResult.tags, TagPickerResult.CallPoint.PdfReaderScreen)) } } @@ -62,7 +62,8 @@ internal class PdfAnnotationViewModel @Inject constructor( annotation = annotation, tags = args.selectedAnnotation.tags, commentFocusText = annotation.comment, - size = annotation.lineWidth ?: 1.0f + size = annotation.lineWidth ?: 1.0f, + fontSize = annotation.fontSize ?: 12.0f ) } } @@ -148,6 +149,29 @@ internal class PdfAnnotationViewModel @Inject constructor( triggerEffect(PdfAnnotationViewEffect.Back) } + fun onFontSizeDecrease() { + updateState { + copy(fontSize = viewState.fontSize - 0.5f) + } + postFontSizeChangeUpdate() + } + + fun onFontSizeIncrease() { + updateState { + copy(fontSize = viewState.fontSize + 0.5f) + } + postFontSizeChangeUpdate() + } + + private fun postFontSizeChangeUpdate() { + EventBus.getDefault().post( + PdfAnnotationFontSizeResult( + key = viewState.annotation!!.key, + size = viewState.fontSize + ) + ) + } + } internal data class PdfAnnotationViewState( @@ -157,6 +181,7 @@ internal data class PdfAnnotationViewState( val commentFocusText: String = "", val color: String = "", val colors: List = emptyList(), + val fontSize: Float = 12f, val size: Float = 1.0f, ) : ViewState diff --git a/app/src/main/java/org/zotero/android/pdf/annotation/data/PdfAnnotationFontSizeResult.kt b/app/src/main/java/org/zotero/android/pdf/annotation/data/PdfAnnotationFontSizeResult.kt new file mode 100644 index 00000000..2c4e7ce8 --- /dev/null +++ b/app/src/main/java/org/zotero/android/pdf/annotation/data/PdfAnnotationFontSizeResult.kt @@ -0,0 +1,3 @@ +package org.zotero.android.pdf.annotation.data + +data class PdfAnnotationFontSizeResult(val key: String, val size: Float) \ No newline at end of file diff --git a/app/src/main/java/org/zotero/android/pdf/annotation/row/PdfAnnotationHeaderRow.kt b/app/src/main/java/org/zotero/android/pdf/annotation/row/PdfAnnotationHeaderRow.kt new file mode 100644 index 00000000..4bea8550 --- /dev/null +++ b/app/src/main/java/org/zotero/android/pdf/annotation/row/PdfAnnotationHeaderRow.kt @@ -0,0 +1,77 @@ +package org.zotero.android.pdf.annotation.row + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.material.Text +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.graphics.ColorFilter +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import org.zotero.android.R +import org.zotero.android.architecture.ui.CustomLayoutSize +import org.zotero.android.database.objects.AnnotationType +import org.zotero.android.pdf.data.PDFAnnotation +import org.zotero.android.uicomponents.Drawables +import org.zotero.android.uicomponents.Strings +import org.zotero.android.uicomponents.theme.CustomTheme +import org.zotero.android.uicomponents.topbar.HeadingTextButton + +@Composable +internal fun PdfAnnotationHeaderRow( + annotation: PDFAnnotation, + annotationColor: Color, + layoutType: CustomLayoutSize.LayoutType, + onBack: () -> Unit, +) { + val title = stringResource(R.string.page) + " " + annotation.pageLabel + val icon = when (annotation.type) { + AnnotationType.note -> Drawables.annotate_note + AnnotationType.highlight -> Drawables.annotate_highlight + AnnotationType.image -> Drawables.annotate_area + AnnotationType.ink -> Drawables.annotate_ink + AnnotationType.underline -> Drawables.annotate_underline + AnnotationType.text -> Drawables.annotate_text + } + Box(modifier = Modifier.fillMaxWidth()) { + Row( + modifier = Modifier.align(Alignment.CenterStart), + verticalAlignment = Alignment.CenterVertically + ) { + Spacer(modifier = Modifier.width(8.dp)) + Image( + modifier = Modifier.size(layoutType.calculatePdfSidebarHeaderIconSize()), + painter = painterResource(id = icon), + contentDescription = null, + colorFilter = ColorFilter.tint(annotationColor), + ) + Spacer(modifier = Modifier.width(8.dp)) + Text( + text = title, + color = CustomTheme.colors.primaryContent, + style = CustomTheme.typography.defaultBold, + fontSize = layoutType.calculatePdfSidebarTextSize(), + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + } + + Row(modifier = Modifier.align(Alignment.CenterEnd)) { + HeadingTextButton( + onClick = onBack, + text = stringResource(Strings.done) + ) + Spacer(modifier = Modifier.width(8.dp)) + } + + } +} \ No newline at end of file diff --git a/app/src/main/java/org/zotero/android/pdf/annotation/row/PdfAnnotationHighlightRow.kt b/app/src/main/java/org/zotero/android/pdf/annotation/row/PdfAnnotationHighlightRow.kt new file mode 100644 index 00000000..08a1e165 --- /dev/null +++ b/app/src/main/java/org/zotero/android/pdf/annotation/row/PdfAnnotationHighlightRow.kt @@ -0,0 +1,49 @@ +package org.zotero.android.pdf.annotation.row + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import org.zotero.android.architecture.ui.CustomLayoutSize +import org.zotero.android.pdf.annotation.ColorPicker +import org.zotero.android.pdf.annotation.CommentSection +import org.zotero.android.pdf.annotation.PdfAnnotationViewModel +import org.zotero.android.pdf.annotation.PdfAnnotationViewState +import org.zotero.android.pdf.annotation.TagsSection +import org.zotero.android.pdf.reader.sidebar.SidebarDivider + +@Composable +internal fun PdfAnnotationHighlightRow( + viewState: PdfAnnotationViewState, + viewModel: PdfAnnotationViewModel, + layoutType: CustomLayoutSize.LayoutType, +) { + + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = 0.dp, bottom = 8.dp) + ) { + CommentSection(viewState, layoutType, viewModel) + Spacer(modifier = Modifier.height(4.dp)) + SidebarDivider( + modifier = Modifier + .height(1.dp) + .fillMaxWidth() + ) + Spacer(modifier = Modifier.height(4.dp)) + ColorPicker(viewState, viewModel) + Spacer(modifier = Modifier.height(4.dp)) + SidebarDivider( + modifier = Modifier + .height(1.dp) + .fillMaxWidth() + ) + Spacer(modifier = Modifier.height(4.dp)) + TagsSection(viewModel = viewModel, viewState = viewState, layoutType = layoutType) + } +} diff --git a/app/src/main/java/org/zotero/android/pdf/annotation/row/PdfAnnotationImageRow.kt b/app/src/main/java/org/zotero/android/pdf/annotation/row/PdfAnnotationImageRow.kt new file mode 100644 index 00000000..fb1df7f4 --- /dev/null +++ b/app/src/main/java/org/zotero/android/pdf/annotation/row/PdfAnnotationImageRow.kt @@ -0,0 +1,48 @@ +package org.zotero.android.pdf.annotation.row + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import org.zotero.android.architecture.ui.CustomLayoutSize +import org.zotero.android.pdf.annotation.ColorPicker +import org.zotero.android.pdf.annotation.CommentSection +import org.zotero.android.pdf.annotation.PdfAnnotationViewModel +import org.zotero.android.pdf.annotation.PdfAnnotationViewState +import org.zotero.android.pdf.annotation.TagsSection +import org.zotero.android.pdf.reader.sidebar.SidebarDivider + +@Composable +internal fun PdfAnnotationImageRow( + viewState: PdfAnnotationViewState, + viewModel: PdfAnnotationViewModel, + layoutType: CustomLayoutSize.LayoutType, +) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = 0.dp, bottom = 8.dp) + ) { + CommentSection(viewState, layoutType, viewModel) + Spacer(modifier = Modifier.height(4.dp)) + SidebarDivider( + modifier = Modifier + .height(1.dp) + .fillMaxWidth() + ) + Spacer(modifier = Modifier.height(4.dp)) + ColorPicker(viewState, viewModel) + Spacer(modifier = Modifier.height(4.dp)) + SidebarDivider( + modifier = Modifier + .height(1.dp) + .fillMaxWidth() + ) + Spacer(modifier = Modifier.height(4.dp)) + TagsSection(viewModel = viewModel, viewState = viewState, layoutType = layoutType) + } +} diff --git a/app/src/main/java/org/zotero/android/pdf/annotation/row/PdfAnnotationInkRow.kt b/app/src/main/java/org/zotero/android/pdf/annotation/row/PdfAnnotationInkRow.kt new file mode 100644 index 00000000..71032338 --- /dev/null +++ b/app/src/main/java/org/zotero/android/pdf/annotation/row/PdfAnnotationInkRow.kt @@ -0,0 +1,53 @@ +package org.zotero.android.pdf.annotation.row + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import org.zotero.android.architecture.ui.CustomLayoutSize +import org.zotero.android.pdf.annotation.CommentSection +import org.zotero.android.pdf.annotation.PdfAnnotationViewModel +import org.zotero.android.pdf.annotation.PdfAnnotationViewState +import org.zotero.android.pdf.annotation.SizeSelector +import org.zotero.android.pdf.annotation.TagsSection +import org.zotero.android.pdf.reader.sidebar.SidebarDivider + +@Composable +internal fun PdfAnnotationInkRow( + viewState: PdfAnnotationViewState, + viewModel: PdfAnnotationViewModel, + layoutType: CustomLayoutSize.LayoutType, +) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = 0.dp, bottom = 8.dp) + ) { + CommentSection(viewState, layoutType, viewModel) + Spacer(modifier = Modifier.height(4.dp)) + SidebarDivider( + modifier = Modifier + .height(1.dp) + .fillMaxWidth() + ) + Spacer(modifier = Modifier.height(4.dp)) + SizeSelector( + viewState = viewState, + viewModel = viewModel, + layoutType = layoutType + ) + Spacer(modifier = Modifier.height(4.dp)) + SidebarDivider( + modifier = Modifier + .height(1.dp) + .fillMaxWidth() + ) + Spacer(modifier = Modifier.height(4.dp)) + TagsSection(viewModel = viewModel, viewState = viewState, layoutType = layoutType) + } +} + diff --git a/app/src/main/java/org/zotero/android/pdf/annotation/row/PdfAnnotationNoteRow.kt b/app/src/main/java/org/zotero/android/pdf/annotation/row/PdfAnnotationNoteRow.kt new file mode 100644 index 00000000..f19449b2 --- /dev/null +++ b/app/src/main/java/org/zotero/android/pdf/annotation/row/PdfAnnotationNoteRow.kt @@ -0,0 +1,40 @@ +package org.zotero.android.pdf.annotation.row + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import org.zotero.android.architecture.ui.CustomLayoutSize +import org.zotero.android.pdf.annotation.ColorPicker +import org.zotero.android.pdf.annotation.CommentSection +import org.zotero.android.pdf.annotation.PdfAnnotationViewModel +import org.zotero.android.pdf.annotation.PdfAnnotationViewState +import org.zotero.android.pdf.annotation.TagsSection +import org.zotero.android.pdf.reader.sidebar.SidebarDivider + +@Composable +internal fun PdfAnnotationNoteRow( + viewState: PdfAnnotationViewState, + viewModel: PdfAnnotationViewModel, + layoutType: CustomLayoutSize.LayoutType +) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = 0.dp, bottom = 8.dp) + ) { + CommentSection(viewState, layoutType, viewModel) + Spacer(modifier = Modifier.height(4.dp)) + SidebarDivider() + Spacer(modifier = Modifier.height(4.dp)) + ColorPicker(viewState, viewModel) + Spacer(modifier = Modifier.height(4.dp)) + SidebarDivider() + Spacer(modifier = Modifier.height(4.dp)) + TagsSection(viewModel = viewModel, viewState = viewState, layoutType = layoutType) + } +} diff --git a/app/src/main/java/org/zotero/android/pdf/annotation/row/PdfAnnotationTextRow.kt b/app/src/main/java/org/zotero/android/pdf/annotation/row/PdfAnnotationTextRow.kt new file mode 100644 index 00000000..1396811d --- /dev/null +++ b/app/src/main/java/org/zotero/android/pdf/annotation/row/PdfAnnotationTextRow.kt @@ -0,0 +1,45 @@ +package org.zotero.android.pdf.annotation.row + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import org.zotero.android.architecture.ui.CustomLayoutSize +import org.zotero.android.pdf.annotation.ColorPicker +import org.zotero.android.pdf.annotation.FontSizeSelector +import org.zotero.android.pdf.annotation.PdfAnnotationViewModel +import org.zotero.android.pdf.annotation.PdfAnnotationViewState +import org.zotero.android.pdf.annotation.TagsSection +import org.zotero.android.pdf.annotationmore.SpacerDivider + +@Composable +internal fun PdfAnnotationTextRow( + viewState: PdfAnnotationViewState, + viewModel: PdfAnnotationViewModel, + layoutType: CustomLayoutSize.LayoutType, +) { + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = 0.dp, bottom = 8.dp) + ) { + SpacerDivider() + FontSizeSelector( + fontSize = viewState.fontSize, + onFontSizeDecrease = viewModel::onFontSizeDecrease, + onFontSizeIncrease = viewModel::onFontSizeIncrease, + ) + SpacerDivider() + ColorPicker(viewState, viewModel) + SpacerDivider() + Spacer(modifier = Modifier.height(4.dp)) + TagsSection(viewModel = viewModel, viewState = viewState, layoutType = layoutType) + Spacer(modifier = Modifier.height(4.dp)) + SpacerDivider() + } +} + diff --git a/app/src/main/java/org/zotero/android/pdf/annotation/row/PdfAnnotationUnderlineRow.kt b/app/src/main/java/org/zotero/android/pdf/annotation/row/PdfAnnotationUnderlineRow.kt new file mode 100644 index 00000000..bec7cba4 --- /dev/null +++ b/app/src/main/java/org/zotero/android/pdf/annotation/row/PdfAnnotationUnderlineRow.kt @@ -0,0 +1,49 @@ +package org.zotero.android.pdf.annotation.row + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import org.zotero.android.architecture.ui.CustomLayoutSize +import org.zotero.android.pdf.annotation.ColorPicker +import org.zotero.android.pdf.annotation.CommentSection +import org.zotero.android.pdf.annotation.PdfAnnotationViewModel +import org.zotero.android.pdf.annotation.PdfAnnotationViewState +import org.zotero.android.pdf.annotation.TagsSection +import org.zotero.android.pdf.reader.sidebar.SidebarDivider + +@Composable +internal fun PdfAnnotationUnderlineRow( + viewState: PdfAnnotationViewState, + viewModel: PdfAnnotationViewModel, + layoutType: CustomLayoutSize.LayoutType, +) { + + Column( + modifier = Modifier + .fillMaxWidth() + .padding(top = 0.dp, bottom = 8.dp) + ) { + CommentSection(viewState, layoutType, viewModel) + Spacer(modifier = Modifier.height(4.dp)) + SidebarDivider( + modifier = Modifier + .height(1.dp) + .fillMaxWidth() + ) + Spacer(modifier = Modifier.height(4.dp)) + ColorPicker(viewState, viewModel) + Spacer(modifier = Modifier.height(4.dp)) + SidebarDivider( + modifier = Modifier + .height(1.dp) + .fillMaxWidth() + ) + Spacer(modifier = Modifier.height(4.dp)) + TagsSection(viewModel = viewModel, viewState = viewState, layoutType = layoutType) + } +} diff --git a/app/src/main/java/org/zotero/android/pdf/reader/PdfReaderViewModel.kt b/app/src/main/java/org/zotero/android/pdf/reader/PdfReaderViewModel.kt index 6f1ae5ff..e3b9bdfe 100644 --- a/app/src/main/java/org/zotero/android/pdf/reader/PdfReaderViewModel.kt +++ b/app/src/main/java/org/zotero/android/pdf/reader/PdfReaderViewModel.kt @@ -116,6 +116,7 @@ import org.zotero.android.pdf.annotation.data.PdfAnnotationArgs import org.zotero.android.pdf.annotation.data.PdfAnnotationColorResult import org.zotero.android.pdf.annotation.data.PdfAnnotationCommentResult import org.zotero.android.pdf.annotation.data.PdfAnnotationDeleteResult +import org.zotero.android.pdf.annotation.data.PdfAnnotationFontSizeResult import org.zotero.android.pdf.annotation.data.PdfAnnotationSizeResult import org.zotero.android.pdf.annotationmore.data.PdfAnnotationMoreArgs import org.zotero.android.pdf.annotationmore.data.PdfAnnotationMoreDeleteResult @@ -236,6 +237,9 @@ class PdfReaderViewModel @Inject constructor( private var disableForceScreenOnTimer: Timer? = null + private var annotationEditSelectedKey: String? = null + private var isLongPressOnTextAnnotation = false + val screenArgs: PdfReaderArgs by lazy { val argsEncoded = stateHandle.get(ARG_PDF_SCREEN).require() navigationParamsMarshaller.decodeObjectFromBase64(argsEncoded) @@ -266,8 +270,8 @@ class PdfReaderViewModel @Inject constructor( @Subscribe(threadMode = ThreadMode.MAIN) fun onEvent(tagPickerResult: TagPickerResult) { if (tagPickerResult.callPoint == TagPickerResult.CallPoint.PdfReaderScreen) { - val annotation = this@PdfReaderViewModel.selectedAnnotation ?: return - set(tags = tagPickerResult.tags, key = annotation.key) + val key = this.annotationEditSelectedKey ?: return + set(tags = tagPickerResult.tags, key = key) } } @@ -288,6 +292,11 @@ class PdfReaderViewModel @Inject constructor( setLineWidth(key = result.key, width = result.size) } + @Subscribe(threadMode = ThreadMode.MAIN) + fun onEvent(result: PdfAnnotationFontSizeResult) { + setF(key = result.key, fontSize = result.size) + } + @Subscribe(threadMode = ThreadMode.MAIN) fun onEvent(result: PdfAnnotationMoreDeleteResult) { val key = viewState.selectedAnnotationKey ?: return @@ -665,6 +674,14 @@ class PdfReaderViewModel @Inject constructor( } private fun setupInteractionListeners() { + pdfFragment.setOnDocumentLongPressListener { _, _, _, _, annotation -> + if (annotation?.type == AnnotationType.FREETEXT) { + isLongPressOnTextAnnotation = true + pdfFragment.setSelectedAnnotation(annotation) + return@setOnDocumentLongPressListener true + } + false + } pdfFragment.addOnAnnotationSelectedListener(object : AnnotationManager.OnAnnotationSelectedListener { override fun onPrepareAnnotationSelection( @@ -680,7 +697,9 @@ class PdfReaderViewModel @Inject constructor( val key = annotation.key ?: annotation.uuid val type: Kind = if (annotation.isZoteroAnnotation) Kind.database else Kind.document - selectAnnotationFromDocument(AnnotationKey(key = key, type = type)) + selectAnnotationFromDocument( + key = AnnotationKey(key = key, type = type), + ) } }) @@ -1595,10 +1614,12 @@ class PdfReaderViewModel @Inject constructor( private fun updateAnnotationsList(forceNotShowAnnotationPopup: Boolean = false) { hidePspdfkitToolbars() var showAnnotationPopup = !forceNotShowAnnotationPopup && !viewState.showSideBar && selectedAnnotation != null - if (selectedAnnotation?.type == org.zotero.android.database.objects.AnnotationType.text) { + if (selectedAnnotation?.type == org.zotero.android.database.objects.AnnotationType.text && !isLongPressOnTextAnnotation) { showAnnotationPopup = false } + isLongPressOnTextAnnotation = false if (showAnnotationPopup) { + annotationEditSelectedKey = selectedAnnotation?.key ScreenArguments.pdfAnnotationArgs = PdfAnnotationArgs( selectedAnnotation = selectedAnnotation, userId = viewState.userId, @@ -1766,6 +1787,9 @@ class PdfReaderViewModel @Inject constructor( if (blendMode != null) { pdfAnnotation.blendMode = blendMode } + if (annotation.type == org.zotero.android.database.objects.AnnotationType.text) { + pdfFragment.notifyAnnotationHasChanged(pdfAnnotation) + } } if (changes.contains(PdfAnnotationChanges.contents) && contents != null) { @@ -2968,7 +2992,7 @@ class PdfReaderViewModel @Inject constructor( val annotation = annotation(key) ?: return - selectAnnotationFromDocument(key) + selectAnnotationFromDocument(key = key) updateState { copy( @@ -2983,10 +3007,12 @@ class PdfReaderViewModel @Inject constructor( // return // } val annotationKey = AnnotationKey(key = annotation.key, type = Kind.database) - selectAnnotationFromDocument(annotationKey) + selectAnnotationFromDocument(key = annotationKey) val selected = annotation.tags.map { it.name }.toSet() + this.annotationEditSelectedKey = annotation.key + ScreenArguments.tagPickerArgs = TagPickerArgs( libraryId = viewState.library.identifier, selectedTags = selected, diff --git a/buildSrc/src/main/kotlin/BuildConfig.kt b/buildSrc/src/main/kotlin/BuildConfig.kt index 5aa76934..86c8613a 100644 --- a/buildSrc/src/main/kotlin/BuildConfig.kt +++ b/buildSrc/src/main/kotlin/BuildConfig.kt @@ -4,7 +4,7 @@ object BuildConfig { const val compileSdkVersion = 34 const val targetSdk = 34 - val versionCode = 117 // Must be updated on every build + val versionCode = 118 // Must be updated on every build val version = Version( major = 1, minor = 0,