com.freeletics.khonshu.deeplinks.plugin.DeeplinksManifestConfigurator.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of deeplinks-plugin Show documentation
Show all versions of deeplinks-plugin Show documentation
A Gradle plugin that generates intent filters in AndroidManifest from deeplink config.
The newest version!
package com.freeletics.khonshu.deeplinks.plugin
import com.freeletics.khonshu.navigation.deeplinks.DeepLinkDefinition
import com.freeletics.khonshu.navigation.deeplinks.DeepLinkDefinitions
import com.freeletics.khonshu.navigation.deeplinks.PatternDefinition
import com.freeletics.khonshu.navigation.deeplinks.PrefixDefinition
import java.io.File
private const val PLACEHOLDER = ""
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 definitions = DeepLinkDefinitions.decodeFromString(configurationFile.readText())
val indentation = manifest[placeholderIndex].takeWhile { it == ' ' }
manifest[placeholderIndex] = intentFiltersFromConfig(definitions, indentation)
outputManifestFile.writeText(manifest.joinToString(separator = "\n"))
}
private fun intentFiltersFromConfig(definitions: DeepLinkDefinitions, indentation: String): String {
val builder = IntentFilterBuilder(indentation)
val deepLinksWithGlobalPrefixes = definitions.deepLinks.values.filter { it.prefixes.isEmpty() }
if (deepLinksWithGlobalPrefixes.isNotEmpty()) {
check(definitions.prefixes.isNotEmpty()) {
"Configuration contains deep links without a prefix but has no global prefixes"
}
definitions.prefixes.forEach { prefix ->
builder.appendIntentFilter(prefix, deepLinksWithGlobalPrefixes)
}
}
definitions.deepLinks.values.filter { it.prefixes.isNotEmpty() }.forEach {
it.prefixes.forEach { prefix ->
builder.appendIntentFilter(prefix, listOf(it))
}
}
return builder.toString()
}
private fun IntentFilterBuilder.appendIntentFilter(prefix: PrefixDefinition, deepLinks: List) {
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")
}
fun appendAction(action: String) {
builder.appendLine("$indentation ")
}
fun appendCategory(category: String) {
builder.appendLine("$indentation ")
}
fun appendData(scheme: String, host: String, pattern: PatternDefinition) {
val pathPattern = pattern.replacePlaceholders { ".*" }
builder.appendLine("$indentation ")
}
fun end() {
builder.appendLine("$indentation ")
}
override fun toString(): String {
return builder.toString().trimEnd()
}
}