vaderjs-native 1.0.23 → 1.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/cli/android/build.ts +4 -2
  2. package/cli/binaries/fetch.ts +56 -0
  3. package/package.json +5 -9
  4. package/templates/android/.gradle/9.1.0/checksums/checksums.lock +0 -0
  5. package/templates/android/.gradle/9.1.0/fileChanges/last-build.bin +0 -0
  6. package/templates/android/.gradle/9.1.0/fileHashes/fileHashes.lock +0 -0
  7. package/templates/android/.gradle/9.1.0/gc.properties +0 -0
  8. package/templates/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  9. package/templates/android/.gradle/buildOutputCleanup/cache.properties +0 -2
  10. package/templates/android/.gradle/vcs-1/gc.properties +0 -0
  11. package/templates/android/app/build.gradle.kts +0 -54
  12. package/templates/android/app/proguard-rules.pro +0 -21
  13. package/templates/android/app/src/main/AndroidManifest.xml +0 -33
  14. package/templates/android/app/src/main/java/myapp/AndroidBridge.kt +0 -199
  15. package/templates/android/app/src/main/java/myapp/MainActivity.kt +0 -133
  16. package/templates/android/app/src/main/res/mipmap-hdpi/ic_launcher.webp +0 -0
  17. package/templates/android/app/src/main/res/mipmap-mdpi/ic_launcher.webp +0 -0
  18. package/templates/android/app/src/main/res/mipmap-xhdpi/ic_launcher.webp +0 -0
  19. package/templates/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp +0 -0
  20. package/templates/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp +0 -0
  21. package/templates/android/app/src/main/res/values/strings.xml +0 -3
  22. package/templates/android/app/src/main/res/values/themes.xml +0 -4
  23. package/templates/android/build.gradle.kts +0 -5
  24. package/templates/android/gradle/libs.versions.toml +0 -30
  25. package/templates/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  26. package/templates/android/gradle/wrapper/gradle-wrapper.properties +0 -9
  27. package/templates/android/gradle.properties +0 -23
  28. package/templates/android/gradlew +0 -251
  29. package/templates/android/gradlew.bat +0 -94
  30. package/templates/android/local.properties +0 -1
  31. package/templates/android/settings.gradle.kts +0 -23
  32. package/templates/i.txt +0 -1
  33. package/templates/windows/App1/App1/App.xaml +0 -16
  34. package/templates/windows/App1/App1/App.xaml.cs +0 -50
  35. package/templates/windows/App1/App1/App1.csproj +0 -41
  36. package/templates/windows/App1/App1/App1.csproj.user +0 -12
  37. package/templates/windows/App1/App1/MainWindow.xaml +0 -16
  38. package/templates/windows/App1/App1/MainWindow.xaml.cs +0 -417
  39. package/templates/windows/App1/App1/Properties/PublishProfiles/win-arm64.pubxml +0 -14
  40. package/templates/windows/App1/App1/Properties/PublishProfiles/win-x64.pubxml +0 -14
  41. package/templates/windows/App1/App1/Properties/PublishProfiles/win-x86.pubxml +0 -14
  42. package/templates/windows/App1/App1/app.manifest +0 -17
  43. package/templates/windows/App1/App1/obj/App1.csproj.nuget.dgspec.json +0 -143
  44. package/templates/windows/App1/App1/obj/App1.csproj.nuget.g.props +0 -36
  45. package/templates/windows/App1/App1/obj/App1.csproj.nuget.g.targets +0 -18
  46. package/templates/windows/App1/App1/obj/project.assets.json +0 -3321
  47. package/templates/windows/App1/App1/obj/project.nuget.cache +0 -33
  48. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/.NETCoreApp,Version=v8.0.AssemblyAttributes.cs +0 -4
  49. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/App.g.cs +0 -17
  50. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/App.g.i.cs +0 -75
  51. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/App.xaml +0 -17
  52. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/App.xbf +0 -0
  53. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/App1.AssemblyInfo.cs +0 -25
  54. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/App1.AssemblyInfoInputs.cache +0 -1
  55. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/App1.GeneratedMSBuildEditorConfig.editorconfig +0 -25
  56. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/App1.assets.cache +0 -0
  57. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/App1.csproj.AssemblyReference.cache +0 -0
  58. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/App1.csproj.BuildWithSkipAnalyzers +0 -0
  59. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/App1.csproj.CoreCompileInputs.cache +0 -1
  60. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/App1.csproj.FileListAbsolute.txt +0 -99
  61. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/App1.csproj.Up2Date +0 -0
  62. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/App1.designer.deps.json +0 -314
  63. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/App1.designer.runtimeconfig.json +0 -19
  64. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/App1.dll +0 -0
  65. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/App1.genruntimeconfig.cache +0 -1
  66. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/App1.pdb +0 -0
  67. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/MainWindow.g.cs +0 -51
  68. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/MainWindow.g.i.cs +0 -47
  69. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/MainWindow.xaml +0 -17
  70. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/MainWindow.xbf +0 -0
  71. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/MultipleQualifiersPerDimensionFound.txt +0 -1
  72. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/XamlSaveStateFile.xml +0 -1
  73. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/XamlTypeInfo.g.cs +0 -1054
  74. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/apphost.exe +0 -0
  75. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/embed/embed.resfiles +0 -0
  76. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/embed/embed.resfiles.intermediate +0 -0
  77. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/excluded.layout.resfiles +0 -0
  78. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/excluded.layout.resfiles.intermediate +0 -0
  79. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/filtered.layout.resfiles +0 -11
  80. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/filtered.layout.resfiles.intermediate +0 -11
  81. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/intermediatexaml/App1.dll +0 -0
  82. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/pri.resfiles +0 -0
  83. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/pri.resfiles.intermediate +0 -0
  84. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/priconfig.xml +0 -67
  85. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/priconfig.xml.intermediate +0 -67
  86. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/qualifiers.txt +0 -0
  87. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/qualifiers.txt.intermediate +0 -0
  88. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/ref/App1.dll +0 -0
  89. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/refint/App1.dll +0 -0
  90. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/resources.resfiles +0 -0
  91. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/resources.resfiles.intermediate +0 -0
  92. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/unfiltered.layout.resfiles +0 -11
  93. package/templates/windows/App1/App1/obj/x64/Debug/net8.0-windows10.0.19041.0/unfiltered.layout.resfiles.intermediate +0 -11
  94. package/templates/windows/App1.slnx +0 -15
@@ -1,5 +1,7 @@
1
1
  import path from "path";
2
2
  import fsSync, { existsSync } from "fs";
3
+ //@ts-ignore
4
+ import pkg from "../../package.json" assert { type: "json" };
3
5
  import fs from "fs/promises";
4
6
  import os from "os";
5
7
  import { spawn, execSync } from "child_process";
@@ -7,7 +9,7 @@ import { ensureAndroidInstalled, findAndroidSdk } from "./sdk.js";
7
9
  import { logger } from "../logger.js";
8
10
  import { loadConfig } from "../../main.js";
9
11
  import { Config } from "../../config/index.js";
10
-
12
+ import { fetchBinary } from "../binaries/fetch.js";
11
13
  const PROJECT_ROOT = process.cwd();
12
14
  const DIST_DIR = path.join(PROJECT_ROOT, "dist");
13
15
 
@@ -263,7 +265,7 @@ export async function addDeepLinks(buildDir: string) {
263
265
  export async function buildAndroid(isDev = false) {
264
266
  const config: Config = await loadConfig(process.cwd());
265
267
  const APP_ID = config.app?.id || "com.vaderjs.app";
266
- const BUILD_SRC = path.join(process.cwd(), "node_modules", "vaderjs-native", "templates", "android");
268
+ const BUILD_SRC = await fetchBinary("android", pkg.version);
267
269
  const BUILD_DIR = path.join(process.cwd(), "build", "android-src", APP_ID);
268
270
 
269
271
  logger.step("🚀 Android Build");
@@ -0,0 +1,56 @@
1
+ import path from "path";
2
+ import os from "os";
3
+ import fs from "fs";
4
+ import fsPromises from "fs/promises";
5
+ import https from "https";
6
+ import extract from "extract-zip";
7
+ import { logger } from "../logger.js";
8
+
9
+ const CACHE_ROOT = path.join(os.homedir(), ".vaderjs", "binaries");
10
+
11
+ async function download(url: string, dest: string) {
12
+ return new Promise<void>((resolve, reject) => {
13
+ https.get(url, res => {
14
+ if (res.statusCode !== 200) {
15
+ reject(new Error(`Download failed (${res.statusCode}) → ${url}`));
16
+ return;
17
+ }
18
+
19
+ const file = fs.createWriteStream(dest);
20
+ res.pipe(file);
21
+ file.on("finish", () => file.close(resolve));
22
+ file.on("error", reject);
23
+ }).on("error", reject);
24
+ });
25
+ }
26
+
27
+ export async function fetchBinary(
28
+ platform: "android" | "windows" | "linux",
29
+ version: string
30
+ ): Promise<string> {
31
+ const platformDir = path.join(CACHE_ROOT, version, platform);
32
+ const marker = path.join(platformDir, ".ready");
33
+
34
+ if (fs.existsSync(marker)) {
35
+ logger.info(`📦 Using cached ${platform} binaries (${version})`);
36
+ return platformDir;
37
+ }
38
+
39
+ logger.info(`⬇️ Downloading ${platform} binaries v${version}`);
40
+
41
+ await fsPromises.mkdir(platformDir, { recursive: true });
42
+
43
+ const zipPath = path.join(platformDir, `${platform}.zip`);
44
+ const url = `https://github.com/Postr-Inc/Vaderjs-Native-Binaries/releases/download/${version}/${platform}.zip`;
45
+
46
+ await download(url, zipPath);
47
+
48
+ logger.info(`📂 Extracting ${platform}.zip`);
49
+ await extract(zipPath, { dir: platformDir });
50
+
51
+ await fsPromises.unlink(zipPath);
52
+ await fsPromises.writeFile(marker, "ok");
53
+
54
+ logger.success(`✅ ${platform} binaries ready`);
55
+ return platformDir;
56
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vaderjs-native",
3
- "version": "1.0.23",
3
+ "version": "1.0.25",
4
4
  "description": "Build Native Applications using Vaderjs framework.",
5
5
  "bin": {
6
6
  "vaderjs": "./main.ts"
@@ -10,12 +10,8 @@
10
10
  "url": "https://github.com/Postr-Inc/Vaderjs-Native"
11
11
  },
12
12
  "license": "MIT",
13
- "dependencies": {
14
- "@tailwindcss/postcss": "^4.1.18",
15
- "ansi-colors": "^4.1.3",
16
- "autoprefixer": "^10.4.23",
17
- "postcss-cli": "^11.0.1",
18
- "tailwindcss": "^4.1.18",
19
- "vaderjs-types": "^1.0.0"
20
- }
13
+ "dependencies": {
14
+ "vaderjs-types": "latest",
15
+ "extract-zip":"latest"
16
+ }
21
17
  }
File without changes
@@ -1,2 +0,0 @@
1
- #Tue Jan 27 07:50:43 PST 2026
2
- gradle.version=9.1.0
File without changes
@@ -1,54 +0,0 @@
1
- plugins {
2
- alias(libs.plugins.android.application)
3
- alias(libs.plugins.kotlin.compose)
4
- }
5
-
6
- android {
7
- namespace = "{{APP_PACKAGE}}"
8
- compileSdk {
9
- version = release(36)
10
- }
11
-
12
- defaultConfig {
13
- applicationId = "{{APP_PACKAGE}}"
14
- minSdk = 21
15
- targetSdk = 36
16
- versionCode = 1
17
- versionName = "1.0"
18
-
19
- }
20
-
21
- buildTypes {
22
- release {
23
- isMinifyEnabled = false
24
- proguardFiles(
25
- getDefaultProguardFile("proguard-android-optimize.txt"),
26
- "proguard-rules.pro"
27
- )
28
- }
29
- }
30
- compileOptions {
31
- sourceCompatibility = JavaVersion.VERSION_11
32
- targetCompatibility = JavaVersion.VERSION_11
33
- }
34
- buildFeatures {
35
- compose = true
36
- }
37
- }
38
-
39
- dependencies {
40
- implementation(libs.androidx.core.ktx)
41
- implementation(libs.androidx.appcompat)
42
- implementation(platform(libs.androidx.compose.bom))
43
- implementation(libs.androidx.compose.ui)
44
- implementation(libs.androidx.compose.ui.graphics)
45
- implementation(libs.androidx.compose.ui.tooling.preview)
46
- implementation(libs.androidx.tv.foundation)
47
- implementation(libs.androidx.tv.material)
48
- implementation(libs.androidx.lifecycle.runtime.ktx)
49
- implementation(libs.androidx.activity.compose)
50
- androidTestImplementation(platform(libs.androidx.compose.bom))
51
- androidTestImplementation(libs.androidx.compose.ui.test.junit4)
52
- debugImplementation(libs.androidx.compose.ui.tooling)
53
- debugImplementation(libs.androidx.compose.ui.test.manifest)
54
- }
@@ -1,21 +0,0 @@
1
- # Add project specific ProGuard rules here.
2
- # You can control the set of applied configuration files using the
3
- # proguardFiles setting in build.gradle.
4
- #
5
- # For more details, see
6
- # http://developer.android.com/guide/developing/tools/proguard.html
7
-
8
- # If your project uses WebView with JS, uncomment the following
9
- # and specify the fully qualified class name to the JavaScript interface
10
- # class:
11
- #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12
- # public *;
13
- #}
14
-
15
- # Uncomment this to preserve the line number information for
16
- # debugging stack traces.
17
- #-keepattributes SourceFile,LineNumberTable
18
-
19
- # If you keep the line number information, uncomment this to
20
- # hide the original source file name.
21
- #-renamesourcefileattribute SourceFile
@@ -1,33 +0,0 @@
1
- <?xml version="1.0" encoding="utf-8"?>
2
- <manifest xmlns:android="http://schemas.android.com/apk/res/android"
3
- xmlns:tools="http://schemas.android.com/tools">
4
-
5
- <!-- Permissions will be added by patchPermissions -->
6
-
7
- <uses-feature
8
- android:name="android.hardware.touchscreen"
9
- android:required="false" />
10
- <uses-feature
11
- android:name="android.software.leanback"
12
- android:required="false" />
13
-
14
- <application
15
- android:allowBackup="true"
16
- android:banner="@mipmap/ic_launcher"
17
- android:icon="@mipmap/ic_launcher"
18
- android:usesCleartextTraffic="true"
19
- android:label="@string/app_name"
20
- android:supportsRtl="true"
21
- android:theme="@style/Theme.MyApplication">
22
- <activity
23
- android:name=".MainActivity"
24
- android:exported="true">
25
- <intent-filter>
26
- <action android:name="android.intent.action.MAIN" />
27
- <category android:name="android.intent.category.LAUNCHER" />
28
- <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
29
- </intent-filter>
30
- </activity>
31
- </application>
32
-
33
- </manifest>
@@ -1,199 +0,0 @@
1
- import android.app.AlertDialog
2
- import android.content.Context
3
- import android.content.pm.PackageManager
4
- import android.net.Uri
5
- import android.webkit.JavascriptInterface
6
- import android.webkit.WebView
7
- import android.widget.Toast
8
- import androidx.activity.ComponentActivity
9
- import androidx.core.app.ActivityCompat
10
- import androidx.core.content.ContextCompat
11
- import org.json.JSONArray
12
- import java.io.File
13
- import java.io.FileNotFoundException
14
- import java.net.HttpURLConnection
15
- import java.net.URL
16
-
17
- class AndroidBridge(
18
- private val activity: ComponentActivity,
19
- private val webView: WebView,
20
- private val baseUrl: String
21
- ) {
22
-
23
- private val PERMISSION_REQUEST_CODE = 9001
24
-
25
- // ---- Toast ----
26
- @JavascriptInterface
27
- fun showToast(message: String) {
28
- activity.runOnUiThread {
29
- Toast.makeText(activity, message, Toast.LENGTH_SHORT).show()
30
- }
31
- }
32
-
33
- // ---- File System Methods ----
34
- @JavascriptInterface
35
- fun writeFile(path: String, content: String): Boolean {
36
- return try {
37
- activity.openFileOutput(path, Context.MODE_PRIVATE).use {
38
- it.write(content.toByteArray())
39
- }
40
- true
41
- } catch (e: Exception) {
42
- e.printStackTrace()
43
- false
44
- }
45
- }
46
-
47
- @JavascriptInterface
48
- fun readFile(path: String): String {
49
- return try {
50
- activity.openFileInput(path).bufferedReader().use { it.readText() }
51
- } catch (e: FileNotFoundException) {
52
- "{\"error\":\"File not found\"}"
53
- } catch (e: Exception) {
54
- e.printStackTrace()
55
- "{\"error\":\"${e.message}\"}"
56
- }
57
- }
58
-
59
- @JavascriptInterface
60
- fun deleteFile(path: String): Boolean {
61
- return try {
62
- activity.deleteFile(path)
63
- } catch (e: Exception) {
64
- e.printStackTrace()
65
- false
66
- }
67
- }
68
-
69
- @JavascriptInterface
70
- fun listFiles(): String {
71
- return try {
72
- val files = activity.fileList()
73
- JSONArray(files.toList()).toString()
74
- } catch (e: Exception) {
75
- e.printStackTrace()
76
- "[]"
77
- }
78
- }
79
-
80
- // ---- Permissions ----
81
- @JavascriptInterface
82
- fun hasPermission(name: String): Boolean {
83
- val permissions = mapPermission(name)
84
- return permissions.all {
85
- ContextCompat.checkSelfPermission(activity, it) ==
86
- PackageManager.PERMISSION_GRANTED
87
- }
88
- }
89
-
90
- @JavascriptInterface
91
- fun requestPermission(name: String) {
92
- val permissions = mapPermission(name)
93
-
94
- if (permissions.isEmpty()) {
95
- sendPermissionResult(true)
96
- return
97
- }
98
-
99
- val granted = permissions.all {
100
- ContextCompat.checkSelfPermission(activity, it) ==
101
- PackageManager.PERMISSION_GRANTED
102
- }
103
-
104
- if (granted) {
105
- sendPermissionResult(true)
106
- return
107
- }
108
-
109
- ActivityCompat.requestPermissions(
110
- activity,
111
- permissions,
112
- PERMISSION_REQUEST_CODE
113
- )
114
- }
115
-
116
- fun onPermissionResult(requestCode: Int, grantResults: IntArray) {
117
- if (requestCode != PERMISSION_REQUEST_CODE) return
118
- val granted = grantResults.all { it == PackageManager.PERMISSION_GRANTED }
119
- sendPermissionResult(granted)
120
- }
121
-
122
- private fun sendPermissionResult(granted: Boolean) {
123
- webView.post {
124
- webView.evaluateJavascript(
125
- "window.onNativePermissionResult && window.onNativePermissionResult($granted)",
126
- null
127
- )
128
- }
129
- }
130
-
131
- // ---- Dialog ----
132
- @JavascriptInterface
133
- fun showDialog(
134
- title: String,
135
- message: String,
136
- okText: String = "OK",
137
- cancelText: String = "Cancel"
138
- ) {
139
- activity.runOnUiThread {
140
- AlertDialog.Builder(activity)
141
- .setTitle(title)
142
- .setMessage(message)
143
- .setPositiveButton(okText) { _, _ ->
144
- webView.evaluateJavascript(
145
- "window.onNativeDialogResult && window.onNativeDialogResult(true)",
146
- null
147
- )
148
- }
149
- .setNegativeButton(cancelText) { _, _ ->
150
- webView.evaluateJavascript(
151
- "window.onNativeDialogResult && window.onNativeDialogResult(false)",
152
- null
153
- )
154
- }
155
- .setCancelable(false)
156
- .show()
157
- }
158
- }
159
-
160
- // ---- Native fetch ----
161
- @JavascriptInterface
162
- fun nativeFetch(url: String, method: String): String {
163
- return try {
164
- val connection = URL(url).openConnection() as HttpURLConnection
165
- connection.requestMethod = method
166
- connection.connectTimeout = 5000
167
- connection.readTimeout = 5000
168
- val response = connection.inputStream.bufferedReader().use { it.readText() }
169
- connection.disconnect()
170
- response
171
- } catch (e: Exception) {
172
- "{\"error\":\"${e.message}\"}"
173
- }
174
- }
175
-
176
- // ---- Navigation ----
177
- @JavascriptInterface
178
- fun navigate(path: String?) {
179
- val clean = path?.trimStart('/') ?: ""
180
- webView.post {
181
- val finalUrl = "$baseUrl$clean/index.html".replace("//index", "/index")
182
- webView.loadUrl(finalUrl)
183
- }
184
- }
185
-
186
- // ---- Permission map ----
187
- private fun mapPermission(name: String): Array<String> {
188
- return when (name) {
189
- "storage" -> arrayOf(
190
- android.Manifest.permission.READ_EXTERNAL_STORAGE,
191
- android.Manifest.permission.WRITE_EXTERNAL_STORAGE
192
- )
193
- "camera" -> arrayOf(android.Manifest.permission.CAMERA)
194
- "microphone" -> arrayOf(android.Manifest.permission.RECORD_AUDIO)
195
- "notifications" -> arrayOf(android.Manifest.permission.POST_NOTIFICATIONS)
196
- else -> emptyArray()
197
- }
198
- }
199
- }
@@ -1,133 +0,0 @@
1
- package com.mycompany.app
2
-
3
- import android.annotation.SuppressLint
4
- import android.os.Bundle
5
- import android.os.Message
6
- import android.view.KeyEvent
7
- import android.webkit.WebChromeClient
8
- import android.webkit.WebView
9
- import android.webkit.WebViewClient
10
- import android.widget.Toast
11
- import androidx.activity.ComponentActivity
12
- import androidx.activity.OnBackPressedCallback
13
-
14
- class MainActivity : ComponentActivity() {
15
-
16
- lateinit var webView: WebView
17
- lateinit var androidBridge: AndroidBridge
18
-
19
- private val baseUrl = "file:///android_asset/com.mycompany.app/"
20
-
21
- @SuppressLint("SetJavaScriptEnabled", "AddJavascriptInterface")
22
- override fun onCreate(savedInstanceState: Bundle?) {
23
- super.onCreate(savedInstanceState)
24
-
25
- webView = WebView(this)
26
- setContentView(webView)
27
-
28
- webView.settings.apply {
29
- javaScriptEnabled = true
30
- allowFileAccess = true
31
- allowContentAccess = true
32
- allowFileAccessFromFileURLs = true
33
- allowUniversalAccessFromFileURLs = true
34
- domStorageEnabled = true
35
- databaseEnabled = true
36
- mediaPlaybackRequiresUserGesture = false
37
-
38
- setSupportMultipleWindows(false)
39
- loadWithOverviewMode = true
40
- useWideViewPort = true
41
- builtInZoomControls = true
42
- displayZoomControls = false
43
- setSupportZoom(true)
44
-
45
- javaScriptCanOpenWindowsAutomatically = false
46
- loadsImagesAutomatically = true
47
- }
48
-
49
- webView.isFocusable = true
50
- webView.isFocusableInTouchMode = true
51
- webView.requestFocus()
52
-
53
- androidBridge = AndroidBridge(this, webView, baseUrl)
54
- webView.addJavascriptInterface(androidBridge, "Android")
55
-
56
- webView.webViewClient = object : WebViewClient() {
57
- override fun shouldOverrideUrlLoading(view: WebView?, url: String?): Boolean {
58
- return if (url != null && url.startsWith(baseUrl)) {
59
- false
60
- } else {
61
- Toast.makeText(
62
- this@MainActivity,
63
- "Blocked external navigation",
64
- Toast.LENGTH_SHORT
65
- ).show()
66
- true
67
- }
68
- }
69
-
70
- override fun onPageFinished(view: WebView?, url: String?) {
71
- view?.evaluateJavascript(
72
- "console.log('Android bridge ready:', !!window.Android)",
73
- null
74
- )
75
- }
76
- }
77
-
78
- webView.webChromeClient = object : WebChromeClient() {
79
- override fun onCreateWindow(
80
- view: WebView?,
81
- isDialog: Boolean,
82
- isUserGesture: Boolean,
83
- resultMsg: Message?
84
- ): Boolean = false
85
- }
86
-
87
- onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
88
- override fun handleOnBackPressed() {
89
- webView.evaluateJavascript(
90
- "window.onNativeKey && window.onNativeKey(4)",
91
- null
92
- )
93
- }
94
- })
95
-
96
- webView.loadUrl(baseUrl)
97
- }
98
-
99
- override fun onRequestPermissionsResult(
100
- requestCode: Int,
101
- permissions: Array<out String>,
102
- grantResults: IntArray
103
- ) {
104
- super.onRequestPermissionsResult(requestCode, permissions, grantResults)
105
- androidBridge.onPermissionResult(requestCode, grantResults)
106
- }
107
-
108
- @SuppressLint("RestrictedApi")
109
- override fun dispatchKeyEvent(event: KeyEvent): Boolean {
110
- if (event.action == KeyEvent.ACTION_DOWN) {
111
- val handled = when (event.keyCode) {
112
- KeyEvent.KEYCODE_DPAD_UP,
113
- KeyEvent.KEYCODE_DPAD_DOWN,
114
- KeyEvent.KEYCODE_DPAD_LEFT,
115
- KeyEvent.KEYCODE_DPAD_RIGHT,
116
- KeyEvent.KEYCODE_DPAD_CENTER,
117
- KeyEvent.KEYCODE_BACK,
118
- KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE -> {
119
- webView.post {
120
- webView.evaluateJavascript(
121
- "window.onNativeKey && window.onNativeKey(${event.keyCode})",
122
- null
123
- )
124
- }
125
- true
126
- }
127
- else -> false
128
- }
129
- if (handled) return true
130
- }
131
- return super.dispatchKeyEvent(event)
132
- }
133
- }
@@ -1,3 +0,0 @@
1
- <resources>
2
- <string name="app_name">My Application</string>
3
- </resources>
@@ -1,4 +0,0 @@
1
- <resources>
2
-
3
- <style name="Theme.MyApplication" parent="Theme.AppCompat.DayNight.NoActionBar" />
4
- </resources>
@@ -1,5 +0,0 @@
1
- // Top-level build file where you can add configuration options common to all sub-projects/modules.
2
- plugins {
3
- alias(libs.plugins.android.application) apply false
4
- alias(libs.plugins.kotlin.compose) apply false
5
- }
@@ -1,30 +0,0 @@
1
- [versions]
2
- agp = "9.0.0"
3
- coreKtx = "1.10.1"
4
- appcompat = "1.6.1"
5
- kotlin = "2.0.21"
6
- composeBom = "2024.09.00"
7
- tvFoundation = "1.0.0-alpha07"
8
- tvMaterial = "1.0.0-alpha07"
9
- lifecycleRuntimeKtx = "2.6.1"
10
- activityCompose = "1.8.0"
11
-
12
- [libraries]
13
- androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
14
- androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
15
- androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
16
- androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" }
17
- androidx-compose-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
18
- androidx-compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
19
- androidx-compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
20
- androidx-compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
21
- androidx-compose-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
22
- androidx-tv-foundation = { group = "androidx.tv", name = "tv-foundation", version.ref = "tvFoundation" }
23
- androidx-tv-material = { group = "androidx.tv", name = "tv-material", version.ref = "tvMaterial" }
24
- androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
25
- androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
26
-
27
- [plugins]
28
- android-application = { id = "com.android.application", version.ref = "agp" }
29
- kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
30
-
@@ -1,9 +0,0 @@
1
- #Tue Jan 20 13:18:12 PST 2026
2
- distributionBase=GRADLE_USER_HOME
3
- distributionPath=wrapper/dists
4
- distributionSha256Sum=a17ddd85a26b6a7f5ddb71ff8b05fc5104c0202c6e64782429790c933686c806
5
- distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip
6
- networkTimeout=10000
7
- validateDistributionUrl=true
8
- zipStoreBase=GRADLE_USER_HOME
9
- zipStorePath=wrapper/dists
@@ -1,23 +0,0 @@
1
- # Project-wide Gradle settings.
2
- # IDE (e.g. Android Studio) users:
3
- # Gradle settings configured through the IDE *will override*
4
- # any settings specified in this file.
5
- # For more details on how to configure your build environment visit
6
- # http://www.gradle.org/docs/current/userguide/build_environment.html
7
- # Specifies the JVM arguments used for the daemon process.
8
- # The setting is particularly useful for tweaking memory settings.
9
- org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10
- # When configured, Gradle will run in incubating parallel mode.
11
- # This option should only be used with decoupled projects. For more details, visit
12
- # https://developer.android.com/r/tools/gradle-multi-project-decoupled-projects
13
- # org.gradle.parallel=true
14
- # AndroidX package structure to make it clearer which packages are bundled with the
15
- # Android operating system, and which are packaged with your app's APK
16
- # https://developer.android.com/topic/libraries/support-library/androidx-rn
17
- android.useAndroidX=true
18
- # Kotlin code style for this project: "official" or "obsolete":
19
- kotlin.code.style=official
20
- # Enables namespacing of each library's R class so that its R class includes only the
21
- # resources declared in the library itself and none from the library's dependencies,
22
- # thereby reducing the size of the R class for that library
23
- android.nonTransitiveRClass=true