All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.com.freeletics.khonshu.navigation.deeplinks.DeepLinkParser.kt Maven / Gradle / Ivy

There is a newer version: 0.29.1
Show newest version
package com.freeletics.khonshu.navigation.deeplinks

import com.eygraber.uri.Uri
import com.freeletics.khonshu.navigation.deeplinks.DeepLinkHandler.Prefix
import com.freeletics.khonshu.navigation.internal.InternalNavigationApi

/**
 * Checks if the given [uri] matches one of the [DeepLinkHandler] in the `Set` and if yes
 * creates a [DeepLink]. Otherwise `null` is returned.
 *
 * [defaultPrefixes] will be used as base url if [DeepLinkHandler.prefixes] is empty.
 */
@InternalNavigationApi
public fun Set.createDeepLinkIfMatching(
    uri: Uri,
    defaultPrefixes: Set,
): DeepLink? {
    forEach {
        val result = it.createDeepLinkIfMatching(uri, defaultPrefixes)
        if (result != null) {
            return result
        }
    }

    return null
}

/**
 * Checks if the given [uri] matches one of [DeepLinkHandler.patterns] and if yes
 * create a [DeepLink]. Otherwise `null` is returned.
 *
 * [defaultPrefixes] will be used as base url if [DeepLinkHandler.prefixes] is empty.
 */
@InternalNavigationApi
public fun DeepLinkHandler.createDeepLinkIfMatching(
    uri: Uri,
    defaultPrefixes: Set,
): DeepLink? {
    val matchingPattern = findMatchingPattern(uri.toString(), defaultPrefixes) ?: return null
    return deepLink(matchingPattern.extractPathParameters(uri), uri.queryParameters)
}

internal fun DeepLinkHandler.Pattern.extractPathParameters(uri: Uri): MutableMap {
    // create a Uri with the pattern so that we can get the placeholder names and their indices
    // the prefix (domain) does not matter so we use a hardcoded one
    val patternUri = Uri.parse("https://example.com/$value")

    // this check should never fail since the regex matched
    check(uri.pathSegments.size == patternUri.pathSegments.size) {
        "$uri and $patternUri have a different number of path segments"
    }

    val pathParameters = mutableMapOf()
    patternUri.pathSegments.forEachIndexed { index, segment ->
        // when a segment is a placeholder extract the name and get the value from the real uri
        if (segment.startsWith("{") && segment.endsWith("}")) {
            pathParameters[segment.substring(1, segment.length - 1)] = uri.pathSegments[index]
        }
    }

    return pathParameters
}

internal val Uri.queryParameters: Map
    get() = getQueryParameterNames().associateWith { queryParam ->
        getQueryParameter(queryParam)!!
    }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy