@table-js/platform 0.0.3 → 0.0.5
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.
- package/README.md +5 -1
- package/dist/cli.mjs +324 -103
- package/dist/index.d.mts +24 -11
- package/dist/index.d.ts +24 -11
- package/dist/index.js +322 -102
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +322 -102
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
1
|
type Platform = 'tizen' | 'webos' | 'android' | 'all';
|
|
2
|
+
type Target = Exclude<Platform, 'all'>;
|
|
3
|
+
type Mode = 'webview' | 'native';
|
|
2
4
|
interface BuildOptions {
|
|
3
|
-
platform:
|
|
5
|
+
platform: Target;
|
|
4
6
|
outDir: string;
|
|
7
|
+
dir: string;
|
|
5
8
|
minify: boolean;
|
|
9
|
+
mode: Mode;
|
|
6
10
|
sourcemap: boolean;
|
|
7
11
|
}
|
|
8
12
|
interface PlatformAdapter {
|
|
9
13
|
name: string;
|
|
10
14
|
build(options: BuildOptions): Promise<void>;
|
|
11
|
-
package(
|
|
15
|
+
package(options: BuildOptions): Promise<string>;
|
|
12
16
|
}
|
|
13
17
|
interface ManifestBase {
|
|
14
18
|
id: string;
|
|
@@ -23,7 +27,7 @@ declare function build(platform: Platform, options?: Partial<BuildOptions>): Pro
|
|
|
23
27
|
declare class TizenAdapter implements PlatformAdapter {
|
|
24
28
|
name: string;
|
|
25
29
|
build(options: BuildOptions): Promise<void>;
|
|
26
|
-
package(
|
|
30
|
+
package(options: BuildOptions): Promise<string>;
|
|
27
31
|
private createConfig;
|
|
28
32
|
private readPackageJson;
|
|
29
33
|
}
|
|
@@ -31,7 +35,7 @@ declare class TizenAdapter implements PlatformAdapter {
|
|
|
31
35
|
declare class WebOSAdapter implements PlatformAdapter {
|
|
32
36
|
name: string;
|
|
33
37
|
build(options: BuildOptions): Promise<void>;
|
|
34
|
-
package(
|
|
38
|
+
package(options: BuildOptions): Promise<string>;
|
|
35
39
|
private createAppInfo;
|
|
36
40
|
private readPackageJson;
|
|
37
41
|
}
|
|
@@ -39,12 +43,21 @@ declare class WebOSAdapter implements PlatformAdapter {
|
|
|
39
43
|
declare class AndroidAdapter implements PlatformAdapter {
|
|
40
44
|
name: string;
|
|
41
45
|
build(options: BuildOptions): Promise<void>;
|
|
42
|
-
package(
|
|
43
|
-
private
|
|
44
|
-
private
|
|
45
|
-
private
|
|
46
|
-
private
|
|
47
|
-
private
|
|
46
|
+
package(options: BuildOptions): Promise<string>;
|
|
47
|
+
private web;
|
|
48
|
+
private native;
|
|
49
|
+
private root;
|
|
50
|
+
private man;
|
|
51
|
+
private app;
|
|
52
|
+
private res;
|
|
53
|
+
private webKt;
|
|
54
|
+
private nativeKt;
|
|
55
|
+
private cmd;
|
|
56
|
+
private has;
|
|
57
|
+
private apk;
|
|
58
|
+
private safe;
|
|
59
|
+
private pkg;
|
|
60
|
+
private id;
|
|
48
61
|
}
|
|
49
62
|
|
|
50
|
-
export { AndroidAdapter, type BuildOptions, type ManifestBase, type Platform, type PlatformAdapter, TizenAdapter, WebOSAdapter, build };
|
|
63
|
+
export { AndroidAdapter, type BuildOptions, type ManifestBase, type Mode, type Platform, type PlatformAdapter, type Target, TizenAdapter, WebOSAdapter, build };
|
package/dist/index.js
CHANGED
|
@@ -38,6 +38,7 @@ __export(index_exports, {
|
|
|
38
38
|
module.exports = __toCommonJS(index_exports);
|
|
39
39
|
|
|
40
40
|
// src/builder.ts
|
|
41
|
+
var import_fs_extra4 = __toESM(require("fs-extra"));
|
|
41
42
|
var import_vite = require("vite");
|
|
42
43
|
|
|
43
44
|
// src/adapters/tizen.ts
|
|
@@ -48,18 +49,17 @@ var import_fs = require("fs");
|
|
|
48
49
|
var TizenAdapter = class {
|
|
49
50
|
name = "Tizen (Samsung)";
|
|
50
51
|
async build(options) {
|
|
51
|
-
|
|
52
|
-
await this.createConfig(distDir);
|
|
52
|
+
await this.createConfig(options.dir);
|
|
53
53
|
}
|
|
54
|
-
async package(
|
|
55
|
-
const outputPath = import_path.default.join(
|
|
54
|
+
async package(options) {
|
|
55
|
+
const outputPath = import_path.default.join(options.dir, "..", "app.wgt");
|
|
56
56
|
await new Promise((resolve, reject) => {
|
|
57
57
|
const output = (0, import_fs.createWriteStream)(outputPath);
|
|
58
58
|
const archive = (0, import_archiver.default)("zip", { zlib: { level: 9 } });
|
|
59
59
|
output.on("close", () => resolve());
|
|
60
60
|
archive.on("error", reject);
|
|
61
61
|
archive.pipe(output);
|
|
62
|
-
archive.directory(
|
|
62
|
+
archive.directory(options.dir, false);
|
|
63
63
|
archive.finalize();
|
|
64
64
|
});
|
|
65
65
|
return outputPath;
|
|
@@ -115,18 +115,17 @@ var import_fs2 = require("fs");
|
|
|
115
115
|
var WebOSAdapter = class {
|
|
116
116
|
name = "webOS (LG)";
|
|
117
117
|
async build(options) {
|
|
118
|
-
|
|
119
|
-
await this.createAppInfo(distDir);
|
|
118
|
+
await this.createAppInfo(options.dir);
|
|
120
119
|
}
|
|
121
|
-
async package(
|
|
122
|
-
const outputPath = import_path2.default.join(
|
|
120
|
+
async package(options) {
|
|
121
|
+
const outputPath = import_path2.default.join(options.dir, "..", "app.ipk");
|
|
123
122
|
await new Promise((resolve, reject) => {
|
|
124
123
|
const output = (0, import_fs2.createWriteStream)(outputPath);
|
|
125
124
|
const archive = (0, import_archiver2.default)("tar", { gzip: true });
|
|
126
125
|
output.on("close", () => resolve());
|
|
127
126
|
archive.on("error", reject);
|
|
128
127
|
archive.pipe(output);
|
|
129
|
-
archive.directory(
|
|
128
|
+
archive.directory(options.dir, false);
|
|
130
129
|
archive.finalize();
|
|
131
130
|
});
|
|
132
131
|
return outputPath;
|
|
@@ -174,49 +173,106 @@ var import_execa = require("execa");
|
|
|
174
173
|
var AndroidAdapter = class {
|
|
175
174
|
name = "Android TV";
|
|
176
175
|
async build(options) {
|
|
177
|
-
|
|
178
|
-
|
|
176
|
+
if (options.mode === "native") {
|
|
177
|
+
await this.native(options.dir);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
await this.web(options.dir);
|
|
179
181
|
}
|
|
180
|
-
async package(
|
|
181
|
-
const
|
|
182
|
+
async package(options) {
|
|
183
|
+
const proj = import_path3.default.join(options.dir, "project");
|
|
184
|
+
const cmd = await this.cmd(proj);
|
|
185
|
+
if (!cmd) {
|
|
186
|
+
return proj;
|
|
187
|
+
}
|
|
182
188
|
try {
|
|
183
|
-
await (0, import_execa.execa)(
|
|
184
|
-
cwd:
|
|
189
|
+
await (0, import_execa.execa)(cmd, ["assembleRelease"], {
|
|
190
|
+
cwd: proj,
|
|
185
191
|
stdio: "inherit"
|
|
186
192
|
});
|
|
187
|
-
const
|
|
188
|
-
const
|
|
189
|
-
await import_fs_extra3.default.copy(
|
|
190
|
-
return
|
|
191
|
-
} catch
|
|
192
|
-
throw new Error("Android build failed.
|
|
193
|
+
const apk = import_path3.default.join(proj, "app/build/outputs/apk/release/app-release.apk");
|
|
194
|
+
const out2 = import_path3.default.join(options.dir, "..", this.apk(options));
|
|
195
|
+
await import_fs_extra3.default.copy(apk, out2);
|
|
196
|
+
return out2;
|
|
197
|
+
} catch {
|
|
198
|
+
throw new Error("Android build failed. Install the Android SDK and Gradle, or add a Gradle wrapper.");
|
|
193
199
|
}
|
|
194
200
|
}
|
|
195
|
-
async
|
|
196
|
-
const pkg = await this.
|
|
197
|
-
const
|
|
198
|
-
await import_fs_extra3.default.
|
|
199
|
-
await
|
|
200
|
-
await this.
|
|
201
|
-
await this.
|
|
202
|
-
await this.
|
|
201
|
+
async web(dir2) {
|
|
202
|
+
const pkg = await this.pkg();
|
|
203
|
+
const proj = import_path3.default.join(dir2, "project");
|
|
204
|
+
await import_fs_extra3.default.remove(proj);
|
|
205
|
+
await this.root(proj, pkg);
|
|
206
|
+
await this.man(proj, pkg, true);
|
|
207
|
+
await this.app(proj, pkg, false);
|
|
208
|
+
await this.res(proj);
|
|
209
|
+
await this.webKt(proj, pkg);
|
|
210
|
+
await import_fs_extra3.default.copy(import_path3.default.join(dir2, "www"), import_path3.default.join(proj, "app/src/main/assets/www"));
|
|
211
|
+
}
|
|
212
|
+
async native(dir2) {
|
|
213
|
+
const pkg = await this.pkg();
|
|
214
|
+
const proj = import_path3.default.join(dir2, "project");
|
|
215
|
+
await import_fs_extra3.default.remove(proj);
|
|
216
|
+
await this.root(proj, pkg);
|
|
217
|
+
await this.man(proj, pkg, false);
|
|
218
|
+
await this.app(proj, pkg, true);
|
|
219
|
+
await this.res(proj);
|
|
220
|
+
await this.nativeKt(proj, pkg);
|
|
221
|
+
}
|
|
222
|
+
async root(proj, pkg) {
|
|
223
|
+
const settings = `pluginManagement {
|
|
224
|
+
repositories {
|
|
225
|
+
google()
|
|
226
|
+
mavenCentral()
|
|
227
|
+
gradlePluginPortal()
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
dependencyResolutionManagement {
|
|
232
|
+
repositoriesMode.set(org.gradle.api.initialization.resolve.RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
|
233
|
+
repositories {
|
|
234
|
+
google()
|
|
235
|
+
mavenCentral()
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
rootProject.name = "${this.safe(pkg.name)}"
|
|
240
|
+
include(":app")
|
|
241
|
+
`;
|
|
242
|
+
const build2 = `plugins {
|
|
243
|
+
id("com.android.application") version "9.1.0" apply false
|
|
244
|
+
id("org.jetbrains.kotlin.android") version "2.3.10" apply false
|
|
245
|
+
id("org.jetbrains.kotlin.plugin.compose") version "2.3.10" apply false
|
|
246
|
+
}
|
|
247
|
+
`;
|
|
248
|
+
const props = `org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
|
|
249
|
+
android.useAndroidX=true
|
|
250
|
+
kotlin.code.style=official
|
|
251
|
+
`;
|
|
252
|
+
await import_fs_extra3.default.ensureDir(proj);
|
|
253
|
+
await import_fs_extra3.default.ensureDir(import_path3.default.join(proj, "app"));
|
|
254
|
+
await import_fs_extra3.default.writeFile(import_path3.default.join(proj, "settings.gradle.kts"), settings);
|
|
255
|
+
await import_fs_extra3.default.writeFile(import_path3.default.join(proj, "build.gradle.kts"), build2);
|
|
256
|
+
await import_fs_extra3.default.writeFile(import_path3.default.join(proj, "gradle.properties"), props);
|
|
257
|
+
await import_fs_extra3.default.writeFile(import_path3.default.join(proj, "app/proguard-rules.pro"), "");
|
|
203
258
|
}
|
|
204
|
-
async
|
|
259
|
+
async man(proj, pkg, web2) {
|
|
260
|
+
const net = web2 ? '<uses-permission android:name="android.permission.INTERNET" />\n' : "";
|
|
261
|
+
const clear = web2 ? ' android:usesCleartextTraffic="true"\n' : "";
|
|
205
262
|
const manifest = `<?xml version="1.0" encoding="utf-8"?>
|
|
206
263
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
207
264
|
package="${pkg.id || "com.example.app"}">
|
|
208
265
|
|
|
209
|
-
<uses-
|
|
210
|
-
<uses-feature android:name="android.software.leanback" android:required="true" />
|
|
266
|
+
${net} <uses-feature android:name="android.software.leanback" android:required="true" />
|
|
211
267
|
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
|
|
212
268
|
|
|
213
269
|
<application
|
|
214
270
|
android:allowBackup="true"
|
|
215
|
-
android:icon="@mipmap/ic_launcher"
|
|
216
|
-
android:label="${pkg.name}"
|
|
217
271
|
android:banner="@drawable/banner"
|
|
218
|
-
android:
|
|
219
|
-
|
|
272
|
+
android:icon="@android:drawable/sym_def_app_icon"
|
|
273
|
+
android:label="${pkg.name}"
|
|
274
|
+
${clear} android:theme="@android:style/Theme.DeviceDefault.NoActionBar">
|
|
275
|
+
|
|
220
276
|
<activity
|
|
221
277
|
android:name=".MainActivity"
|
|
222
278
|
android:exported="true"
|
|
@@ -228,79 +284,215 @@ var AndroidAdapter = class {
|
|
|
228
284
|
</activity>
|
|
229
285
|
</application>
|
|
230
286
|
</manifest>`;
|
|
231
|
-
const
|
|
232
|
-
await import_fs_extra3.default.ensureDir(import_path3.default.dirname(
|
|
233
|
-
await import_fs_extra3.default.writeFile(
|
|
287
|
+
const file = import_path3.default.join(proj, "app/src/main/AndroidManifest.xml");
|
|
288
|
+
await import_fs_extra3.default.ensureDir(import_path3.default.dirname(file));
|
|
289
|
+
await import_fs_extra3.default.writeFile(file, manifest);
|
|
234
290
|
}
|
|
235
|
-
async
|
|
236
|
-
const
|
|
237
|
-
id
|
|
238
|
-
|
|
291
|
+
async app(proj, pkg, native) {
|
|
292
|
+
const plugins = native ? `plugins {
|
|
293
|
+
id("com.android.application")
|
|
294
|
+
id("org.jetbrains.kotlin.android")
|
|
295
|
+
id("org.jetbrains.kotlin.plugin.compose")
|
|
296
|
+
}` : `plugins {
|
|
297
|
+
id("com.android.application")
|
|
298
|
+
id("org.jetbrains.kotlin.android")
|
|
299
|
+
}`;
|
|
300
|
+
const flags = native ? `
|
|
301
|
+
buildFeatures {
|
|
302
|
+
compose = true
|
|
303
|
+
}` : "";
|
|
304
|
+
const deps = native ? `dependencies {
|
|
305
|
+
val bom = platform("androidx.compose:compose-bom:2026.02.01")
|
|
239
306
|
|
|
307
|
+
implementation(bom)
|
|
308
|
+
androidTestImplementation(bom)
|
|
309
|
+
|
|
310
|
+
implementation("androidx.activity:activity-compose:1.12.4")
|
|
311
|
+
implementation("androidx.compose.foundation:foundation")
|
|
312
|
+
implementation("androidx.compose.ui:ui")
|
|
313
|
+
implementation("androidx.compose.ui:ui-tooling-preview")
|
|
314
|
+
implementation("androidx.tv:tv-material:1.0.0")
|
|
315
|
+
debugImplementation("androidx.compose.ui:ui-tooling")
|
|
316
|
+
}` : `dependencies {
|
|
317
|
+
implementation("androidx.leanback:leanback:1.0.0")
|
|
318
|
+
}`;
|
|
319
|
+
const build2 = `${plugins}
|
|
240
320
|
android {
|
|
241
|
-
namespace
|
|
242
|
-
compileSdk 34
|
|
321
|
+
namespace = "${pkg.id || "com.example.app"}"
|
|
322
|
+
compileSdk = 34
|
|
243
323
|
|
|
244
324
|
defaultConfig {
|
|
245
|
-
applicationId "${pkg.id || "com.example.app"}"
|
|
246
|
-
minSdk 21
|
|
247
|
-
targetSdk 34
|
|
248
|
-
versionCode 1
|
|
249
|
-
versionName "${pkg.version}"
|
|
325
|
+
applicationId = "${pkg.id || "com.example.app"}"
|
|
326
|
+
minSdk = 21
|
|
327
|
+
targetSdk = 34
|
|
328
|
+
versionCode = 1
|
|
329
|
+
versionName = "${pkg.version}"
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
compileOptions {
|
|
333
|
+
sourceCompatibility = JavaVersion.VERSION_17
|
|
334
|
+
targetCompatibility = JavaVersion.VERSION_17
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
kotlinOptions {
|
|
338
|
+
jvmTarget = "17"
|
|
250
339
|
}
|
|
340
|
+
${flags}
|
|
251
341
|
|
|
252
342
|
buildTypes {
|
|
253
343
|
release {
|
|
254
|
-
|
|
255
|
-
proguardFiles
|
|
344
|
+
isMinifyEnabled = true
|
|
345
|
+
proguardFiles(
|
|
346
|
+
getDefaultProguardFile("proguard-android-optimize.txt"),
|
|
347
|
+
"proguard-rules.pro",
|
|
348
|
+
)
|
|
256
349
|
}
|
|
257
350
|
}
|
|
258
351
|
}
|
|
259
352
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
await import_fs_extra3.default.writeFile(import_path3.default.join(projectDir, "app/build.gradle"), buildGradle);
|
|
353
|
+
${deps}
|
|
354
|
+
`;
|
|
355
|
+
await import_fs_extra3.default.writeFile(import_path3.default.join(proj, "app/build.gradle.kts"), build2);
|
|
264
356
|
}
|
|
265
|
-
async
|
|
266
|
-
const
|
|
267
|
-
|
|
357
|
+
async res(proj) {
|
|
358
|
+
const banner = `<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
|
359
|
+
<solid android:color="#10151E" />
|
|
360
|
+
<corners android:radius="18dp" />
|
|
361
|
+
</shape>
|
|
362
|
+
`;
|
|
363
|
+
const file = import_path3.default.join(proj, "app/src/main/res/drawable/banner.xml");
|
|
364
|
+
await import_fs_extra3.default.ensureDir(import_path3.default.dirname(file));
|
|
365
|
+
await import_fs_extra3.default.writeFile(file, banner);
|
|
366
|
+
}
|
|
367
|
+
async webKt(proj, pkg) {
|
|
368
|
+
const id = pkg.id || "com.example.app";
|
|
369
|
+
const main = `package ${id}
|
|
370
|
+
|
|
371
|
+
import android.app.Activity
|
|
372
|
+
import android.os.Bundle
|
|
373
|
+
import android.webkit.WebSettings
|
|
374
|
+
import android.webkit.WebView
|
|
375
|
+
|
|
376
|
+
class MainActivity : Activity() {
|
|
377
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
378
|
+
super.onCreate(savedInstanceState)
|
|
268
379
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
import android.webkit.WebView;
|
|
272
|
-
import android.webkit.WebSettings;
|
|
380
|
+
val web = WebView(this)
|
|
381
|
+
setContentView(web)
|
|
273
382
|
|
|
274
|
-
|
|
275
|
-
|
|
383
|
+
val set: WebSettings = web.settings
|
|
384
|
+
set.javaScriptEnabled = true
|
|
385
|
+
set.domStorageEnabled = true
|
|
386
|
+
set.allowFileAccess = true
|
|
276
387
|
|
|
277
|
-
|
|
278
|
-
protected void onCreate(Bundle savedInstanceState) {
|
|
279
|
-
super.onCreate(savedInstanceState);
|
|
280
|
-
|
|
281
|
-
webView = new WebView(this);
|
|
282
|
-
setContentView(webView);
|
|
283
|
-
|
|
284
|
-
WebSettings settings = webView.getSettings();
|
|
285
|
-
settings.setJavaScriptEnabled(true);
|
|
286
|
-
settings.setDomStorageEnabled(true);
|
|
287
|
-
settings.setAllowFileAccess(true);
|
|
288
|
-
|
|
289
|
-
webView.loadUrl("file:///android_asset/www/index.html");
|
|
388
|
+
web.loadUrl("file:///android_asset/www/index.html")
|
|
290
389
|
}
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
);
|
|
296
|
-
await import_fs_extra3.default.ensureDir(import_path3.default.dirname(activityPath));
|
|
297
|
-
await import_fs_extra3.default.writeFile(activityPath, activity);
|
|
390
|
+
}
|
|
391
|
+
`;
|
|
392
|
+
const file = import_path3.default.join(proj, `app/src/main/java/${id.replace(/\./g, "/")}/MainActivity.kt`);
|
|
393
|
+
await import_fs_extra3.default.ensureDir(import_path3.default.dirname(file));
|
|
394
|
+
await import_fs_extra3.default.writeFile(file, main);
|
|
298
395
|
}
|
|
299
|
-
async
|
|
396
|
+
async nativeKt(proj, pkg) {
|
|
397
|
+
const id = pkg.id || "com.example.app";
|
|
398
|
+
const main = `package ${id}
|
|
399
|
+
|
|
400
|
+
import android.os.Bundle
|
|
401
|
+
import androidx.activity.ComponentActivity
|
|
402
|
+
import androidx.activity.compose.setContent
|
|
403
|
+
import androidx.compose.foundation.background
|
|
404
|
+
import androidx.compose.foundation.layout.Arrangement
|
|
405
|
+
import androidx.compose.foundation.layout.Box
|
|
406
|
+
import androidx.compose.foundation.layout.Column
|
|
407
|
+
import androidx.compose.foundation.layout.fillMaxSize
|
|
408
|
+
import androidx.compose.foundation.layout.fillMaxWidth
|
|
409
|
+
import androidx.compose.foundation.layout.padding
|
|
410
|
+
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
411
|
+
import androidx.compose.ui.Alignment
|
|
412
|
+
import androidx.compose.ui.Modifier
|
|
413
|
+
import androidx.compose.ui.graphics.Color
|
|
414
|
+
import androidx.compose.ui.text.style.TextAlign
|
|
415
|
+
import androidx.compose.ui.unit.dp
|
|
416
|
+
import androidx.tv.material3.Button
|
|
417
|
+
import androidx.tv.material3.MaterialTheme
|
|
418
|
+
import androidx.tv.material3.Surface
|
|
419
|
+
import androidx.tv.material3.Text
|
|
420
|
+
|
|
421
|
+
class MainActivity : ComponentActivity() {
|
|
422
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
423
|
+
super.onCreate(savedInstanceState)
|
|
424
|
+
setContent {
|
|
425
|
+
MaterialTheme {
|
|
426
|
+
Surface(modifier = Modifier.fillMaxSize()) {
|
|
427
|
+
Box(
|
|
428
|
+
modifier = Modifier
|
|
429
|
+
.fillMaxSize()
|
|
430
|
+
.background(Color(0xFF05070A))
|
|
431
|
+
.padding(48.dp),
|
|
432
|
+
contentAlignment = Alignment.Center,
|
|
433
|
+
) {
|
|
434
|
+
Column(
|
|
435
|
+
modifier = Modifier
|
|
436
|
+
.fillMaxWidth()
|
|
437
|
+
.background(Color(0xFF10151E), RoundedCornerShape(28.dp))
|
|
438
|
+
.padding(32.dp),
|
|
439
|
+
horizontalAlignment = Alignment.CenterHorizontally,
|
|
440
|
+
verticalArrangement = Arrangement.spacedBy(20.dp),
|
|
441
|
+
) {
|
|
442
|
+
Text(
|
|
443
|
+
text = "${pkg.name}",
|
|
444
|
+
style = MaterialTheme.typography.displayMedium,
|
|
445
|
+
textAlign = TextAlign.Center,
|
|
446
|
+
)
|
|
447
|
+
Text(
|
|
448
|
+
text = "Android native mode uses Kotlin and Compose for TV instead of WebView.",
|
|
449
|
+
style = MaterialTheme.typography.bodyLarge,
|
|
450
|
+
textAlign = TextAlign.Center,
|
|
451
|
+
color = Color(0xFFD4D7DD),
|
|
452
|
+
)
|
|
453
|
+
Button(onClick = {}) {
|
|
454
|
+
Text("Ready")
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
`;
|
|
464
|
+
const file = import_path3.default.join(proj, `app/src/main/java/${id.replace(/\./g, "/")}/MainActivity.kt`);
|
|
465
|
+
await import_fs_extra3.default.ensureDir(import_path3.default.dirname(file));
|
|
466
|
+
await import_fs_extra3.default.writeFile(file, main);
|
|
467
|
+
}
|
|
468
|
+
async cmd(proj) {
|
|
469
|
+
if (await import_fs_extra3.default.pathExists(import_path3.default.join(proj, "gradlew"))) {
|
|
470
|
+
return "./gradlew";
|
|
471
|
+
}
|
|
472
|
+
if (await this.has("gradle")) {
|
|
473
|
+
return "gradle";
|
|
474
|
+
}
|
|
475
|
+
return null;
|
|
476
|
+
}
|
|
477
|
+
async has(cmd) {
|
|
478
|
+
try {
|
|
479
|
+
await (0, import_execa.execa)(cmd, ["--version"]);
|
|
480
|
+
return true;
|
|
481
|
+
} catch {
|
|
482
|
+
return false;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
apk(options) {
|
|
486
|
+
return options.mode === "native" ? "app-native.apk" : "app.apk";
|
|
487
|
+
}
|
|
488
|
+
safe(name) {
|
|
489
|
+
return name.replace(/[^a-z0-9._-]/gi, "-");
|
|
490
|
+
}
|
|
491
|
+
async pkg() {
|
|
300
492
|
try {
|
|
301
493
|
const pkg = await import_fs_extra3.default.readJson("package.json");
|
|
302
494
|
return {
|
|
303
|
-
id: pkg.androidAppId || pkg.name
|
|
495
|
+
id: pkg.androidAppId || this.id(pkg.name),
|
|
304
496
|
name: pkg.name,
|
|
305
497
|
version: pkg.version,
|
|
306
498
|
description: pkg.description
|
|
@@ -313,13 +505,17 @@ public class MainActivity extends Activity {
|
|
|
313
505
|
};
|
|
314
506
|
}
|
|
315
507
|
}
|
|
508
|
+
id(name) {
|
|
509
|
+
const slug = name.toLowerCase().replace(/[^a-z0-9]+/g, ".").replace(/^\.+|\.+$/g, "").replace(/\.\.+/g, ".");
|
|
510
|
+
return `com.tablejs.${slug || "app"}`;
|
|
511
|
+
}
|
|
316
512
|
};
|
|
317
513
|
|
|
318
514
|
// src/builder.ts
|
|
319
515
|
async function build(platform, options = {}) {
|
|
320
516
|
const opts = {
|
|
321
|
-
platform,
|
|
322
517
|
outDir: options.outDir || "dist",
|
|
518
|
+
mode: options.mode || "webview",
|
|
323
519
|
minify: options.minify ?? true,
|
|
324
520
|
sourcemap: options.sourcemap ?? false
|
|
325
521
|
};
|
|
@@ -333,21 +529,30 @@ async function build(platform, options = {}) {
|
|
|
333
529
|
}
|
|
334
530
|
await buildPlatform(platform, opts);
|
|
335
531
|
}
|
|
336
|
-
async function buildPlatform(platform,
|
|
532
|
+
async function buildPlatform(platform, base) {
|
|
533
|
+
const options = {
|
|
534
|
+
...base,
|
|
535
|
+
dir: out(base.outDir, platform, base.mode),
|
|
536
|
+
platform
|
|
537
|
+
};
|
|
337
538
|
const adapter = getAdapter(platform);
|
|
338
|
-
|
|
339
|
-
build
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
539
|
+
if (web(platform, options.mode)) {
|
|
540
|
+
await (0, import_vite.build)({
|
|
541
|
+
build: {
|
|
542
|
+
outDir: dir(options),
|
|
543
|
+
minify: options.minify,
|
|
544
|
+
sourcemap: options.sourcemap,
|
|
545
|
+
emptyOutDir: true
|
|
546
|
+
},
|
|
547
|
+
define: {
|
|
548
|
+
__TABLE_PLATFORM__: JSON.stringify(platform)
|
|
549
|
+
}
|
|
550
|
+
});
|
|
551
|
+
} else {
|
|
552
|
+
await import_fs_extra4.default.emptyDir(options.dir);
|
|
553
|
+
}
|
|
349
554
|
await adapter.build(options);
|
|
350
|
-
const packagePath = await adapter.package(
|
|
555
|
+
const packagePath = await adapter.package(options);
|
|
351
556
|
console.log(`\u2713 ${adapter.name} package created: ${packagePath}`);
|
|
352
557
|
}
|
|
353
558
|
function getAdapter(platform) {
|
|
@@ -362,6 +567,21 @@ function getAdapter(platform) {
|
|
|
362
567
|
throw new Error(`Unknown platform: ${platform}`);
|
|
363
568
|
}
|
|
364
569
|
}
|
|
570
|
+
function out(root, platform, mode) {
|
|
571
|
+
if (platform === "android" && mode === "native") {
|
|
572
|
+
return `${root}/android-native`;
|
|
573
|
+
}
|
|
574
|
+
return `${root}/${platform}`;
|
|
575
|
+
}
|
|
576
|
+
function dir(options) {
|
|
577
|
+
if (options.platform === "android") {
|
|
578
|
+
return `${options.dir}/www`;
|
|
579
|
+
}
|
|
580
|
+
return options.dir;
|
|
581
|
+
}
|
|
582
|
+
function web(platform, mode) {
|
|
583
|
+
return platform !== "android" || mode === "webview";
|
|
584
|
+
}
|
|
365
585
|
// Annotate the CommonJS export names for ESM import in node:
|
|
366
586
|
0 && (module.exports = {
|
|
367
587
|
AndroidAdapter,
|