Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Compose, Kotlin, and Gradle to latest versions #9

Merged
merged 3 commits into from
Jan 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[*.{kt,kts}]
ktlint_function_naming_ignore_when_annotated_with=Composable
17 changes: 17 additions & 0 deletions .github/workflows/pr_check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: Run Gradle on PRs
on: pull_request
jobs:
pr-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 17

- name: Setup Gradle
uses: gradle/gradle-build-action@v2

- name: Execute Gradle
run: ./gradlew spotlessCheck testDebugUnitTest
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 1 addition & 3 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .idea/compiler.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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"
}
Expand Down
2 changes: 1 addition & 1 deletion buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
repositories {
jcenter()
mavenCentral()
}

plugins {
Expand Down
17 changes: 9 additions & 8 deletions buildSrc/src/main/java/com/husseinala/neon/Dependencies.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand All @@ -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"
Expand Down
5 changes: 3 additions & 2 deletions core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -43,7 +44,7 @@ android {
}

composeOptions {
kotlinCompilerExtensionVersion Versions.COMPOSE
kotlinCompilerExtensionVersion Versions.COMPOSE_COMPILER
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 2 additions & 5 deletions core/src/main/java/com/husseinala/neon/core/ImageLoader.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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].
*
Expand All @@ -18,7 +17,7 @@ interface ImageLoader {
fun getImage(
imageConfig: ImageConfig<*>,
onSuccess: (ImageBitmap) -> Unit,
onFailure: (Exception) -> Unit
onFailure: (Exception) -> Unit,
): Cancelable
}

Expand All @@ -33,14 +32,13 @@ interface ImageLoader {
data class ImageConfig<T>(
val id: ImageId<T>,
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<T> {

abstract val value: T

/**
Expand Down Expand Up @@ -76,7 +74,6 @@ sealed class ImageId<T> {
* An interface that's used to indicate a cancelable request.
*/
fun interface Cancelable {

/**
* Attempts to cancel execution of the current request.
*/
Expand Down
67 changes: 34 additions & 33 deletions core/src/main/java/com/husseinala/neon/core/Neon.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<ImageLoader>()

@Deprecated(
"Renamed to LocalImageLoader",
replaceWith = ReplaceWith(
"LocalImageLoader",
"com.husseinala.neon.core.LocalImageLoader"
)
)
val AmbientImageLoader get() = LocalImageLoader
val LocalImageLoader =
staticCompositionLocalOf<ImageLoader> {
error("CompositionLocal ImageLoader not present")
}

/**
* A composable that downloads and display an image using the specified [url]. This will attempt
Expand Down Expand Up @@ -60,9 +54,9 @@ fun Neon(
contentDescription = contentDescription,
contentScale = ContentScale.Inside,
alignment = Alignment.Center,
modifier = Modifier.fillMaxSize()
modifier = Modifier.fillMaxSize(),
)
}
},
) {
Neon(
url = url,
Expand All @@ -76,7 +70,7 @@ fun Neon(
is NeonState.Success -> onSuccess(result)
}
}
}
},
)
}

Expand All @@ -97,29 +91,32 @@ fun Neon(
url: String,
modifier: Modifier = Modifier,
transformation: Transformation = Transformation.centerInside(),
content: @Composable (state: NeonState<ImageBitmap>) -> Unit
content: @Composable (state: NeonState<ImageBitmap>) -> Unit,
) {
var neonState by remember { mutableStateOf<NeonState<ImageBitmap>>(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)
}
Expand All @@ -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() }
}
},
)
}

Expand All @@ -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)
}
1 change: 1 addition & 0 deletions core/src/main/java/com/husseinala/neon/core/NeonState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ sealed class NeonState<out T> {
object Loading : NeonState<Nothing>()

data class Success<T>(val result: T) : NeonState<T>()

data class Error(val error: Throwable) : NeonState<Nothing>()
}
Loading