@thelacanians/vue-native-cli 0.4.7 → 0.4.9
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/dist/cli.js +1 -1
- package/native/android/VueNativeCore/build.gradle.kts +1 -1
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/HotReloadManager.swift +11 -1
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/JSPolyfills.swift +21 -0
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Bridge/VueNativeViewController.swift +8 -5
- package/native/ios/VueNativeCore/Sources/VueNativeCore/Components/ComponentRegistry.swift +10 -2
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -10,7 +10,7 @@ import { join, dirname } from "path";
|
|
|
10
10
|
import { fileURLToPath } from "url";
|
|
11
11
|
import { existsSync } from "fs";
|
|
12
12
|
import pc from "picocolors";
|
|
13
|
-
var VERSION = "0.4.
|
|
13
|
+
var VERSION = "0.4.9";
|
|
14
14
|
var createCommand = new Command("create").description("Create a new Vue Native project").argument("<name>", "project name").option("-t, --template <template>", "project template (blank, tabs, drawer)", "blank").action(async (name, options) => {
|
|
15
15
|
const template = options.template;
|
|
16
16
|
if (!["blank", "tabs", "drawer"].includes(template)) {
|
|
@@ -19,6 +19,8 @@ public final class HotReloadManager: NSObject, URLSessionWebSocketDelegate {
|
|
|
19
19
|
private var session: URLSession?
|
|
20
20
|
private var serverURL: URL?
|
|
21
21
|
private var isConnecting = false
|
|
22
|
+
private var reconnectAttempts = 0
|
|
23
|
+
private let maxReconnectAttempts = 10
|
|
22
24
|
|
|
23
25
|
private override init() {
|
|
24
26
|
super.init()
|
|
@@ -29,6 +31,7 @@ public final class HotReloadManager: NSObject, URLSessionWebSocketDelegate {
|
|
|
29
31
|
/// Connect to the dev server. Safe to call multiple times.
|
|
30
32
|
public func connect(to url: URL) {
|
|
31
33
|
serverURL = url
|
|
34
|
+
reconnectAttempts = 0
|
|
32
35
|
scheduleConnect(delay: 0)
|
|
33
36
|
}
|
|
34
37
|
|
|
@@ -103,6 +106,7 @@ public final class HotReloadManager: NSObject, URLSessionWebSocketDelegate {
|
|
|
103
106
|
switch type {
|
|
104
107
|
case "connected":
|
|
105
108
|
isConnecting = false
|
|
109
|
+
reconnectAttempts = 0
|
|
106
110
|
NSLog("[VueNative HotReload] Connected — hot reload active")
|
|
107
111
|
|
|
108
112
|
case "bundle":
|
|
@@ -126,8 +130,14 @@ public final class HotReloadManager: NSObject, URLSessionWebSocketDelegate {
|
|
|
126
130
|
|
|
127
131
|
private func scheduleReconnect() {
|
|
128
132
|
guard serverURL != nil else { return }
|
|
133
|
+
reconnectAttempts += 1
|
|
134
|
+
if reconnectAttempts > maxReconnectAttempts {
|
|
135
|
+
NSLog("[VueNative HotReload] Giving up after %d attempts — start `bun run dev` and relaunch the app", maxReconnectAttempts)
|
|
136
|
+
disconnect()
|
|
137
|
+
return
|
|
138
|
+
}
|
|
129
139
|
isConnecting = false
|
|
130
|
-
NSLog("[VueNative HotReload] Reconnecting in 2s...")
|
|
140
|
+
NSLog("[VueNative HotReload] Reconnecting in 2s... (attempt %d/%d)", reconnectAttempts, maxReconnectAttempts)
|
|
131
141
|
scheduleConnect(delay: 2.0)
|
|
132
142
|
}
|
|
133
143
|
|
|
@@ -79,6 +79,27 @@ enum JSPolyfills {
|
|
|
79
79
|
registerTextEncoding(in: context)
|
|
80
80
|
registerURL(in: context)
|
|
81
81
|
registerCrypto(in: context)
|
|
82
|
+
registerBridgeStubs(in: context)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// MARK: - Bridge callback stubs
|
|
86
|
+
|
|
87
|
+
/// Register no-op stubs for global functions that the bundle will overwrite.
|
|
88
|
+
/// Native modules may call dispatchGlobalEvent() before the JS bundle has
|
|
89
|
+
/// loaded and registered the real handlers — these stubs prevent the
|
|
90
|
+
/// "JS function 'X' not found" warnings during that window.
|
|
91
|
+
private static func registerBridgeStubs(in context: JSContext) {
|
|
92
|
+
context.evaluateScript("""
|
|
93
|
+
if (typeof __VN_handleGlobalEvent === 'undefined') {
|
|
94
|
+
globalThis.__VN_handleGlobalEvent = function() {};
|
|
95
|
+
}
|
|
96
|
+
if (typeof __VN_handleEvent === 'undefined') {
|
|
97
|
+
globalThis.__VN_handleEvent = function() {};
|
|
98
|
+
}
|
|
99
|
+
if (typeof __VN_resolveCallback === 'undefined') {
|
|
100
|
+
globalThis.__VN_resolveCallback = function() {};
|
|
101
|
+
}
|
|
102
|
+
""")
|
|
82
103
|
}
|
|
83
104
|
|
|
84
105
|
// MARK: - console.log / warn / error
|
|
@@ -50,7 +50,10 @@ open class VueNativeViewController: UIViewController {
|
|
|
50
50
|
|
|
51
51
|
override open func viewDidLoad() {
|
|
52
52
|
super.viewDidLoad()
|
|
53
|
-
|
|
53
|
+
// Use black as the loading background so any unstyled gap between the
|
|
54
|
+
// native chrome and the Vue-rendered root view is not visible.
|
|
55
|
+
// The Vue app sets its own background colour via VSafeArea / VView props.
|
|
56
|
+
view.backgroundColor = .black
|
|
54
57
|
|
|
55
58
|
// Initialize JS engine first (creates JSContext, registers polyfills).
|
|
56
59
|
// Bridge init MUST happen inside this callback so the JSContext exists
|
|
@@ -69,14 +72,14 @@ open class VueNativeViewController: UIViewController {
|
|
|
69
72
|
// MARK: - Bundle loading
|
|
70
73
|
|
|
71
74
|
private func loadBundle() {
|
|
75
|
+
#if DEBUG
|
|
72
76
|
if let wsURL = devServerURL {
|
|
73
77
|
// Connect hot reload manager; it will also do the initial HTTP fetch
|
|
74
78
|
HotReloadManager.shared.connect(to: wsURL)
|
|
75
|
-
// Also load from the embedded bundle immediately as a fallback
|
|
76
|
-
loadEmbeddedBundle()
|
|
77
|
-
} else {
|
|
78
|
-
loadEmbeddedBundle()
|
|
79
79
|
}
|
|
80
|
+
#endif
|
|
81
|
+
// Always load from the embedded bundle (serves as fallback in dev, sole source in release)
|
|
82
|
+
loadEmbeddedBundle()
|
|
80
83
|
}
|
|
81
84
|
|
|
82
85
|
private func loadEmbeddedBundle() {
|
|
@@ -166,8 +166,16 @@ final class VRootFactory: NativeComponentFactory {
|
|
|
166
166
|
|
|
167
167
|
func createView() -> UIView {
|
|
168
168
|
let view = UIView()
|
|
169
|
-
//
|
|
170
|
-
|
|
169
|
+
// Configure the root Yoga node to fill its container and stack children
|
|
170
|
+
// vertically (column direction matches the default CSS flex behaviour).
|
|
171
|
+
// grow(1) + width/height 100% ensures the entire safe-area rect is
|
|
172
|
+
// occupied even if the first child doesn't explicitly set flex: 1.
|
|
173
|
+
view.flex
|
|
174
|
+
.direction(.column)
|
|
175
|
+
.grow(1)
|
|
176
|
+
.shrink(1)
|
|
177
|
+
.width(100%)
|
|
178
|
+
.height(100%)
|
|
171
179
|
return view
|
|
172
180
|
}
|
|
173
181
|
|