Skip to content

Commit 91ef6e8

Browse files
committed
feat: clean up devtools handling, add support for android emulators
1 parent 2355797 commit 91ef6e8

File tree

5 files changed

+134
-28
lines changed

5 files changed

+134
-28
lines changed

demo/App_Resources/Android/src/main/AndroidManifest.xml

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,20 @@
66
android:smallScreens="true"
77
android:normalScreens="true"
88
android:largeScreens="true"
9-
android:xlargeScreens="true"/>
9+
android:xlargeScreens="true" />
1010

11-
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
12-
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
13-
<uses-permission android:name="android.permission.INTERNET"/>
14-
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
11+
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
12+
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
13+
<uses-permission android:name="android.permission.INTERNET" />
14+
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
1515

1616
<application
1717
android:name="com.tns.NativeScriptApplication"
1818
android:allowBackup="true"
1919
android:icon="@mipmap/ic_launcher"
2020
android:label="@string/app_name"
2121
android:theme="@style/AppTheme"
22+
android:usesCleartextTraffic="true"
2223
android:hardwareAccelerated="true">
2324

2425
<activity
@@ -27,7 +28,7 @@
2728
android:configChanges="keyboard|keyboardHidden|orientation|screenSize|smallestScreenSize|screenLayout|locale|uiMode"
2829
android:theme="@style/LaunchScreenTheme"
2930
android:hardwareAccelerated="true"
30-
android:launchMode="singleTask"
31+
android:launchMode="singleTask"
3132
android:exported="true">
3233

3334
<meta-data android:name="SET_THEME_ON_LAUNCH" android:resource="@style/AppTheme" />
@@ -37,6 +38,6 @@
3738
<category android:name="android.intent.category.LAUNCHER" />
3839
</intent-filter>
3940
</activity>
40-
<activity android:name="com.tns.ErrorReportActivity"/>
41+
<activity android:name="com.tns.ErrorReportActivity" />
4142
</application>
4243
</manifest>

devtools.js

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,33 @@
11
if (__DEV__) {
2-
const temp = globalThis.global;
2+
try {
3+
const _global = globalThis.global;
34

4-
const document = {
5-
title: '',
6-
querySelector: () => null,
7-
querySelectorAll: () => [],
8-
};
5+
const host = (_global.__VUE_DEVTOOLS_HOST__ ??= __NS_VUE_DEVTOOLS_HOST__);
6+
const port = (_global.__VUE_DEVTOOLS_PORT__ ??= __NS_VUE_DEVTOOLS_PORT__);
7+
_global.__VUE_DEVTOOLS_TOAST__ ??= (message) => {
8+
console.warn('[VueDevtools]', message);
9+
};
910

10-
temp.document = document;
11-
temp.addEventListener = () => {};
12-
temp.removeEventListener = () => {};
13-
temp.window = temp;
11+
const platform = global.isAndroid ? 'Android' : 'iOS';
1412

15-
require('@vue/devtools/build/hook.js');
16-
require('@vue/devtools/build/backend.js');
13+
const documentShim = {
14+
// this shows as the title in VueDevtools
15+
title: `${platform} :: ${host}:${port} :: NativeScript`,
16+
querySelector: () => null,
17+
querySelectorAll: () => [],
18+
};
19+
20+
_global.document = Object.assign({}, documentShim, _global.document);
21+
_global.addEventListener ??= () => {};
22+
_global.removeEventListener ??= () => {};
23+
_global.window ??= _global;
24+
25+
console.warn(
26+
`[VueDevtools] Connecting to ${global.__VUE_DEVTOOLS_HOST__}:${global.__VUE_DEVTOOLS_PORT__}...`
27+
);
28+
require('@vue/devtools/build/hook.js');
29+
require('@vue/devtools/build/backend.js');
30+
} catch (e) {
31+
console.warn('[VueDevtools] Failed to init:', e);
32+
}
1733
}

nativescript.webpack.js

Lines changed: 96 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,106 @@
1-
const spawn = require('cross-spawn');
21
const { VueLoaderPlugin } = require('vue-loader');
2+
const spawn = require('cross-spawn');
3+
4+
function findFreePort(startingPort = 8098) {
5+
let found = false;
6+
let port = startingPort;
7+
8+
const isPortFree = (port) =>
9+
new Promise((resolve) => {
10+
const server = require('http')
11+
.createServer()
12+
.listen(port, '0.0.0.0', () => {
13+
server.close();
14+
resolve(true);
15+
})
16+
.on('error', () => {
17+
resolve(false);
18+
});
19+
});
20+
21+
const findFreePort = () => {
22+
isPortFree(port).then((isFree) => {
23+
if (!isFree) {
24+
port++;
25+
return findFreePort();
26+
}
27+
found = true;
28+
});
29+
};
30+
31+
findFreePort();
32+
33+
while (!found) {
34+
process._tickCallback();
35+
const start = Date.now();
36+
while (Date.now() - start < 100) {
37+
// busy wait... not ideal, but we need to find a port synchronously...
38+
}
39+
}
40+
41+
return port;
42+
}
43+
44+
function startVueDevtools(port, isAndroid = false) {
45+
console.log(`[VueDevtools] Starting standalone Vue Devtools on port ${port}`);
46+
if (isAndroid) {
47+
console.log(
48+
`[VueDevtools] If the app doesn't automatically connect, check if http traffic is allowed. (e.g. on Android, you may need to set android:usesCleartextTraffic="true" in AndroidManifest.xml)`
49+
);
50+
}
51+
spawn(require.resolve('@vue/devtools/bin.js'), [], {
52+
stdio: 'ignore',
53+
env: {
54+
...process.env,
55+
PORT: port,
56+
},
57+
});
58+
}
359

460
/**
561
* @param {typeof import("@nativescript/webpack")} webpack
662
*/
7-
module.exports = ({ env, ...webpack }) => {
63+
module.exports = (webpack) => {
864
webpack.useConfig('vue');
965

10-
webpack.chainWebpack((config) => {
66+
webpack.chainWebpack((config, env) => {
67+
const additionalDefines = {
68+
__VUE_PROD_DEVTOOLS__: false,
69+
};
70+
71+
// todo: support configuring the devtools host/port from the nativescript.config.ts...
1172
if (!!env.vueDevtools) {
12-
config.entry('bundle').prepend(require.resolve('./devtools.js'));
73+
// find a free port for the devtools
74+
const vueDevtoolsPort = findFreePort(8098);
75+
const isAndroid = webpack.Utils.platform.getPlatformName() === 'android';
76+
77+
// on android simulators, localhost is not the host machine...
78+
const vueDevtoolsHost = isAndroid
79+
? 'http://10.0.2.2'
80+
: 'http://localhost';
81+
82+
additionalDefines['__VUE_PROD_DEVTOOLS__'] = true;
83+
additionalDefines['__NS_VUE_DEVTOOLS_HOST__'] =
84+
JSON.stringify(vueDevtoolsHost);
85+
additionalDefines['__NS_VUE_DEVTOOLS_PORT__'] = vueDevtoolsPort;
86+
87+
const devtoolsEntryPath = require.resolve('./devtools.js');
88+
const entryPath = webpack.Utils.platform.getEntryPath();
89+
const paths = config.entry('bundle').values();
90+
const entryIndex = paths.indexOf(entryPath);
91+
92+
if (entryIndex === -1) {
93+
// if the app entry is not found, add the devtools entry at the beginning - generally should not happen, but just in case.
94+
paths.unshift(entryPath);
95+
} else {
96+
// insert devtools entry before the app entry, but after globals etc.
97+
paths.splice(entryIndex, 0, devtoolsEntryPath);
98+
}
99+
100+
config.entry('bundle').clear().merge(paths);
101+
102+
// start the devtools...
103+
startVueDevtools(vueDevtoolsPort, isAndroid);
13104
}
14105

15106
// resolve any imports from "vue" to "nativescript-vue"
@@ -46,7 +137,7 @@ module.exports = ({ env, ...webpack }) => {
46137
config.plugin('DefinePlugin').tap((args) => {
47138
Object.assign(args[0], {
48139
__VUE_OPTIONS_API__: true,
49-
__VUE_PROD_DEVTOOLS__: false,
140+
...additionalDefines,
50141
});
51142

52143
return args;
@@ -67,8 +158,4 @@ module.exports = ({ env, ...webpack }) => {
67158
return args;
68159
});
69160
});
70-
71-
if (!!env.vueDevtools) {
72-
spawn(require.resolve('@vue/devtools/bin.js'), [], { stdio: 'ignore' });
73-
}
74161
};

src/components/ActionBar.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ registerElement('NSCActionBar', () => NSCActionBar, {
4949
});
5050

5151
export const ActionBar = /*#__PURE__*/ defineComponent({
52+
name: 'ActionBar',
5253
setup(props, ctx) {
5354
return () => {
5455
return h(

src/components/ListView.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ function getListItem(item: any, index: number): ListItem {
4141
const LIST_CELL_ID = Symbol('list_cell_id');
4242

4343
export const ListView = /*#__PURE__*/ defineComponent({
44+
name: 'ListView',
4445
props: {
4546
items: {
4647
validator(value) {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy