Skip to content

Conversation

@KonradIT
Copy link
Contributor

@KonradIT KonradIT commented Dec 7, 2025

Hi all!

These two apps:

Do not use pebblejs://close# URL scheme when passing data back to the mobile app.

Pebblify Solanum
imagen imagen

The pebble documentation specifically states this must be the case: https://pebble.github.io/pebblejs/#settings

document.location = 'pebblejs://close#' + encodeURIComponent(JSON.stringify(options));

URI encode your options json as the hash to pebblejs://close. This will close your configurable

The original pebble app worked with these apps, so pebble technology corp was aware that not all developers would follow the documentation by the book and added some wiggle room in how to intercept the close URLs.

I used this snippet to develop the fix:

import io.ktor.http.decodeURLPart

data class WebRequest(val url: String)

fun main() {
    println("PebbleJS close interceptor test")
    
    val badPrefix = "pebblejs://close#"

    val request = WebRequest(url = "pebblejs://close/?token=abc123&state=success")
    val request2 = WebRequest(url = "pebblejs://close#token=abc123&state=success")
    val request3 = WebRequest(url = "pebblejs://close")

    val howitshouldbe = request2.url.removePrefix(badPrefix).decodeURLPart()
    if (howitshouldbe.isNotEmpty()) {
        println("current app prefix with compliant url: $howitshouldbe")
    } // output: token=abc123&state=success

    // Matches pebblejs://close followed by #, /, or /? and captures the query params
    val closeUrlRegex = Regex("""^pebblejs://close(?:#|/\?|/)(.*)$""")

    fun extractParams(url: String): String? {
        return closeUrlRegex.find(url)?.groupValues?.get(1)?.decodeURLPart()
    }

    val data1 = extractParams(request.url)
    if (data1?.isNotEmpty() == true) {
        println("request1 params: $data1")
    }

    val data2 = extractParams(request2.url)
    if (data2?.isNotEmpty() == true) {
        println("request2 params: $data2")
    }

    val data3 = extractParams(request3.url)
    if (data3?.isNotEmpty() == true) {
        println("request3 params: $data3")
    }
}
PebbleJS close interceptor test
current app prefix with compliant url: token=abc123&state=success
request1 params: token=abc123&state=success
request2 params: token=abc123&state=success

@sjp4 sjp4 requested a review from crc-32 December 15, 2025 16:47
@sjp4
Copy link
Member

sjp4 commented Dec 15, 2025

@crc-32 can you take a look at this one?

@KonradIT
Copy link
Contributor Author

rebased off of main to get the test fixes, now CI passes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants