blob: 3f29ac0cb3e22eb935e78923d23cfeb0e92b02e7 (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
import groovy.json.JsonSlurper
plugins { id("com.android.application") }
// One version for every package (CLAUDE.md): read from the desktop client's
// package.json rather than written a second time here.
val packageVersion = (JsonSlurper().parse(rootDir.resolve("../meshbay-client/package.json"))
as Map<*, *>)["version"] as String
val versionParts = packageVersion.split(".").map { it.toInt() }
android {
namespace = "org.meshbay.client"
compileSdk = 37
defaultConfig {
applicationId = "org.meshbay.client"
minSdk = 26
targetSdk = 36
versionName = packageVersion
versionCode = versionParts[0] * 10000 + versionParts[1] * 100 + versionParts[2]
}
buildTypes {
getByName("release") {
isMinifyEnabled = false
// A stand-in until the release key exists (Stage D12): the debug
// key, so a release build installs over a debug one and back
// without losing the account. Not a key to publish anything with.
signingConfig = signingConfigs.getByName("debug")
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
buildFeatures { buildConfig = true }
testOptions { unitTests.isReturnDefaultValues = false }
}
dependencies {
implementation("androidx.webkit:webkit:1.17.1")
implementation("com.squareup.okhttp3:okhttp:5.5.0")
// Ed25519, X25519, HKDF and Argon2id, identical on the JVM and every
// Android version: the platform has no Argon2 and its Ed25519 is recent.
implementation("org.bouncycastle:bcprov-jdk18on:1.86")
// Casting: discovery through MediaRouter, control through the cast sender
// SDK and the default media receiver. Needs the vendor's play services at
// run time; where they are absent the page is offered no cast at all.
implementation("com.google.android.gms:play-services-cast-framework:22.3.1")
implementation("androidx.mediarouter:mediarouter:1.8.1")
testImplementation("junit:junit:4.13.2")
// Android's org.json is a stub on the JVM; the unit tests need the real one.
testImplementation("org.json:json:20260814")
}
/**
* The interface, copied from its single source at build time (§8.3).
*
* `meshbay-hub/src/meshbay_hub/static/` is the interface for the web, the
* desktop application and this one. The copy lands in build/ and is never
* committed, so it cannot fork. The page itself is the desktop application's
* `scripts/index.html` — the hub builds its own with a /a/<hash>/ prefix that
* would point back at the hub — so an application loading from its package
* has one page, not two.
*/
abstract class SyncUi : DefaultTask() {
@get:InputDirectory abstract val staticDir: DirectoryProperty
@get:InputFile abstract val indexHtml: RegularFileProperty
@get:OutputDirectory abstract val outputDir: DirectoryProperty
@TaskAction
fun copy() {
val ui = outputDir.get().asFile.resolve("ui")
outputDir.get().asFile.deleteRecursively()
staticDir.get().asFile.copyRecursively(ui)
indexHtml.get().asFile.copyTo(ui.resolve("index.html"), overwrite = true)
}
}
val syncUi = tasks.register<SyncUi>("syncUi") {
staticDir.set(rootDir.resolve("../meshbay-hub/src/meshbay_hub/static"))
indexHtml.set(rootDir.resolve("../meshbay-client/scripts/index.html"))
outputDir.set(layout.buildDirectory.dir("generated/ui-assets"))
}
androidComponents {
onVariants { variant ->
variant.sources.assets?.addGeneratedSourceDirectory(syncUi, SyncUi::outputDir)
}
}
|