jsbox-cview 1.6.3 → 1.6.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/components/dialogs/dialog-sheet.ts +1 -1
- package/components/dialogs/list-dialog.ts +26 -0
- package/components/oc-webview.ts +50 -0
- package/dist/components/dialogs/list-dialog.js +0 -9
- package/dist/components/oc-webview.js +29 -0
- package/dist/components/spinners/loading-dual-ring.js +3 -12
- package/dist/components/spinners/loading-wedges.js +3 -12
- package/dist/test/dialog-sheet.js +3 -12
- package/dist/test/form-dialog.js +3 -12
- package/dist/test/oc-webview.js +195 -0
- package/dist/test/refresh-button.js +3 -12
- package/package.json +1 -1
- package/test/oc-webview.ts +197 -0
- package/tsconfig.json +1 -1
|
@@ -36,7 +36,7 @@ export class DialogSheet extends Sheet<ContentView, UIView, UiTypes.ViewOptions>
|
|
|
36
36
|
constructor(props: {
|
|
37
37
|
title: string;
|
|
38
38
|
cview: Base<any, any>;
|
|
39
|
-
doneHandler?: () =>
|
|
39
|
+
doneHandler?: () => any;
|
|
40
40
|
presentMode?: number;
|
|
41
41
|
bgcolor?: UIColor;
|
|
42
42
|
doneButtonHidden?: boolean;
|
|
@@ -10,6 +10,32 @@ import { List } from "../single-views";
|
|
|
10
10
|
* @param values 默认选中的选项, 配合multiSelectEnabled使用
|
|
11
11
|
* @param title 标题
|
|
12
12
|
*/
|
|
13
|
+
export function listDialog({
|
|
14
|
+
items,
|
|
15
|
+
multiSelectEnabled,
|
|
16
|
+
value,
|
|
17
|
+
values,
|
|
18
|
+
title,
|
|
19
|
+
}: {
|
|
20
|
+
items: string[];
|
|
21
|
+
multiSelectEnabled: true;
|
|
22
|
+
value?: never;
|
|
23
|
+
values?: number[];
|
|
24
|
+
title: string;
|
|
25
|
+
}): Promise<number[]>;
|
|
26
|
+
export function listDialog({
|
|
27
|
+
items,
|
|
28
|
+
multiSelectEnabled,
|
|
29
|
+
value,
|
|
30
|
+
values,
|
|
31
|
+
title,
|
|
32
|
+
}: {
|
|
33
|
+
items: string[];
|
|
34
|
+
multiSelectEnabled?: false | undefined;
|
|
35
|
+
value?: number;
|
|
36
|
+
values?: never;
|
|
37
|
+
title: string;
|
|
38
|
+
}): Promise<number>;
|
|
13
39
|
export function listDialog({
|
|
14
40
|
items,
|
|
15
41
|
multiSelectEnabled,
|
package/components/oc-webview.ts
CHANGED
|
@@ -29,11 +29,13 @@ import { Base } from "./base";
|
|
|
29
29
|
* - goForward()
|
|
30
30
|
* - stopLoading()
|
|
31
31
|
* - reload()
|
|
32
|
+
* - evaluateJavaScript(script)
|
|
32
33
|
*
|
|
33
34
|
*/
|
|
34
35
|
export class OCWebView extends Base<UIView, UiTypes.RuntimeOptions> {
|
|
35
36
|
_defineView: () => UiTypes.RuntimeOptions;
|
|
36
37
|
webView: any; // 实际为WKWebView OC类型
|
|
38
|
+
private _originUrl: string;
|
|
37
39
|
constructor({
|
|
38
40
|
props,
|
|
39
41
|
layout,
|
|
@@ -53,6 +55,7 @@ export class OCWebView extends Base<UIView, UiTypes.RuntimeOptions> {
|
|
|
53
55
|
config.invoke("setWebsiteDataStore:", $objc("WKWebsiteDataStore").invoke("defaultDataStore"));
|
|
54
56
|
const webView = $objc("WKWebView").invoke("alloc.initWithFrame:configuration:", $rect(0, 0, 0, 0), config);
|
|
55
57
|
this.webView = webView;
|
|
58
|
+
this._originUrl = props.url;
|
|
56
59
|
|
|
57
60
|
this._defineView = () => {
|
|
58
61
|
return {
|
|
@@ -101,6 +104,17 @@ export class OCWebView extends Base<UIView, UiTypes.RuntimeOptions> {
|
|
|
101
104
|
return nsurl ? nsurl.invoke("absoluteString").rawValue() : "";
|
|
102
105
|
}
|
|
103
106
|
|
|
107
|
+
set url(urlStr: string) {
|
|
108
|
+
const url = $objc("NSURL").invoke("URLWithString:", urlStr);
|
|
109
|
+
const req = $objc("NSURLRequest").invoke("requestWithURL:", url);
|
|
110
|
+
this.webView.invoke("loadRequest:", req);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
get title(): string {
|
|
114
|
+
const title = this.webView.invoke("title");
|
|
115
|
+
return title ? title.rawValue() : "";
|
|
116
|
+
}
|
|
117
|
+
|
|
104
118
|
get canGoBack(): boolean {
|
|
105
119
|
return this.webView.invoke("canGoBack");
|
|
106
120
|
}
|
|
@@ -124,4 +138,40 @@ export class OCWebView extends Base<UIView, UiTypes.RuntimeOptions> {
|
|
|
124
138
|
reload() {
|
|
125
139
|
this.webView.invoke("reload");
|
|
126
140
|
}
|
|
141
|
+
|
|
142
|
+
reloadFromOrigin() {
|
|
143
|
+
this.url = this._originUrl;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
exec<T = any>(script: string): Promise<T> {
|
|
147
|
+
return new Promise((resolve, reject) => {
|
|
148
|
+
this.webView.invoke(
|
|
149
|
+
"evaluateJavaScript:completionHandler:",
|
|
150
|
+
script,
|
|
151
|
+
$block("void, id, NSError *", (result: any, error: any) => {
|
|
152
|
+
const jsError = error ? error.jsValue() : null;
|
|
153
|
+
if (jsError) {
|
|
154
|
+
reject(jsError);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
if (!result) {
|
|
158
|
+
resolve(result);
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
if (typeof result.jsValue === "function") {
|
|
162
|
+
resolve(result.jsValue());
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
resolve(result);
|
|
166
|
+
}),
|
|
167
|
+
);
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
eval({ script, handler }: { script: string; handler: (result: any, error?: NSError) => void }) {
|
|
172
|
+
this.exec(script).then(
|
|
173
|
+
(result) => handler(result),
|
|
174
|
+
(error) => handler(undefined, error),
|
|
175
|
+
);
|
|
176
|
+
}
|
|
127
177
|
}
|
|
@@ -3,15 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.listDialog = void 0;
|
|
4
4
|
const dialog_sheet_1 = require("./dialog-sheet");
|
|
5
5
|
const single_views_1 = require("../single-views");
|
|
6
|
-
/**
|
|
7
|
-
* 显示一个列表以供选择
|
|
8
|
-
*
|
|
9
|
-
* @param items 选项
|
|
10
|
-
* @param multiSelectEnabled 是否允许多选
|
|
11
|
-
* @param value 默认选中的选项
|
|
12
|
-
* @param values 默认选中的选项, 配合multiSelectEnabled使用
|
|
13
|
-
* @param title 标题
|
|
14
|
-
*/
|
|
15
6
|
function listDialog({ items, multiSelectEnabled, value, values = [], title, }) {
|
|
16
7
|
if (value)
|
|
17
8
|
values = [value];
|
|
@@ -31,6 +31,7 @@ const base_1 = require("./base");
|
|
|
31
31
|
* - goForward()
|
|
32
32
|
* - stopLoading()
|
|
33
33
|
* - reload()
|
|
34
|
+
* - evaluateJavaScript(script)
|
|
34
35
|
*
|
|
35
36
|
*/
|
|
36
37
|
class OCWebView extends base_1.Base {
|
|
@@ -84,6 +85,10 @@ class OCWebView extends base_1.Base {
|
|
|
84
85
|
const nsurl = this.webView.invoke("URL");
|
|
85
86
|
return nsurl ? nsurl.invoke("absoluteString").rawValue() : "";
|
|
86
87
|
}
|
|
88
|
+
get title() {
|
|
89
|
+
const title = this.webView.invoke("title");
|
|
90
|
+
return title ? title.rawValue() : "";
|
|
91
|
+
}
|
|
87
92
|
get canGoBack() {
|
|
88
93
|
return this.webView.invoke("canGoBack");
|
|
89
94
|
}
|
|
@@ -104,5 +109,29 @@ class OCWebView extends base_1.Base {
|
|
|
104
109
|
reload() {
|
|
105
110
|
this.webView.invoke("reload");
|
|
106
111
|
}
|
|
112
|
+
evaluateJavaScript(script) {
|
|
113
|
+
return new Promise((resolve, reject) => {
|
|
114
|
+
this.webView.invoke("evaluateJavaScript:completionHandler:", script, $block("void, id, NSError *", (result, error) => {
|
|
115
|
+
const jsError = error ? error.jsValue() : null;
|
|
116
|
+
if (jsError) {
|
|
117
|
+
reject(jsError);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (!result) {
|
|
121
|
+
resolve(result);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (typeof result.jsValue === "function") {
|
|
125
|
+
resolve(result.jsValue());
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (typeof result.rawValue === "function") {
|
|
129
|
+
resolve(result.rawValue());
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
resolve(result);
|
|
133
|
+
}));
|
|
134
|
+
});
|
|
135
|
+
}
|
|
107
136
|
}
|
|
108
137
|
exports.OCWebView = OCWebView;
|
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
3
|
exports.DualRing = void 0;
|
|
13
4
|
const base_1 = require("../base");
|
|
@@ -72,15 +63,15 @@ class DualRing extends base_1.Base {
|
|
|
72
63
|
views: [canvas1.definition, canvas2.definition],
|
|
73
64
|
layout,
|
|
74
65
|
events: {
|
|
75
|
-
ready: (sender) =>
|
|
66
|
+
ready: async (sender) => {
|
|
76
67
|
while (sender.super) {
|
|
77
68
|
canvas1.startAngle += Math.PI * interval * 2;
|
|
78
69
|
canvas1.redraw();
|
|
79
70
|
canvas2.startAngle += Math.PI * interval * 2;
|
|
80
71
|
canvas2.redraw();
|
|
81
|
-
|
|
72
|
+
await $wait(interval);
|
|
82
73
|
}
|
|
83
|
-
}
|
|
74
|
+
},
|
|
84
75
|
},
|
|
85
76
|
};
|
|
86
77
|
};
|
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
3
|
exports.Wedges = void 0;
|
|
13
4
|
const base_1 = require("../base");
|
|
@@ -77,7 +68,7 @@ class Wedges extends base_1.Base {
|
|
|
77
68
|
views: [canvas1.definition, canvas2.definition, canvas3.definition, canvas4.definition],
|
|
78
69
|
layout,
|
|
79
70
|
events: {
|
|
80
|
-
ready: (sender) =>
|
|
71
|
+
ready: async (sender) => {
|
|
81
72
|
while (sender.super) {
|
|
82
73
|
canvas1.startAngle += Math.PI * interval * 4;
|
|
83
74
|
canvas1.redraw();
|
|
@@ -87,9 +78,9 @@ class Wedges extends base_1.Base {
|
|
|
87
78
|
canvas3.redraw();
|
|
88
79
|
canvas4.startAngle += Math.PI * interval * 1;
|
|
89
80
|
canvas4.redraw();
|
|
90
|
-
|
|
81
|
+
await $wait(interval);
|
|
91
82
|
}
|
|
92
|
-
}
|
|
83
|
+
},
|
|
93
84
|
},
|
|
94
85
|
};
|
|
95
86
|
};
|
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
3
|
const dialog_sheet_1 = require("../components/dialogs/dialog-sheet");
|
|
13
4
|
const single_views_1 = require("../components/single-views");
|
|
@@ -26,7 +17,7 @@ $ui.render({
|
|
|
26
17
|
},
|
|
27
18
|
layout: $layout.center,
|
|
28
19
|
events: {
|
|
29
|
-
tapped: () =>
|
|
20
|
+
tapped: async () => {
|
|
30
21
|
const sheet = new dialog_sheet_1.DialogSheet({
|
|
31
22
|
title: "Dialog Sheet",
|
|
32
23
|
cview,
|
|
@@ -41,8 +32,8 @@ $ui.render({
|
|
|
41
32
|
},
|
|
42
33
|
doneButtonTitle: "完成",
|
|
43
34
|
});
|
|
44
|
-
|
|
45
|
-
}
|
|
35
|
+
await sheet.present();
|
|
36
|
+
},
|
|
46
37
|
},
|
|
47
38
|
},
|
|
48
39
|
],
|
package/dist/test/form-dialog.js
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
3
|
const form_dialog_1 = require("../components/dialogs/form-dialog");
|
|
13
4
|
$ui.render({
|
|
@@ -19,8 +10,8 @@ $ui.render({
|
|
|
19
10
|
},
|
|
20
11
|
layout: $layout.center,
|
|
21
12
|
events: {
|
|
22
|
-
tapped: () =>
|
|
23
|
-
const values =
|
|
13
|
+
tapped: async () => {
|
|
14
|
+
const values = await (0, form_dialog_1.formDialog)({
|
|
24
15
|
sections: [
|
|
25
16
|
{
|
|
26
17
|
title: "Section 1",
|
|
@@ -53,7 +44,7 @@ $ui.render({
|
|
|
53
44
|
title: "Values",
|
|
54
45
|
message: JSON.stringify(values, null, 2),
|
|
55
46
|
});
|
|
56
|
-
}
|
|
47
|
+
},
|
|
57
48
|
},
|
|
58
49
|
},
|
|
59
50
|
],
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const oc_webview_1 = require("../components/oc-webview");
|
|
4
|
+
const initialURL = "https://www.example.com";
|
|
5
|
+
const normalizeURL = (value) => {
|
|
6
|
+
const url = value.trim();
|
|
7
|
+
if (!url)
|
|
8
|
+
return initialURL;
|
|
9
|
+
if (/^[a-z][a-z\d+\-.]*:\/\//i.test(url))
|
|
10
|
+
return url;
|
|
11
|
+
return `https://${url}`;
|
|
12
|
+
};
|
|
13
|
+
const currentURL = (sender) => {
|
|
14
|
+
const nsurl = sender.invoke("URL");
|
|
15
|
+
return nsurl ? nsurl.invoke("absoluteString").rawValue() : "";
|
|
16
|
+
};
|
|
17
|
+
const currentTitle = (sender) => {
|
|
18
|
+
const title = sender.invoke("title");
|
|
19
|
+
return title ? title.rawValue() : "";
|
|
20
|
+
};
|
|
21
|
+
const syncAddress = (sender) => {
|
|
22
|
+
const input = $("oc-webview-url");
|
|
23
|
+
if (!input)
|
|
24
|
+
return;
|
|
25
|
+
const url = currentURL(sender);
|
|
26
|
+
if (url)
|
|
27
|
+
input.text = url;
|
|
28
|
+
};
|
|
29
|
+
const logState = (event, sender, error) => {
|
|
30
|
+
const url = currentURL(sender);
|
|
31
|
+
const title = currentTitle(sender);
|
|
32
|
+
const message = error ? ` error=${error.localizedDescription}` : "";
|
|
33
|
+
console.log(`[${event}] url=${url} title=${title}${message}`);
|
|
34
|
+
};
|
|
35
|
+
const localStorageScript = `
|
|
36
|
+
(() => {
|
|
37
|
+
const data = {};
|
|
38
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
39
|
+
const key = localStorage.key(i);
|
|
40
|
+
if (key !== null) data[key] = localStorage.getItem(key);
|
|
41
|
+
}
|
|
42
|
+
return JSON.stringify(data);
|
|
43
|
+
})()
|
|
44
|
+
`;
|
|
45
|
+
const webView = new oc_webview_1.OCWebView({
|
|
46
|
+
props: {
|
|
47
|
+
url: initialURL,
|
|
48
|
+
},
|
|
49
|
+
layout: (make, view) => {
|
|
50
|
+
make.top.equalTo($("oc-webview-toolbar").bottom);
|
|
51
|
+
make.left.right.bottom.inset(0);
|
|
52
|
+
},
|
|
53
|
+
events: {
|
|
54
|
+
didStart: (sender) => {
|
|
55
|
+
syncAddress(sender);
|
|
56
|
+
logState("didStart", sender);
|
|
57
|
+
},
|
|
58
|
+
didFinish: async (sender) => {
|
|
59
|
+
syncAddress(sender);
|
|
60
|
+
logState("didFinish", sender);
|
|
61
|
+
try {
|
|
62
|
+
const localStorage = await webView.evaluateJavaScript(localStorageScript);
|
|
63
|
+
console.log(`[localStorage] ${localStorage || "{}"}`);
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
console.log(`[localStorage] error=${(error === null || error === void 0 ? void 0 : error.localizedDescription) || error}`);
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
didFail: (sender, error) => {
|
|
70
|
+
syncAddress(sender);
|
|
71
|
+
logState("didFail", sender, error);
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
});
|
|
75
|
+
const loadURL = (value) => {
|
|
76
|
+
const url = normalizeURL(value);
|
|
77
|
+
const input = $("oc-webview-url");
|
|
78
|
+
if (input)
|
|
79
|
+
input.text = url;
|
|
80
|
+
const nsurl = $objc("NSURL").invoke("URLWithString:", url);
|
|
81
|
+
const request = $objc("NSURLRequest").invoke("requestWithURL:", nsurl);
|
|
82
|
+
webView.webView.invoke("loadRequest:", request);
|
|
83
|
+
};
|
|
84
|
+
$ui.render({
|
|
85
|
+
views: [
|
|
86
|
+
{
|
|
87
|
+
type: "view",
|
|
88
|
+
props: {
|
|
89
|
+
id: "oc-webview-toolbar",
|
|
90
|
+
},
|
|
91
|
+
layout: (make, view) => {
|
|
92
|
+
make.top.equalTo(view.super.safeAreaTop);
|
|
93
|
+
make.left.right.inset(0);
|
|
94
|
+
make.height.equalTo(88);
|
|
95
|
+
},
|
|
96
|
+
views: [
|
|
97
|
+
{
|
|
98
|
+
type: "input",
|
|
99
|
+
props: {
|
|
100
|
+
id: "oc-webview-url",
|
|
101
|
+
text: initialURL,
|
|
102
|
+
type: $kbType.url,
|
|
103
|
+
bgcolor: $color("secondarySurface"),
|
|
104
|
+
radius: 8,
|
|
105
|
+
placeholder: "输入网址后回车",
|
|
106
|
+
},
|
|
107
|
+
layout: (make, view) => {
|
|
108
|
+
make.top.inset(12);
|
|
109
|
+
make.left.right.inset(12);
|
|
110
|
+
make.height.equalTo(36);
|
|
111
|
+
},
|
|
112
|
+
events: {
|
|
113
|
+
returned: (sender) => {
|
|
114
|
+
loadURL(sender.text);
|
|
115
|
+
},
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
type: "view",
|
|
120
|
+
props: {},
|
|
121
|
+
layout: (make, view) => {
|
|
122
|
+
make.top.equalTo(view.prev.bottom).offset(8);
|
|
123
|
+
make.left.right.bottom.inset(12);
|
|
124
|
+
},
|
|
125
|
+
views: [
|
|
126
|
+
{
|
|
127
|
+
type: "button",
|
|
128
|
+
props: {
|
|
129
|
+
title: "后退",
|
|
130
|
+
},
|
|
131
|
+
layout: (make, view) => {
|
|
132
|
+
make.left.top.bottom.inset(0);
|
|
133
|
+
make.width.equalTo(72);
|
|
134
|
+
},
|
|
135
|
+
events: {
|
|
136
|
+
tapped: () => {
|
|
137
|
+
webView.goBack();
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
type: "button",
|
|
143
|
+
props: {
|
|
144
|
+
title: "前进",
|
|
145
|
+
},
|
|
146
|
+
layout: (make, view) => {
|
|
147
|
+
make.left.equalTo(view.prev.right).offset(8);
|
|
148
|
+
make.top.bottom.equalTo(view.prev);
|
|
149
|
+
make.width.equalTo(72);
|
|
150
|
+
},
|
|
151
|
+
events: {
|
|
152
|
+
tapped: () => {
|
|
153
|
+
webView.goForward();
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
type: "button",
|
|
159
|
+
props: {
|
|
160
|
+
title: "刷新",
|
|
161
|
+
},
|
|
162
|
+
layout: (make, view) => {
|
|
163
|
+
make.left.equalTo(view.prev.right).offset(8);
|
|
164
|
+
make.top.bottom.equalTo(view.prev);
|
|
165
|
+
make.width.equalTo(72);
|
|
166
|
+
},
|
|
167
|
+
events: {
|
|
168
|
+
tapped: () => {
|
|
169
|
+
webView.reload();
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
type: "button",
|
|
175
|
+
props: {
|
|
176
|
+
title: "分享",
|
|
177
|
+
},
|
|
178
|
+
layout: (make, view) => {
|
|
179
|
+
make.left.equalTo(view.prev.right).offset(8);
|
|
180
|
+
make.top.bottom.equalTo(view.prev);
|
|
181
|
+
make.width.equalTo(72);
|
|
182
|
+
},
|
|
183
|
+
events: {
|
|
184
|
+
tapped: () => {
|
|
185
|
+
$share.sheet(currentURL(webView.webView) || initialURL);
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
},
|
|
191
|
+
],
|
|
192
|
+
},
|
|
193
|
+
webView.definition,
|
|
194
|
+
],
|
|
195
|
+
});
|
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
3
|
const refresh_button_1 = require("../components/refresh-button");
|
|
13
4
|
const refreshButton = new refresh_button_1.RefreshButton({
|
|
@@ -23,11 +14,11 @@ const refreshButton = new refresh_button_1.RefreshButton({
|
|
|
23
14
|
make.centerX.equalTo(view.super);
|
|
24
15
|
},
|
|
25
16
|
events: {
|
|
26
|
-
tapped: () =>
|
|
17
|
+
tapped: async () => {
|
|
27
18
|
refreshButton.loading = true;
|
|
28
|
-
|
|
19
|
+
await $wait(2);
|
|
29
20
|
refreshButton.loading = false;
|
|
30
|
-
}
|
|
21
|
+
},
|
|
31
22
|
},
|
|
32
23
|
});
|
|
33
24
|
$ui.render({
|
package/package.json
CHANGED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { OCWebView } from "../components/oc-webview";
|
|
2
|
+
|
|
3
|
+
const initialURL = "https://www.example.com";
|
|
4
|
+
|
|
5
|
+
const normalizeURL = (value: string) => {
|
|
6
|
+
const url = value.trim();
|
|
7
|
+
if (!url) return initialURL;
|
|
8
|
+
if (/^[a-z][a-z\d+\-.]*:\/\//i.test(url)) return url;
|
|
9
|
+
return `https://${url}`;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const currentURL = (sender: any) => {
|
|
13
|
+
const nsurl = sender.invoke("URL");
|
|
14
|
+
return nsurl ? nsurl.invoke("absoluteString").rawValue() : "";
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const currentTitle = (sender: any) => {
|
|
18
|
+
const title = sender.invoke("title");
|
|
19
|
+
return title ? title.rawValue() : "";
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const syncAddress = (sender: any) => {
|
|
23
|
+
const input = $("oc-webview-url") as UIInputView | undefined;
|
|
24
|
+
if (!input) return;
|
|
25
|
+
const url = currentURL(sender);
|
|
26
|
+
if (url) input.text = url;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const logState = (event: string, sender: any, error?: NSError | null) => {
|
|
30
|
+
const url = currentURL(sender);
|
|
31
|
+
const title = currentTitle(sender);
|
|
32
|
+
const message = error ? ` error=${error.localizedDescription}` : "";
|
|
33
|
+
console.log(`[${event}] url=${url} title=${title}${message}`);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const localStorageScript = `
|
|
37
|
+
(() => {
|
|
38
|
+
const data = {};
|
|
39
|
+
for (let i = 0; i < localStorage.length; i++) {
|
|
40
|
+
const key = localStorage.key(i);
|
|
41
|
+
if (key !== null) data[key] = localStorage.getItem(key);
|
|
42
|
+
}
|
|
43
|
+
return JSON.stringify(data);
|
|
44
|
+
})()
|
|
45
|
+
`;
|
|
46
|
+
|
|
47
|
+
const webView = new OCWebView({
|
|
48
|
+
props: {
|
|
49
|
+
url: initialURL,
|
|
50
|
+
},
|
|
51
|
+
layout: (make, view) => {
|
|
52
|
+
make.top.equalTo($("oc-webview-toolbar").bottom);
|
|
53
|
+
make.left.right.bottom.inset(0);
|
|
54
|
+
},
|
|
55
|
+
events: {
|
|
56
|
+
didStart: (sender) => {
|
|
57
|
+
syncAddress(sender);
|
|
58
|
+
logState("didStart", sender);
|
|
59
|
+
},
|
|
60
|
+
didFinish: async (sender) => {
|
|
61
|
+
syncAddress(sender);
|
|
62
|
+
logState("didFinish", sender);
|
|
63
|
+
try {
|
|
64
|
+
const localStorage = await webView.exec<string>(localStorageScript);
|
|
65
|
+
console.log(`[localStorage] ${localStorage || "{}"}`);
|
|
66
|
+
} catch (error: any) {
|
|
67
|
+
console.log(`[localStorage] error=${error?.localizedDescription || error}`);
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
didFail: (sender, error) => {
|
|
71
|
+
syncAddress(sender);
|
|
72
|
+
logState("didFail", sender, error);
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
const loadURL = (value: string) => {
|
|
78
|
+
const url = normalizeURL(value);
|
|
79
|
+
const input = $("oc-webview-url") as UIInputView | undefined;
|
|
80
|
+
if (input) input.text = url;
|
|
81
|
+
const nsurl = $objc("NSURL").invoke("URLWithString:", url);
|
|
82
|
+
const request = $objc("NSURLRequest").invoke("requestWithURL:", nsurl);
|
|
83
|
+
webView.webView.invoke("loadRequest:", request);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
$ui.render({
|
|
87
|
+
views: [
|
|
88
|
+
{
|
|
89
|
+
type: "view",
|
|
90
|
+
props: {
|
|
91
|
+
id: "oc-webview-toolbar",
|
|
92
|
+
},
|
|
93
|
+
layout: (make, view) => {
|
|
94
|
+
make.top.equalTo(view.super.safeAreaTop);
|
|
95
|
+
make.left.right.inset(0);
|
|
96
|
+
make.height.equalTo(88);
|
|
97
|
+
},
|
|
98
|
+
views: [
|
|
99
|
+
{
|
|
100
|
+
type: "input",
|
|
101
|
+
props: {
|
|
102
|
+
id: "oc-webview-url",
|
|
103
|
+
text: initialURL,
|
|
104
|
+
type: $kbType.url,
|
|
105
|
+
bgcolor: $color("secondarySurface"),
|
|
106
|
+
radius: 8,
|
|
107
|
+
placeholder: "输入网址后回车",
|
|
108
|
+
},
|
|
109
|
+
layout: (make, view) => {
|
|
110
|
+
make.top.inset(12);
|
|
111
|
+
make.left.right.inset(12);
|
|
112
|
+
make.height.equalTo(36);
|
|
113
|
+
},
|
|
114
|
+
events: {
|
|
115
|
+
returned: (sender) => {
|
|
116
|
+
loadURL(sender.text);
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
type: "view",
|
|
122
|
+
props: {},
|
|
123
|
+
layout: (make, view) => {
|
|
124
|
+
make.top.equalTo(view.prev.bottom).offset(8);
|
|
125
|
+
make.left.right.bottom.inset(12);
|
|
126
|
+
},
|
|
127
|
+
views: [
|
|
128
|
+
{
|
|
129
|
+
type: "button",
|
|
130
|
+
props: {
|
|
131
|
+
title: "后退",
|
|
132
|
+
},
|
|
133
|
+
layout: (make, view) => {
|
|
134
|
+
make.left.top.bottom.inset(0);
|
|
135
|
+
make.width.equalTo(72);
|
|
136
|
+
},
|
|
137
|
+
events: {
|
|
138
|
+
tapped: () => {
|
|
139
|
+
webView.goBack();
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
type: "button",
|
|
145
|
+
props: {
|
|
146
|
+
title: "前进",
|
|
147
|
+
},
|
|
148
|
+
layout: (make, view) => {
|
|
149
|
+
make.left.equalTo(view.prev.right).offset(8);
|
|
150
|
+
make.top.bottom.equalTo(view.prev);
|
|
151
|
+
make.width.equalTo(72);
|
|
152
|
+
},
|
|
153
|
+
events: {
|
|
154
|
+
tapped: () => {
|
|
155
|
+
webView.goForward();
|
|
156
|
+
},
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
type: "button",
|
|
161
|
+
props: {
|
|
162
|
+
title: "刷新",
|
|
163
|
+
},
|
|
164
|
+
layout: (make, view) => {
|
|
165
|
+
make.left.equalTo(view.prev.right).offset(8);
|
|
166
|
+
make.top.bottom.equalTo(view.prev);
|
|
167
|
+
make.width.equalTo(72);
|
|
168
|
+
},
|
|
169
|
+
events: {
|
|
170
|
+
tapped: () => {
|
|
171
|
+
webView.reload();
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
type: "button",
|
|
177
|
+
props: {
|
|
178
|
+
title: "分享",
|
|
179
|
+
},
|
|
180
|
+
layout: (make, view) => {
|
|
181
|
+
make.left.equalTo(view.prev.right).offset(8);
|
|
182
|
+
make.top.bottom.equalTo(view.prev);
|
|
183
|
+
make.width.equalTo(72);
|
|
184
|
+
},
|
|
185
|
+
events: {
|
|
186
|
+
tapped: () => {
|
|
187
|
+
$share.sheet(currentURL(webView.webView) || initialURL);
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
],
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
},
|
|
195
|
+
webView.definition,
|
|
196
|
+
],
|
|
197
|
+
});
|
package/tsconfig.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
|
12
12
|
|
|
13
13
|
/* Language and Environment */
|
|
14
|
-
"target": "
|
|
14
|
+
"target": "es2017", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
|
15
15
|
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
|
16
16
|
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
|
17
17
|
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
|