-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6578e52
commit 171449c
Showing
12 changed files
with
651 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
58 changes: 58 additions & 0 deletions
58
deeplinks-plugin/src/main/kotlin/com/freeletics/khonshu/deeplinks/plugin/Configuration.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package com.freeletics.khonshu.deeplinks.plugin | ||
|
||
import com.freeletics.khonshu.navigation.deeplinks.DeepLinkHandler | ||
import com.freeletics.khonshu.navigation.deeplinks.DeepLinkHandler.Pattern | ||
import kotlinx.serialization.KSerializer | ||
import kotlinx.serialization.Serializable | ||
import kotlinx.serialization.descriptors.PrimitiveKind | ||
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor | ||
import kotlinx.serialization.descriptors.SerialDescriptor | ||
import kotlinx.serialization.encoding.Decoder | ||
import kotlinx.serialization.encoding.Encoder | ||
|
||
@Serializable | ||
internal data class Configuration( | ||
val prefixes: List<Prefix> = emptyList(), | ||
val placeholders: List<Placeholder> = emptyList(), | ||
val deepLinks: Map<String, DeepLink>, | ||
) | ||
|
||
@Serializable | ||
internal data class DeepLink( | ||
val patterns: List< | ||
@Serializable(PatternSerializer::class) | ||
Pattern, | ||
>, | ||
val prefixes: List<Prefix>? = null, // use global if null | ||
val placeholders: List<Placeholder>? = null, // use global if null or if key not found | ||
) | ||
|
||
@Serializable | ||
internal data class Prefix( | ||
val scheme: String, | ||
val host: String, | ||
val autoVerified: Boolean, | ||
) { | ||
init { | ||
// for validation purposes | ||
DeepLinkHandler.Prefix("$scheme://$host") | ||
} | ||
} | ||
|
||
@Serializable | ||
internal data class Placeholder( | ||
val key: String, | ||
val values: List<String>, | ||
) | ||
|
||
internal object PatternSerializer : KSerializer<Pattern> { | ||
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("Pattern", PrimitiveKind.STRING) | ||
|
||
override fun deserialize(decoder: Decoder): Pattern { | ||
return Pattern(decoder.decodeString()) | ||
} | ||
|
||
override fun serialize(encoder: Encoder, value: Pattern) { | ||
throw UnsupportedOperationException() | ||
} | ||
} |
23 changes: 0 additions & 23 deletions
23
deeplinks-plugin/src/main/kotlin/com/freeletics/khonshu/deeplinks/plugin/Deeplinks.kt
This file was deleted.
Oops, something went wrong.
100 changes: 100 additions & 0 deletions
100
.../src/main/kotlin/com/freeletics/khonshu/deeplinks/plugin/DeeplinksManifestConfigurator.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
package com.freeletics.khonshu.deeplinks.plugin | ||
|
||
import com.freeletics.khonshu.navigation.deeplinks.DeepLinkHandler | ||
import com.freeletics.khonshu.navigation.deeplinks.replacePlaceholders | ||
import com.freeletics.khonshu.navigation.internal.InternalNavigationApi | ||
import java.io.File | ||
import net.peanuuutz.tomlkt.Toml | ||
|
||
|
||
private const val PLACEHOLDER = "<!-- DEEPLINK INTENT FILTERS -->" | ||
|
||
internal fun configure( | ||
configurationFile: File, | ||
inputManifestFile: File, | ||
outputManifestFile: File, | ||
) { | ||
val manifest = inputManifestFile.readLines().toMutableList() | ||
val placeholderIndex = manifest.indexOfFirst { it.contains(PLACEHOLDER) } | ||
check(placeholderIndex >= 0) { | ||
"Did not find $PLACEHOLDER in given manifest ${inputManifestFile.absolutePath}" | ||
} | ||
|
||
val configuration = Toml.decodeFromString(Configuration.serializer(), configurationFile.readText()) | ||
val indentation = manifest[placeholderIndex].takeWhile { it == ' ' } | ||
manifest[placeholderIndex] = intentFiltersFromConfig(configuration, indentation) | ||
|
||
outputManifestFile.writeText(manifest.joinToString(separator = "\n")) | ||
} | ||
|
||
private fun intentFiltersFromConfig(configuration: Configuration, indentation: String): String { | ||
val builder = IntentFilterBuilder(indentation) | ||
|
||
val deepLinksWithGlobalPrefixes = configuration.deepLinks.values.filter { it.prefixes == null } | ||
if (deepLinksWithGlobalPrefixes.isNotEmpty()) { | ||
check(configuration.prefixes.isNotEmpty()) { | ||
"Configuration contains deep links without a prefix but has no global prefixes" | ||
} | ||
|
||
configuration.prefixes.forEach { prefix -> | ||
builder.appendIntentFilter(prefix, deepLinksWithGlobalPrefixes) | ||
} | ||
} | ||
|
||
configuration.deepLinks.values.filter { it.prefixes != null }.forEach { | ||
it.prefixes!!.forEach { prefix -> | ||
builder.appendIntentFilter(prefix, listOf(it)) | ||
} | ||
} | ||
|
||
return builder.toString().trim() | ||
} | ||
|
||
private fun IntentFilterBuilder.appendIntentFilter(prefix: Prefix, deepLinks: List<DeepLink>) { | ||
start(prefix.autoVerified) | ||
appendAction("android.intent.action.VIEW") | ||
appendCategory("android.intent.category.DEFAULT") | ||
appendCategory("android.intent.category.BROWSABLE") | ||
|
||
deepLinks.forEach { deepLink -> | ||
deepLink.patterns.forEach { pattern -> | ||
appendData(prefix.scheme, prefix.host, pattern) | ||
} | ||
} | ||
end() | ||
} | ||
|
||
private class IntentFilterBuilder( | ||
private val indentation: String, | ||
) { | ||
private val builder = StringBuilder() | ||
|
||
fun start(autoVerify: Boolean) { | ||
builder.appendLine("$indentation<intent-filter android:autoVerify=\"${autoVerify}\">") | ||
} | ||
|
||
fun appendAction(action: String) { | ||
builder.appendLine("$indentation <action android:name=\"${action}\" />") | ||
} | ||
|
||
fun appendCategory(category: String) { | ||
builder.appendLine("$indentation <action android:name=\"${category}\" />") | ||
} | ||
|
||
@OptIn(InternalNavigationApi::class) | ||
fun appendData(scheme: String, host: String, pathPattern: DeepLinkHandler.Pattern) { | ||
builder.appendLine("$indentation <data") | ||
builder.appendLine("$indentation android:scheme=\"${scheme}\"") | ||
builder.appendLine("$indentation android:host=\"${host}\"") | ||
builder.appendLine("$indentation android:pathPattern=\"/${pathPattern.replacePlaceholders(".*")}\"") | ||
builder.appendLine("$indentation />") | ||
} | ||
|
||
fun end() { | ||
builder.appendLine("$indentation</intent-filter>") | ||
} | ||
|
||
override fun toString(): String { | ||
return builder.toString() | ||
} | ||
} |
32 changes: 6 additions & 26 deletions
32
.../main/kotlin/com/freeletics/khonshu/deeplinks/plugin/DeeplinksManifestConfiguratorTask.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,48 +1,28 @@ | ||
package com.freeletics.khonshu.deeplinks.plugin | ||
|
||
import java.io.File | ||
import org.gradle.api.DefaultTask | ||
import org.gradle.api.file.RegularFileProperty | ||
import org.gradle.api.tasks.InputFile | ||
import org.gradle.api.tasks.OutputFile | ||
import org.gradle.api.tasks.TaskAction | ||
|
||
abstract class DeeplinksManifestConfiguratorTask : DefaultTask() { | ||
public abstract class DeeplinksManifestConfiguratorTask : DefaultTask() { | ||
|
||
@get:InputFile | ||
abstract val deeplinksConfigurationFile: RegularFileProperty | ||
public abstract val deeplinksConfigurationFile: RegularFileProperty | ||
|
||
@get:InputFile | ||
abstract val mergedManifest: RegularFileProperty | ||
public abstract val mergedManifest: RegularFileProperty | ||
|
||
@get:OutputFile | ||
abstract val updatedManifest: RegularFileProperty | ||
public abstract val updatedManifest: RegularFileProperty | ||
|
||
@TaskAction | ||
fun taskAction() { | ||
public fun taskAction() { | ||
val configurationFile = deeplinksConfigurationFile.get().asFile | ||
val inputManifest = mergedManifest.get().asFile | ||
val outputManifest = updatedManifest.get().asFile | ||
|
||
DeeplinksManifestConfigurator(configurationFile, inputManifest, outputManifest).configure() | ||
} | ||
} | ||
|
||
internal class DeeplinksManifestConfigurator( | ||
private val configurationFile: File, | ||
private val inputManifestFile: File, | ||
private val outputManifestFile: File, | ||
) { | ||
fun configure() { | ||
val configuration = configurationFile.readText() | ||
|
||
var manifest = inputManifestFile.readText() | ||
manifest = manifest.replace(PLACEHOLDER, configuration) | ||
|
||
outputManifestFile.writeText(manifest) | ||
} | ||
|
||
companion object { | ||
const val PLACEHOLDER = "<!-- DEEPLINK INTENT FILTERS -->" | ||
configure(configurationFile, inputManifest, outputManifest) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.