Skip to content

Commit

Permalink
First implementation stab at “Make the annotation bar movable/dockable
Browse files Browse the repository at this point in the history
…#101”

Start of refactoring of build.gradle’s dependencies. Moving them into “Libs.kt” and several Plugin classes. This not only groups related dependencies and makes updating several dependencies with the same version number easier, but also will allow us to configure CI to use a dependency cache and point mentioned classes to the CI to use them as a hash to decide when to update the cache, which should speed up the build process.

Upping versionCode to 42
  • Loading branch information
Dima-Android committed Jan 23, 2024
1 parent 77bc262 commit 2db483b
Show file tree
Hide file tree
Showing 10 changed files with 359 additions and 69 deletions.
73 changes: 10 additions & 63 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ plugins {
id("kotlin-parcelize")
id("com.google.gms.google-services")
id("com.google.firebase.crashlytics")
id("compose")
id("accompanist")
id("daggerAndHilt")
id("tests")
id("com.google.dagger.hilt.android")
}

Expand Down Expand Up @@ -92,20 +96,15 @@ android {
}
}


compileOptions {
sourceCompatibility = javaVersion
targetCompatibility = javaVersion
}
kotlinOptions {
jvmTarget = javaVersion.toString()
}
composeOptions {
kotlinCompilerExtensionVersion = "1.5.4"
}
buildFeatures {
viewBinding = true
compose = true
buildConfig = true
}

Expand Down Expand Up @@ -152,30 +151,6 @@ dependencies {
//Material design
implementation("com.google.android.material:material:1.10.0")

//Compose
implementation("androidx.compose.ui:ui-viewbinding:1.5.4")
implementation("androidx.compose.ui:ui-util:1.5.4")
implementation("androidx.compose.ui:ui-tooling:1.5.4")
implementation("androidx.compose.ui:ui:1.5.4")
implementation("androidx.navigation:navigation-compose:2.7.5")
implementation("androidx.compose.material:material:1.5.4")
implementation("androidx.compose.runtime:runtime-livedata:1.5.4")
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.2")
implementation("androidx.compose.foundation:foundation:1.5.4")
implementation("androidx.constraintlayout:constraintlayout-compose:1.0.1")
implementation("androidx.activity:activity-compose:1.8.1")
implementation("androidx.compose.material3:material3:1.1.2")
implementation("androidx.compose.material3:material3-window-size-class:1.1.2")

//Accompanist
implementation("com.google.accompanist:accompanist-insets:0.31.5-beta")
implementation("com.google.accompanist:accompanist-placeholder:0.32.0")
implementation("com.google.accompanist:accompanist-systemuicontroller:0.32.0")
implementation("com.google.accompanist:accompanist-pager:0.32.0")
implementation("com.google.accompanist:accompanist-navigation-animation:0.32.0")
implementation("com.google.accompanist:accompanist-swiperefresh:0.32.0")
implementation("com.google.accompanist:accompanist-flowlayout:0.32.0")

//Kotlin
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.9.20")
implementation("org.jetbrains.kotlin:kotlin-reflect:1.9.20")
Expand All @@ -184,28 +159,17 @@ dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.1")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1")

//Dagger + Hilt
implementation("com.google.dagger:hilt-android:2.48")
// implementation("com.google.dagger:dagger:2.44")
// kapt("com.google.dagger:dagger-compiler:2.44")
kapt("com.google.dagger:hilt-compiler:2.47")
annotationProcessor("com.google.dagger:hilt-android-compiler:2.47")

implementation("androidx.hilt:hilt-work:1.1.0")
kapt("androidx.hilt:hilt-compiler:1.1.0")
implementation("androidx.hilt:hilt-navigation-compose:1.1.0")

//Crash & Analytics
//Crash
implementation("com.google.firebase:firebase-crashlytics-ktx:18.5.1")

//PSPDFKIT
implementation("com.pspdfkit:pspdfkit:8.10.0")

//Retrofit 2
implementation("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:0.8.0")
implementation("com.squareup.retrofit2:retrofit:2.9.0")
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("com.squareup.retrofit2:converter-scalars:2.9.0")
implementation(Libs.Retrofit.kotlinSerialization)
implementation(Libs.Retrofit.core)
implementation(Libs.Retrofit.converterGson)
implementation(Libs.Retrofit.converterScalars)

//Ok HTTP
implementation("com.squareup.okhttp3:okhttp:4.10.0")
Expand All @@ -219,7 +183,7 @@ dependencies {
implementation("androidx.media3:media3-ui:1.2.0")

//Coil
implementation("io.coil-kt:coil-compose:2.2.2")
implementation(Libs.Coil.compose)

//Other
implementation("com.jakewharton.timber:timber:4.7.1")
Expand All @@ -230,23 +194,6 @@ dependencies {
implementation("commons-codec:commons-codec:1.13")
implementation("commons-validator:commons-validator:1.7")
implementation("net.yslibrary.keyboardvisibilityevent:keyboardvisibilityevent:3.0.0-RC3")

//Unit Tests
testImplementation("junit:junit:4.13.2")
testImplementation("androidx.test:core:1.5.0")
testImplementation("androidx.arch.core:core-testing:2.2.0")

testImplementation("org.mockito:mockito-core:3.11.0")
testImplementation("org.mockito:mockito-inline:3.11.0")

testImplementation("io.mockk:mockk:1.11.0")
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.1")
testImplementation("org.amshove.kluent:kluent-android:1.72")

//Instrumented Tests
androidTestImplementation("androidx.test:rules:1.5.0")
androidTestImplementation("androidx.test:runner:1.5.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
}

kapt {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,33 +1,55 @@
package org.zotero.android.pdf.reader

import android.net.Uri
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.AnchoredDraggableState
import androidx.compose.foundation.gestures.DraggableAnchors
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.anchoredDraggable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxScope
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Icon
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.PathEffect
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import com.pspdfkit.ui.special_mode.controller.AnnotationTool
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import org.zotero.android.pdf.data.PdfReaderTool
import org.zotero.android.uicomponents.Drawables
import org.zotero.android.uicomponents.Strings
import org.zotero.android.uicomponents.foundation.safeClickable
import org.zotero.android.uicomponents.theme.CustomTheme
import kotlin.math.roundToInt

private val pdfReaderToolsList = listOf(
PdfReaderTool(
Expand Down Expand Up @@ -68,27 +90,135 @@ internal fun PdfReaderPspdfKitBox(
viewModel: PdfReaderViewModel,
viewState: PdfReaderViewState
) {
val density = LocalDensity.current
val positionalThreshold = { distance: Float -> distance * 0.5f }
val velocityThreshold = { with(density) { 1000.dp.toPx() } }
val animationSpec = tween<Float>()

var shouldShowSnapTargetAreas: Boolean by remember { mutableStateOf(false) }
val confirmValueChange = { newValue: DragAnchors ->
shouldShowSnapTargetAreas = false
true
}
val anchoredDraggableState = rememberSaveable(
saver = AnchoredDraggableState.Saver(
animationSpec = animationSpec,
positionalThreshold = positionalThreshold,
velocityThreshold = velocityThreshold,
confirmValueChange = confirmValueChange,
)
) {
AnchoredDraggableState(
initialValue = DragAnchors.Start,
positionalThreshold = positionalThreshold,
velocityThreshold = velocityThreshold,
animationSpec = animationSpec,
confirmValueChange = confirmValueChange,
)
}
val rightTargetAreaXOffset = with(density) { 92.dp.toPx() }

Box(
modifier = Modifier.fillMaxSize()
modifier = Modifier
.fillMaxSize()
.onSizeChanged { layoutSize ->
val dragEndPoint = layoutSize.width - rightTargetAreaXOffset
anchoredDraggableState.updateAnchors(
DraggableAnchors {
DragAnchors.entries
.forEach { anchor ->
anchor at dragEndPoint * anchor.fraction
}
}
)
}
) {
PdfReaderPspdfKitView(uri = uri, viewModel = viewModel)
if (viewState.showCreationToolbar) {
PdfReaderAnnotationCreationToolbar(
viewModel = viewModel,
viewState = viewState
viewState = viewState,
state = anchoredDraggableState,
onShowSnapTargetAreas = { shouldShowSnapTargetAreas = true },
shouldShowSnapTargetAreas = shouldShowSnapTargetAreas
)
}
}
}

enum class DragAnchors(val fraction: Float) {
Start(0f),
End(1f),
}

@Composable
fun PdfReaderAnnotationCreationToolbar(
fun BoxScope.PdfReaderAnnotationCreationToolbar(
viewModel: PdfReaderViewModel,
viewState: PdfReaderViewState
viewState: PdfReaderViewState,
state: AnchoredDraggableState<DragAnchors>,
onShowSnapTargetAreas: () -> Unit,
shouldShowSnapTargetAreas: Boolean,
) {
val roundCornerShape = RoundedCornerShape(size = 4.dp)
val draggableInteractionSource = remember { MutableInteractionSource() }
val coroutineScope = rememberCoroutineScope()
LaunchedEffect(key1 = viewModel) {
draggableInteractionSource.interactions.onEach {
onShowSnapTargetAreas()
}.launchIn(coroutineScope)
}

if (shouldShowSnapTargetAreas) {
val stroke = Stroke(
width = 5f,
pathEffect = PathEffect.dashPathEffect(floatArrayOf(10f, 10f), 0f)
)
val snapAreaBackgroundColor =
if (isSystemInDarkTheme()) Color(0xFF080E1C) else Color(0xFFE2EAFB)
Box(
modifier = Modifier
.size(width = 72.dp, height = 500.dp)
.padding(start = 20.dp, top = 20.dp)
.background(
color = snapAreaBackgroundColor,
roundCornerShape
)
.clip(roundCornerShape)
.drawBehind {
drawRoundRect(color = Color(0xFF4978E7), style = stroke)
}
)
Box(
modifier = Modifier
.align(Alignment.TopEnd)
.size(width = 72.dp, height = 500.dp)
.padding(end = 20.dp, top = 20.dp)
.background(
color = snapAreaBackgroundColor,
roundCornerShape
)
.clip(roundCornerShape)
.drawBehind {
drawRoundRect(color = Color(0xFF4978E7), style = stroke)
}
)
}

Box(
modifier = Modifier
.offset {
IntOffset(
x = state
.requireOffset()
.roundToInt(),
y = 0,
)
}
.anchoredDraggable(
state = state,
orientation = Orientation.Horizontal,
interactionSource = draggableInteractionSource
)
.height(500.dp)
.padding(start = 20.dp, top = 20.dp)
.background(
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ buildscript {
classpath("org.jetbrains.kotlin:kotlin-serialization:1.9.20")
classpath("com.google.firebase:firebase-crashlytics-gradle:2.9.9")
classpath("com.google.gms:google-services:4.4.0")
classpath("com.google.dagger:hilt-android-gradle-plugin:2.47")
classpath(Libs.Dagger.hiltGradlePlugin)
classpath("io.realm:realm-gradle-plugin:10.15.1")
classpath("com.google.gms:google-services:4.4.0")

Expand Down
20 changes: 20 additions & 0 deletions buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,23 @@ dependencies {
implementation("com.squareup:javapoet:1.13.0")
}

gradlePlugin {
plugins {
register("ComposePlugin") {
id = "compose"
implementationClass = "ComposePlugin"
}
register("AccompanistPlugin") {
id = "accompanist"
implementationClass = "AccompanistPlugin"
}
register("DaggerAndHiltPlugin") {
id = "daggerAndHilt"
implementationClass = "DaggerAndHiltPlugin"
}
register("TestsPlugin") {
id = "tests"
implementationClass = "TestsPlugin"
}
}
}
23 changes: 23 additions & 0 deletions buildSrc/src/main/kotlin/AccompanistPlugin.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import com.android.build.gradle.TestedExtension
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.kotlin.dsl.getByType

class AccompanistPlugin : Plugin<Project> {
override fun apply(project: Project) {
val extension = project.extensions.getByType<TestedExtension>()
extension.configure(project)
}
}

private fun TestedExtension.configure(project: Project) {
project.dependencies.apply {
add("implementation", Libs.Accompanist.flowlayout)
add("implementation", Libs.Accompanist.insets)
add("implementation", Libs.Accompanist.navigationAnimation)
add("implementation", Libs.Accompanist.pager)
add("implementation", Libs.Accompanist.placeholder)
add("implementation", Libs.Accompanist.swipeToRefresh)
add("implementation", Libs.Accompanist.systemuicontroller)
}
}
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/BuildConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ object BuildConfig {
const val compileSdkVersion = 34
const val targetSdk = 33

val versionCode = 41 // Must be updated on every build
val versionCode = 42 // Must be updated on every build
val version = Version(
major = 1,
minor = 0,
Expand Down
Loading

0 comments on commit 2db483b

Please sign in to comment.