diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..931bfa6 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,2 @@ +[*.{kt,kts}] +ktlint_function_naming_ignore_when_annotated_with=Composable \ No newline at end of file diff --git a/.gitignore b/.gitignore index f0b838c..f0cc0a9 100644 --- a/.gitignore +++ b/.gitignore @@ -50,6 +50,9 @@ captures/ .idea/modules.xml # Comment next line if keeping position of elements in Navigation Editor is relevant for you .idea/navEditor.xml +.idea/deploymentTargetDropDown.xml +.idea/kotlinc.xml +.idea/migrations.xml # Keystore files diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index dfca6e5..a906661 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -3,11 +3,9 @@ - diff --git a/.idea/compiler.xml b/.idea/compiler.xml index 61a9130..b589d56 100644 --- a/.idea/compiler.xml +++ b/.idea/compiler.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/build.gradle b/build.gradle index 7f59d9e..ba9586b 100644 --- a/build.gradle +++ b/build.gradle @@ -1,10 +1,11 @@ import com.husseinala.neon.Deps +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { google() - jcenter() + mavenCentral() } dependencies { classpath Deps.Android.GRADLE_PLUGIN @@ -18,19 +19,19 @@ buildscript { } plugins { - id "com.diffplug.spotless" version "5.2.0" + id "com.diffplug.spotless" version "6.23.3" } allprojects { repositories { google() - jcenter() + mavenCentral() } group = project.property("GROUP") as String version = project.property("VERSION_NAME") as String - tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { + tasks.withType(KotlinCompile).configureEach { kotlinOptions { jvmTarget = "1.8" } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 445e21f..f155244 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -1,5 +1,5 @@ repositories { - jcenter() + mavenCentral() } plugins { diff --git a/buildSrc/src/main/java/com/husseinala/neon/Dependencies.kt b/buildSrc/src/main/java/com/husseinala/neon/Dependencies.kt index 5083d74..d3abedd 100644 --- a/buildSrc/src/main/java/com/husseinala/neon/Dependencies.kt +++ b/buildSrc/src/main/java/com/husseinala/neon/Dependencies.kt @@ -3,19 +3,20 @@ package com.husseinala.neon object Versions { // android - const val COMPILE_SDK = 29 + const val COMPILE_SDK = 34 const val MIN_SDK = 21 - const val TARGET_SDK = 29 + const val TARGET_SDK = 34 // Kotlin - const val KOTLIN = "1.4.30" - const val DOKKA = "1.4.0" + const val KOTLIN = "1.9.20" + const val DOKKA = "1.9.10" // Compose - const val COMPOSE = "1.0.0-alpha12" + const val COMPOSE = "1.5.4" + const val COMPOSE_COMPILER = "1.5.5" // Spotless - const val KT_LINT = "0.40.0" + const val KT_LINT = "1.1.1" } object Deps { @@ -27,7 +28,7 @@ object Deps { } object Android { - const val GRADLE_PLUGIN = "com.android.tools.build:gradle:7.0.0-alpha07" + const val GRADLE_PLUGIN = "com.android.tools.build:gradle:8.2.1" } object AndroidX { @@ -48,7 +49,7 @@ object Deps { object Picasso { const val PICASSO = "com.squareup.picasso:picasso:2.8" - const val TRANSFORMATIONS = "jp.wasabeef:picasso-transformations:2.2.1" + const val TRANSFORMATIONS = "jp.wasabeef:picasso-transformations:2.4.0" } const val MAVEN_PUBLISH = "com.vanniktech:gradle-maven-publish-plugin:0.13.0" diff --git a/core/build.gradle b/core/build.gradle index 4e90c8c..f7cc449 100644 --- a/core/build.gradle +++ b/core/build.gradle @@ -16,9 +16,10 @@ spotless { } android { - compileSdkVersion Versions.COMPILE_SDK + namespace "com.husseinala.neon.core" defaultConfig { + compileSdkVersion Versions.COMPILE_SDK minSdkVersion Versions.MIN_SDK targetSdkVersion Versions.TARGET_SDK @@ -43,7 +44,7 @@ android { } composeOptions { - kotlinCompilerExtensionVersion Versions.COMPOSE + kotlinCompilerExtensionVersion Versions.COMPOSE_COMPILER } } diff --git a/core/src/main/java/com/husseinala/neon/core/DefaultTransformations.kt b/core/src/main/java/com/husseinala/neon/core/DefaultTransformations.kt index a4c6c7d..a12a6b0 100644 --- a/core/src/main/java/com/husseinala/neon/core/DefaultTransformations.kt +++ b/core/src/main/java/com/husseinala/neon/core/DefaultTransformations.kt @@ -20,32 +20,35 @@ fun Transformation.circleCrop() = this + CircleCropTransformation * Specify the [ScaleType] to be used when scaling the downloaded image. */ @Composable -fun Transformation.scaleType(scaleType: ScaleType) = this + ScaleTypeTransformation( - scaleType -) +fun Transformation.scaleType(scaleType: ScaleType) = + this + + ScaleTypeTransformation( + scaleType, + ) /** * Use [ScaleType.CENTER_CROP] when scaling down the image to the preferred size. */ @Composable -fun Transformation.centerCrop() = scaleType( - ScaleType.CENTER_CROP -) +fun Transformation.centerCrop() = + scaleType( + ScaleType.CENTER_CROP, + ) /** * Used [ScaleType.CENTER_INSIDE] whe scaling down the image to the preferred size. */ @Composable -fun Transformation.centerInside() = scaleType( - ScaleType.CENTER_INSIDE -) +fun Transformation.centerInside() = + scaleType( + ScaleType.CENTER_INSIDE, + ) /** * Transformation that rounds the corners of the downloaded image using the specified [radius]. */ @Composable -fun Transformation.roundedCorners(radius: Dp) = - this + RoundedCornersTransformation(radius.toPx().roundToInt()) +fun Transformation.roundedCorners(radius: Dp) = this + RoundedCornersTransformation(radius.toPx().roundToInt()) @Composable private fun Dp.toPx() = LocalDensity.current.density * value diff --git a/core/src/main/java/com/husseinala/neon/core/ImageLoader.kt b/core/src/main/java/com/husseinala/neon/core/ImageLoader.kt index 03c4102..519910d 100644 --- a/core/src/main/java/com/husseinala/neon/core/ImageLoader.kt +++ b/core/src/main/java/com/husseinala/neon/core/ImageLoader.kt @@ -7,7 +7,6 @@ import androidx.compose.ui.unit.IntSize * An image loader that can be used to fetch an image from a remote or local source. */ interface ImageLoader { - /** * Fetch an image using the specified [ImageConfig]. * @@ -18,7 +17,7 @@ interface ImageLoader { fun getImage( imageConfig: ImageConfig<*>, onSuccess: (ImageBitmap) -> Unit, - onFailure: (Exception) -> Unit + onFailure: (Exception) -> Unit, ): Cancelable } @@ -33,14 +32,13 @@ interface ImageLoader { data class ImageConfig( val id: ImageId, val size: IntSize = IntSize.Zero, - val transformation: Transformation = Transformation + val transformation: Transformation = Transformation, ) /** * Used to specify the location of the image to be fetched. */ sealed class ImageId { - abstract val value: T /** @@ -76,7 +74,6 @@ sealed class ImageId { * An interface that's used to indicate a cancelable request. */ fun interface Cancelable { - /** * Attempts to cancel execution of the current request. */ diff --git a/core/src/main/java/com/husseinala/neon/core/Neon.kt b/core/src/main/java/com/husseinala/neon/core/Neon.kt index 72eb477..80bc747 100644 --- a/core/src/main/java/com/husseinala/neon/core/Neon.kt +++ b/core/src/main/java/com/husseinala/neon/core/Neon.kt @@ -4,8 +4,8 @@ import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.DisposableEffect -import androidx.compose.runtime.Providers import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -21,16 +21,10 @@ import androidx.compose.ui.unit.IntSize /** * Provides an [ImageLoader] that can be used by the [Neon] and [LoadImage] composables to fetch images. */ -val LocalImageLoader = staticCompositionLocalOf() - -@Deprecated( - "Renamed to LocalImageLoader", - replaceWith = ReplaceWith( - "LocalImageLoader", - "com.husseinala.neon.core.LocalImageLoader" - ) -) -val AmbientImageLoader get() = LocalImageLoader +val LocalImageLoader = + staticCompositionLocalOf { + error("CompositionLocal ImageLoader not present") + } /** * A composable that downloads and display an image using the specified [url]. This will attempt @@ -60,9 +54,9 @@ fun Neon( contentDescription = contentDescription, contentScale = ContentScale.Inside, alignment = Alignment.Center, - modifier = Modifier.fillMaxSize() + modifier = Modifier.fillMaxSize(), ) - } + }, ) { Neon( url = url, @@ -76,7 +70,7 @@ fun Neon( is NeonState.Success -> onSuccess(result) } } - } + }, ) } @@ -97,29 +91,32 @@ fun Neon( url: String, modifier: Modifier = Modifier, transformation: Transformation = Transformation.centerInside(), - content: @Composable (state: NeonState) -> Unit + content: @Composable (state: NeonState) -> Unit, ) { var neonState by remember { mutableStateOf>(NeonState.Loading) } var componentSize by remember { mutableStateOf(IntSize.Zero) } if (componentSize != IntSize.Zero) { LoadImage( - imageConfig = ImageConfig( - id = ImageId.Path(url), - size = componentSize, - transformation = transformation - ), + imageConfig = + ImageConfig( + id = ImageId.Path(url), + size = componentSize, + transformation = transformation, + ), onLoaded = { neonState = NeonState.Success(it) }, - onFailure = { NeonState.Error(it) } + onFailure = { NeonState.Error(it) }, ) } Box( - modifier = modifier then Modifier.onSizeChanged { size -> - if (componentSize != size) componentSize = size - } + modifier = + modifier then + Modifier.onSizeChanged { size -> + if (componentSize != size) componentSize = size + }, ) { content(neonState) } @@ -136,21 +133,22 @@ fun Neon( fun LoadImage( imageConfig: ImageConfig<*>, onLoaded: (ImageBitmap) -> Unit, - onFailure: (Throwable) -> Unit + onFailure: (Throwable) -> Unit, ) { val imageLoader = LocalImageLoader.current DisposableEffect( imageConfig, effect = { - val cancelable = imageLoader.getImage( - imageConfig, - onSuccess = onLoaded, - onFailure = onFailure - ) + val cancelable = + imageLoader.getImage( + imageConfig, + onSuccess = onLoaded, + onFailure = onFailure, + ) onDispose { cancelable.cancel() } - } + }, ) } @@ -160,6 +158,9 @@ fun LoadImage( * to fetch the images. */ @Composable -fun ProvideImageLoader(imageLoader: ImageLoader, children: @Composable () -> Unit) { - Providers(LocalImageLoader provides imageLoader, content = children) +fun ProvideImageLoader( + imageLoader: ImageLoader, + children: @Composable () -> Unit, +) { + CompositionLocalProvider(LocalImageLoader provides imageLoader, content = children) } diff --git a/core/src/main/java/com/husseinala/neon/core/NeonState.kt b/core/src/main/java/com/husseinala/neon/core/NeonState.kt index 3ce830c..a18fd01 100644 --- a/core/src/main/java/com/husseinala/neon/core/NeonState.kt +++ b/core/src/main/java/com/husseinala/neon/core/NeonState.kt @@ -4,5 +4,6 @@ sealed class NeonState { object Loading : NeonState() data class Success(val result: T) : NeonState() + data class Error(val error: Throwable) : NeonState() } diff --git a/core/src/main/java/com/husseinala/neon/core/Transformation.kt b/core/src/main/java/com/husseinala/neon/core/Transformation.kt index 6895f9f..b839400 100644 --- a/core/src/main/java/com/husseinala/neon/core/Transformation.kt +++ b/core/src/main/java/com/husseinala/neon/core/Transformation.kt @@ -5,25 +5,27 @@ package com.husseinala.neon.core * be combined with other transformations to create a new [CombinedTransformation] instance. */ interface Transformation : Iterable { - - override fun iterator(): Iterator = - SingleItemIterator(this) - - operator fun plus(other: Transformation): Transformation = when { - other === this -> this - this is CombinedTransformation -> when (other) { - is CombinedTransformation -> CombinedTransformation( - transformations + other.transformations - ) - else -> copy(transformations + other) + override fun iterator(): Iterator = SingleItemIterator(this) + + operator fun plus(other: Transformation): Transformation = + when { + other === this -> this + this is CombinedTransformation -> + when (other) { + is CombinedTransformation -> + CombinedTransformation( + transformations + other.transformations, + ) + else -> copy(transformations + other) + } + else -> + CombinedTransformation( + listOf( + this, + other, + ), + ) } - else -> CombinedTransformation( - listOf( - this, - other - ) - ) - } companion object : Transformation } @@ -37,7 +39,6 @@ private data class CombinedTransformation(val transformations: List(private val item: T) : Iterator { - private var hasNext: Boolean = true override fun hasNext(): Boolean = hasNext diff --git a/glide/build.gradle b/glide/build.gradle index 0eb6bd7..1b0ce98 100644 --- a/glide/build.gradle +++ b/glide/build.gradle @@ -16,6 +16,7 @@ spotless { } android { + namespace "com.husseinala.neon.glide" compileSdkVersion Versions.COMPILE_SDK defaultConfig { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index db09750..dc46423 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Sat Feb 06 14:08:00 BST 2021 +#Thu Jan 10 19:08:00 GMT 2024 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.2-bin.zip distributionPath=wrapper/dists -zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/picasso/build.gradle b/picasso/build.gradle index 1440f4f..fed8acd 100644 --- a/picasso/build.gradle +++ b/picasso/build.gradle @@ -16,6 +16,7 @@ spotless { } android { + namespace "com.husseinala.neon.picasso" compileSdkVersion Versions.COMPILE_SDK defaultConfig { diff --git a/sample/build.gradle b/sample/build.gradle index 78e83d9..d0e0d08 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -18,7 +18,7 @@ android { compileSdkVersion Versions.COMPILE_SDK defaultConfig { - applicationId "com.husseinala.neon.sample" + namespace "com.husseinala.neon.sample" minSdkVersion Versions.MIN_SDK targetSdkVersion Versions.TARGET_SDK versionCode 1 diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index 36c72e5..b7a79de 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -11,7 +11,9 @@ android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Neon"> - +