Skip to content

Commit

Permalink
Merge remote-tracking branch 'libres/master' into feature/night-support
Browse files Browse the repository at this point in the history
# Conflicts:
#	gradle-plugin/src/main/java/io/github/skeptick/libres/plugin/LibresImagesGenerationTask.kt
  • Loading branch information
Sven Obser committed Dec 12, 2023
2 parents 5253bc9 + 4e0b76d commit 3a2b9d0
Show file tree
Hide file tree
Showing 43 changed files with 363 additions and 258 deletions.
148 changes: 72 additions & 76 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Resources generation in Kotlin Multiplatform.

buildscript {
dependencies {
classpath("io.github.skeptick.libres:gradle-plugin:1.1.8")
classpath("io.github.skeptick.libres:gradle-plugin:1.2.2")
}
}
```
Expand All @@ -25,16 +25,32 @@ libres {
generatedClassName = "MainRes" // "Res" by default
generateNamedArguments = true // false by default
baseLocaleLanguageCode = "ru" // "en" by default
camelCaseNamesForAppleFramework = true // false by default
camelCaseNamesForAppleFramework = false // false by default
}
```

## Jetpack Compose

```kotlin
// build.gradle.kts (module)

kotlin {
commonMain {
dependencies {
implementation("io.github.skeptick.libres:libres-compose:1.2.2")
}
}
}
```

This artifact provides `painterResource` function that can be used
to get `Painter` from `io.github.skeptick.libres.Image` in common code.

## Supported platforms

- **Android**, **JVM**, **iOS**, **MacOS** and **JS** in Kotlin Multiplatform projects.
- Pure Android or JVM projects with Kotlin.


## Requirements

| | |
Expand All @@ -44,11 +60,32 @@ libres {
| Android Gradle Plugin | 7.0+ |
| iOS | 13+ (when using vector icons) |

Also you need to use [CocoaPods](https://cocoapods.org/) and
\
:bangbang: Also you need to use [CocoaPods](https://cocoapods.org/) and
[CocoaPods Gradle plugin](https://kotlinlang.org/docs/native-cocoapods-dsl-reference.html)
to export images to iOS project.
to export images to iOS application.
If you aren't reusing images in iOS then this condition is optional.

## Known issues

### iOS
:warning: Cocoapods caches list of resource directories when `pod install` is called,
so bundles directory must exist at this time.
You won't see this issue if your `.podspec` is in `.gitignore`
in any case it's best to be safe with this hook in your Podfile.

Suppose your Kotlin Framework is added like this:
```ruby
pod 'umbrella', :path => '../common/umbrella/umbrella.podspec'
```

Then this hook will look like this:
```ruby
pre_install do |installer|
FileUtils.mkdir_p(installer.sandbox.root.to_s + '/../../common/umbrella/build/generated/libres/apple/libres-bundles')
end
```

## Usage

Resources must be stored in `{yourSourceSetName}/libres`
Expand Down Expand Up @@ -80,9 +117,9 @@ Android or JVM:
```

### Strings
Strings are stored in the usual for Android form in `xml` files.
The file postfix must contain the code of the language for which the strings are intended. E.g.: `my_app_strings_en.xml`
For each of the languages you can create several files and they will be merged during compilation.
Strings are stored in usual for Android form in `xml` files.
The file postfix must contain language code for which these strings are intended. E.g.: `my_app_strings_en.xml`
For each of languages you can create several files and they will be merged during compilation.
```xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
Expand All @@ -104,13 +141,14 @@ MainRes.string.plural_string.format(5)
Swift:
```swift
MainRes.shared.string.simple_string
// or MainRes.shared.string.simpleString if `camelCaseNamesForAppleFramework` enabled
```
***
> **Note**
> In the example above `MainRes.string.simple_string` will return a string,
> In this example `MainRes.string.simple_string` will return a string,
> so for better localization support it's not recommended to store the value.
> Get it directly at the place where it's displayed in the UI.
> This seems familiar but the ability to work directly with strings instead of resource IDs can be misused.
> Get it directly at the place where it's displayed in UI.
> This seems familiar but ability to work directly with strings instead of resource IDs can be misused.
***
#### [More about localization](docs/LOCALIZATION.md)

Expand All @@ -122,7 +160,7 @@ Supported formats:
- WEBP (Android 4.3+, iOS 14+)
- SVG (iOS 13+)

For Android SVG are converted to
For Android SVGs are converted to
[vector drawable](https://developer.android.com/develop/ui/views/graphics/vector-drawable-resources),
for other platforms they copied as is.

Expand All @@ -131,15 +169,15 @@ The image filename can contain modifiers in parentheses listed through underscor

> **orig**
>
> Used for iOS. Marks the image as `Original` (similar to `Render As: Original Image` in the Assets Manager in XCode).
> Used for iOS. Marks image as `Original` (similar to `Render As: Original Image` in XCode Assets Manager).
Recommended for multicolor images.

> **size**
>
> Applies to bitmaps. Reduces the image resolution to the specified size.
> - For Android images are generated from mdpi to xxxhdpi (where mdpi is 1:1 in pixels to the specified size)
> - For iOS images are generated from 1x to 3x (where 1x is 1:1 in pixels to the specified size)
> - For JVM and JS a single image of the specified size is generated.
> Applies to bitmaps. Reduces image resolution to specified size.
> - For Android generate images from mdpi to xxxhdpi (where mdpi is 1:1 in pixels to specified size)
> - For iOS generate images from @1x to @3x (where @1x is 1:1 in pixels to specified size)
> - For JVM and JS a single image of specified size is generated.
> **night**
>
Expand All @@ -165,71 +203,29 @@ MainRes.image.image_with_night_support
```
Swift:
```swift
MainRes.shared.image.some_hd_image // -> UIImage
MainRes.shared.image.some_hd_image
// or MainRes.shared.image.someHdImage if `camelCaseNamesForAppleFramework` enabled
```

<details>
<summary>How to export an image from Figma</summary>
<summary><h3>Why do I see a black/blue box instead of my picture?</h3></summary>

To obtain bundle of png images with different resolutions (e.g. mdpi - xxxhdpi on Android) do the following steps
1. Export image from Figma with x4 scale (it matches to the biggest used size (xxxhdpi on Android))
2. Put it to libres/images package
3. Remember the biggest side value of image represented in Figma
4. Rename image with the value of the biggest side: from **pic.png** to **pic_(orig)_({side_value})** or **pic_({side_value})**
I'm pretty sure your picture is multicolor JPG/SVG with opaque background.
This happens because UIKit recolors this image with accent color.

Sample:
Image size in Figma is **240x89**. Final image name is **pic_(orig)_(240).png**
Solution: add (orig) modifier to image filename, e.g.: `my_image_(orig).png`
</details>

## Jetpack Compose

```kotlin
// build.gradle.kts (module)

kotlin {
commonMain {
dependencies {
implementation("io.github.skeptick.libres:libres-compose:1.1.8")
}
}
}
```

This artifact provides `painterResource` function that can be used
to get `Painter` from `io.github.skeptick.libres.Image` in common code.

## Known issues

### iOS
⚠️ Add the following code to your Podfile to avoid issues with the release build of your iOS app:
```ruby
post_install do |installer|
installer.pods_project.targets.each do |target|
if target.respond_to?(:product_type) and target.product_type == "com.apple.product-type.bundle"
target.build_configurations.each do |config|
config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
end
end
end
end
```
***
<details>
<summary><h3>How to export bitmap from Figma?</h3></summary>

### Android
⚠️ In AGP 7+ there is a bug due to which the directory with generated images
is not included in the build sourceset. Bug fixed in 8-beta.
Workaround for versions 7+:
```
// build.gradle.kts (module)
To obtain bundle of PNG images with different resolutions (mdpi-xxxhdpi for Android and @1x-@3x for iOS) do following steps:
1. Export image from Figma with x4 scale (it matches to the biggest used size — xxxhdpi on Android)
2. Put it to `libres/images` package
3. Remember the biggest side value of image represented in Figma
4. Rename image with the value of the biggest side:
**pic.png** -> **pic_(orig)_({side_value}).png** or **pic_({side_value}).png**

android {
...
...
sourceSets {
named("main") {
res.srcDir("build/generated/libres/android/resources")
}
}
}
```
Sample:
Image size in Figma is **240x89**. Final image name is **pic_(orig)_(240).png**
</details>
2 changes: 0 additions & 2 deletions buildSrc/settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
@file:Suppress("UnstableApiUsage")

enableFeaturePreview("VERSION_CATALOGS")

dependencyResolutionManagement {
versionCatalogs {
create("libs") {
Expand Down
3 changes: 1 addition & 2 deletions buildSrc/src/main/kotlin/android-setup-plugin.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@ plugins {
}

android {
compileSdk = 33
compileSdk = 34

defaultConfig {
minSdk = 16
targetSdk = 33
}

buildFeatures {
Expand Down
36 changes: 6 additions & 30 deletions buildSrc/src/main/kotlin/multiplatform-setup.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
plugins {
id("com.android.library")
kotlin("multiplatform")
}

kotlin {
jvm()
android {
androidTarget {
publishAllLibraryVariants()
}
js(IR) {
Expand All @@ -16,35 +17,10 @@ kotlin {
macosArm64()
macosX64()

sourceSets {
val commonMain by getting
val iosX64Main by getting
val iosArm64Main by getting
val iosSimulatorArm64Main by getting
val macosArm64Main by getting
val macosX64Main by getting

val macosMain by creating {
dependsOn(commonMain)
macosArm64Main.dependsOn(this)
macosX64Main.dependsOn(this)
}

val iosMain by creating {
dependsOn(commonMain)
iosX64Main.dependsOn(this)
iosArm64Main.dependsOn(this)
iosSimulatorArm64Main.dependsOn(this)
}

val appleMain by creating {
dependsOn(commonMain)
macosMain.dependsOn(this)
iosMain.dependsOn(this)
}
}

tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinCompile> {
kotlinOptions.jvmTarget = JavaVersion.VERSION_1_8.toString()
kotlinOptions {
jvmTarget = JavaVersion.VERSION_1_8.toString()
freeCompilerArgs += "-Xexpect-actual-classes"
}
}
}
23 changes: 9 additions & 14 deletions gradle-plugin/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ plugins {
id("com.vanniktech.maven.publish")
}

java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
version = property("VERSION_NAME").toString()

kotlin {
jvmToolchain(11)
}

dependencies {
Expand All @@ -31,16 +32,12 @@ gradlePlugin {
}
}

sourceSets {
getByName("main").java.srcDir("generated")
}

tasks.register("libresVersion") {
val libresVersion = tasks.register("libresVersion") {
val outputDir = file("generated")
inputs.property("version", version)
outputs.dir(outputDir)

doLast {
doFirst {
val text = """
// Generated file. Do not edit!
package io.github.skeptick.libres
Expand All @@ -54,8 +51,6 @@ tasks.register("libresVersion") {
}
}

afterEvaluate {
tasks.withType(org.jetbrains.kotlin.gradle.dsl.KotlinCompile::class.java).configureEach {
dependsOn("libresVersion")
}
}
sourceSets.main.configure {
kotlin.srcDir(libresVersion)
}
Loading

0 comments on commit 3a2b9d0

Please sign in to comment.