jsbox-cview 1.5.0 → 1.5.1
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.
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Base } from "./base";
|
|
2
|
+
import { cvid } from "../utils/cvid";
|
|
2
3
|
|
|
3
4
|
type MenuItem = {
|
|
4
5
|
title: string;
|
|
@@ -9,93 +10,33 @@ type MenuItem = {
|
|
|
9
10
|
|
|
10
11
|
const RegisteredOCClassName: Set<string> = new Set()
|
|
11
12
|
|
|
12
|
-
function defineOCClass({ classname, menuList }: {
|
|
13
|
-
classname: string;
|
|
14
|
-
menuList: { title: string; items: MenuItem[] }[]
|
|
15
|
-
}) {
|
|
16
|
-
if (RegisteredOCClassName.has(classname)) return;
|
|
17
|
-
RegisteredOCClassName.add(classname);
|
|
18
|
-
$define({
|
|
19
|
-
type: classname + " : UIView <UIContextMenuInteractionDelegate>",
|
|
20
|
-
events: {
|
|
21
|
-
"contextMenuInteraction:configurationForMenuAtLocation:": (interacton: any, point: JBPoint) => {
|
|
22
|
-
console.log(interacton.$view().jsValue().info)
|
|
23
|
-
const menuIndex = (interacton.$view().jsValue().info?.menuIndex ?? 0) as number;
|
|
24
|
-
if (menuIndex < 0 || menuIndex >= menuList.length) return
|
|
25
|
-
return createContextMenuConfiguration(menuList[menuIndex]);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
})
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function createUIAction(item: MenuItem) {
|
|
32
|
-
const action = $objc("UIAction").$actionWithTitle_image_identifier_handler(
|
|
33
|
-
item.title,
|
|
34
|
-
item.symbol,
|
|
35
|
-
null,
|
|
36
|
-
$block("void, UIAction *", () => item.handler())
|
|
37
|
-
);
|
|
38
|
-
if (item.destructive) action.$setAttributes(1 << 1);
|
|
39
|
-
return action;
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
function createContextMenuConfiguration({ title, items }: { title: string, items: MenuItem[] }) {
|
|
43
|
-
return $objc("UIContextMenuConfiguration").$configurationWithIdentifier_previewProvider_actionProvider(
|
|
44
|
-
null,
|
|
45
|
-
null,
|
|
46
|
-
$block("UIMenu *, NSArray *", () => {
|
|
47
|
-
const actions = items.map(item => createUIAction(item))
|
|
48
|
-
return $objc("UIMenu").$menuWithTitle_children(title, actions);
|
|
49
|
-
})
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
function createRuntimeView(classname: string, menuList: { title: string; items: MenuItem[] }[]) {
|
|
54
|
-
defineOCClass({ classname, menuList });
|
|
55
|
-
const view = $objc(classname).invoke("alloc.init");
|
|
56
|
-
const interaction = $objc("UIContextMenuInteraction")
|
|
57
|
-
.invoke("alloc")
|
|
58
|
-
.invoke("initWithDelegate", view);
|
|
59
|
-
view.$addInteraction(interaction);
|
|
60
|
-
return view;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
13
|
/**
|
|
64
14
|
* 动态上下文菜单视图,此视图是为了弥补JSBox中无法动态调整上下文菜单的缺陷而设计的。
|
|
65
15
|
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
* 这和menuList是配套的,同一套menuList用同一个类名。
|
|
72
|
-
* 2. menuList: { title: string; items: MenuItem[] }[] 菜单列表,每个菜单项包含一个标题和一个MenuItem数组。
|
|
73
|
-
* 3. props.info: { menuIndex: number } 用于指定当前视图的菜单索引,从0开始。info中可以包含其他参数。
|
|
16
|
+
* 此视图除了一般UIView的props, layout, events, views四个参数外,还有必须的特殊参数:
|
|
17
|
+
* 1. classname?: string OC类名,如果不指定则会自动生成一个唯一的类名。
|
|
18
|
+
* 如果有不同的DynamicContextMenuView实例使用相同的OC类,那么无法确定弹出的contextMenu是绑定了哪个实例。换言之,实例A弹出的Menu可能是绑定的实例B。
|
|
19
|
+
* 如果这样做,必须使用下面generateContextMenu的sender参数来定位。
|
|
20
|
+
* 2. generateContextMenu: (sender: UIView) => { title: string; items: MenuItem[]; } 生成上下文菜单的回调函数。
|
|
74
21
|
*
|
|
75
22
|
*/
|
|
76
|
-
export class DynamicContextMenuView extends Base<
|
|
77
|
-
private
|
|
23
|
+
export class DynamicContextMenuView extends Base<UIView, UiTypes.RuntimeOptions> {
|
|
24
|
+
private generateContextMenu: (sender: UIView) => { title: string; items: MenuItem[]; };
|
|
25
|
+
private _ocClassName: string;
|
|
78
26
|
_defineView: () => UiTypes.RuntimeOptions;
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
27
|
+
|
|
28
|
+
constructor({ classname, generateContextMenu, props, layout, events, views }: {
|
|
29
|
+
classname?: string;
|
|
30
|
+
generateContextMenu: (sender: UIView) => { title: string; items: MenuItem[]; };
|
|
82
31
|
props: UiTypes.BaseViewProps;
|
|
83
32
|
layout?: (make: MASConstraintMaker, view: UIView) => void;
|
|
84
33
|
events?: UiTypes.BaseViewEvents;
|
|
85
|
-
views
|
|
34
|
+
views?: UiTypes.AllViewOptions[];
|
|
86
35
|
}) {
|
|
87
36
|
super();
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if (typeof props.info.menuIndex !== "number") {
|
|
92
|
-
throw new Error("props.info.menuIndex must be a number");
|
|
93
|
-
}
|
|
94
|
-
if (props.info.menuIndex < 0 || props.info.menuIndex >= menuList.length) {
|
|
95
|
-
throw new Error("props.info.menuIndex is out of range");
|
|
96
|
-
}
|
|
97
|
-
this._menuList = menuList;
|
|
98
|
-
const runtimeView = createRuntimeView(ocClassName, menuList);
|
|
37
|
+
this._ocClassName = classname || `DynamicContextMenuView_${cvid.newId}`;
|
|
38
|
+
this.generateContextMenu = generateContextMenu;
|
|
39
|
+
const runtimeView = this.createRuntimeView();
|
|
99
40
|
this._defineView = () => {
|
|
100
41
|
return {
|
|
101
42
|
type: "runtime",
|
|
@@ -111,15 +52,48 @@ export class DynamicContextMenuView extends Base<UILabelView, UiTypes.RuntimeOpt
|
|
|
111
52
|
}
|
|
112
53
|
}
|
|
113
54
|
|
|
114
|
-
|
|
115
|
-
if (
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
55
|
+
private defineOCClass() {
|
|
56
|
+
if (RegisteredOCClassName.has(this._ocClassName)) return;
|
|
57
|
+
RegisteredOCClassName.add(this._ocClassName);
|
|
58
|
+
$define({
|
|
59
|
+
type: this._ocClassName + " : UIView <UIContextMenuInteractionDelegate>",
|
|
60
|
+
events: {
|
|
61
|
+
"contextMenuInteraction:configurationForMenuAtLocation:": (interacton: any, point: JBPoint) => {
|
|
62
|
+
const view = interacton.$view().jsValue()
|
|
63
|
+
const menu = this.generateContextMenu(view);
|
|
64
|
+
return this.createContextMenuConfiguration(menu);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
})
|
|
120
68
|
}
|
|
121
69
|
|
|
122
|
-
|
|
123
|
-
return
|
|
70
|
+
private createContextMenuConfiguration({ title, items }: { title: string, items: MenuItem[] }) {
|
|
71
|
+
return $objc("UIContextMenuConfiguration").$configurationWithIdentifier_previewProvider_actionProvider(
|
|
72
|
+
null,
|
|
73
|
+
null,
|
|
74
|
+
$block("UIMenu *, NSArray *", () => {
|
|
75
|
+
const actions = items.map(item => {
|
|
76
|
+
const action = $objc("UIAction").$actionWithTitle_image_identifier_handler(
|
|
77
|
+
item.title,
|
|
78
|
+
item.symbol,
|
|
79
|
+
null,
|
|
80
|
+
$block("void, UIAction *", () => item.handler())
|
|
81
|
+
);
|
|
82
|
+
if (item.destructive) action.$setAttributes(1 << 1);
|
|
83
|
+
return action;
|
|
84
|
+
})
|
|
85
|
+
return $objc("UIMenu").$menuWithTitle_children(title, actions);
|
|
86
|
+
})
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
private createRuntimeView() {
|
|
91
|
+
this.defineOCClass();
|
|
92
|
+
const view = $objc(this._ocClassName).invoke("alloc.init");
|
|
93
|
+
const interaction = $objc("UIContextMenuInteraction")
|
|
94
|
+
.invoke("alloc")
|
|
95
|
+
.invoke("initWithDelegate", view);
|
|
96
|
+
view.$addInteraction(interaction);
|
|
97
|
+
return view;
|
|
124
98
|
}
|
|
125
99
|
}
|
|
@@ -2,75 +2,24 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DynamicContextMenuView = void 0;
|
|
4
4
|
const base_1 = require("./base");
|
|
5
|
+
const cvid_1 = require("../utils/cvid");
|
|
5
6
|
const RegisteredOCClassName = new Set();
|
|
6
|
-
function defineOCClass({ classname, menuList }) {
|
|
7
|
-
if (RegisteredOCClassName.has(classname))
|
|
8
|
-
return;
|
|
9
|
-
RegisteredOCClassName.add(classname);
|
|
10
|
-
$define({
|
|
11
|
-
type: classname + " : UIView <UIContextMenuInteractionDelegate>",
|
|
12
|
-
events: {
|
|
13
|
-
"contextMenuInteraction:configurationForMenuAtLocation:": (interacton, point) => {
|
|
14
|
-
var _a, _b;
|
|
15
|
-
console.log(interacton.$view().jsValue().info);
|
|
16
|
-
const menuIndex = ((_b = (_a = interacton.$view().jsValue().info) === null || _a === void 0 ? void 0 : _a.menuIndex) !== null && _b !== void 0 ? _b : 0);
|
|
17
|
-
if (menuIndex < 0 || menuIndex >= menuList.length)
|
|
18
|
-
return;
|
|
19
|
-
return createContextMenuConfiguration(menuList[menuIndex]);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
function createUIAction(item) {
|
|
25
|
-
const action = $objc("UIAction").$actionWithTitle_image_identifier_handler(item.title, item.symbol, null, $block("void, UIAction *", () => item.handler()));
|
|
26
|
-
if (item.destructive)
|
|
27
|
-
action.$setAttributes(1 << 1);
|
|
28
|
-
return action;
|
|
29
|
-
}
|
|
30
|
-
;
|
|
31
|
-
function createContextMenuConfiguration({ title, items }) {
|
|
32
|
-
return $objc("UIContextMenuConfiguration").$configurationWithIdentifier_previewProvider_actionProvider(null, null, $block("UIMenu *, NSArray *", () => {
|
|
33
|
-
const actions = items.map(item => createUIAction(item));
|
|
34
|
-
return $objc("UIMenu").$menuWithTitle_children(title, actions);
|
|
35
|
-
}));
|
|
36
|
-
}
|
|
37
|
-
function createRuntimeView(classname, menuList) {
|
|
38
|
-
defineOCClass({ classname, menuList });
|
|
39
|
-
const view = $objc(classname).invoke("alloc.init");
|
|
40
|
-
const interaction = $objc("UIContextMenuInteraction")
|
|
41
|
-
.invoke("alloc")
|
|
42
|
-
.invoke("initWithDelegate", view);
|
|
43
|
-
view.$addInteraction(interaction);
|
|
44
|
-
return view;
|
|
45
|
-
}
|
|
46
7
|
/**
|
|
47
8
|
* 动态上下文菜单视图,此视图是为了弥补JSBox中无法动态调整上下文菜单的缺陷而设计的。
|
|
48
9
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
* 这和menuList是配套的,同一套menuList用同一个类名。
|
|
55
|
-
* 2. menuList: { title: string; items: MenuItem[] }[] 菜单列表,每个菜单项包含一个标题和一个MenuItem数组。
|
|
56
|
-
* 3. props.info: { menuIndex: number } 用于指定当前视图的菜单索引,从0开始。info中可以包含其他参数。
|
|
10
|
+
* 此视图除了一般UIView的props, layout, events, views四个参数外,还有必须的特殊参数:
|
|
11
|
+
* 1. classname?: string OC类名,如果不指定则会自动生成一个唯一的类名。
|
|
12
|
+
* 如果有不同的DynamicContextMenuView实例使用相同的OC类,那么无法确定弹出的contextMenu是绑定了哪个实例。换言之,实例A弹出的Menu可能是绑定的实例B。
|
|
13
|
+
* 如果这样做,必须使用下面generateContextMenu的sender参数来定位。
|
|
14
|
+
* 2. generateContextMenu: (sender: UIView) => { title: string; items: MenuItem[]; } 生成上下文菜单的回调函数。
|
|
57
15
|
*
|
|
58
16
|
*/
|
|
59
17
|
class DynamicContextMenuView extends base_1.Base {
|
|
60
|
-
constructor({
|
|
61
|
-
var _a, _b;
|
|
18
|
+
constructor({ classname, generateContextMenu, props, layout, events, views }) {
|
|
62
19
|
super();
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (typeof props.info.menuIndex !== "number") {
|
|
67
|
-
throw new Error("props.info.menuIndex must be a number");
|
|
68
|
-
}
|
|
69
|
-
if (props.info.menuIndex < 0 || props.info.menuIndex >= menuList.length) {
|
|
70
|
-
throw new Error("props.info.menuIndex is out of range");
|
|
71
|
-
}
|
|
72
|
-
this._menuList = menuList;
|
|
73
|
-
const runtimeView = createRuntimeView(ocClassName, menuList);
|
|
20
|
+
this._ocClassName = classname || `DynamicContextMenuView_${cvid_1.cvid.newId}`;
|
|
21
|
+
this.generateContextMenu = generateContextMenu;
|
|
22
|
+
const runtimeView = this.createRuntimeView();
|
|
74
23
|
this._defineView = () => {
|
|
75
24
|
return {
|
|
76
25
|
type: "runtime",
|
|
@@ -81,15 +30,40 @@ class DynamicContextMenuView extends base_1.Base {
|
|
|
81
30
|
};
|
|
82
31
|
};
|
|
83
32
|
}
|
|
84
|
-
|
|
85
|
-
if (
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
33
|
+
defineOCClass() {
|
|
34
|
+
if (RegisteredOCClassName.has(this._ocClassName))
|
|
35
|
+
return;
|
|
36
|
+
RegisteredOCClassName.add(this._ocClassName);
|
|
37
|
+
$define({
|
|
38
|
+
type: this._ocClassName + " : UIView <UIContextMenuInteractionDelegate>",
|
|
39
|
+
events: {
|
|
40
|
+
"contextMenuInteraction:configurationForMenuAtLocation:": (interacton, point) => {
|
|
41
|
+
const view = interacton.$view().jsValue();
|
|
42
|
+
const menu = this.generateContextMenu(view);
|
|
43
|
+
return this.createContextMenuConfiguration(menu);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
createContextMenuConfiguration({ title, items }) {
|
|
49
|
+
return $objc("UIContextMenuConfiguration").$configurationWithIdentifier_previewProvider_actionProvider(null, null, $block("UIMenu *, NSArray *", () => {
|
|
50
|
+
const actions = items.map(item => {
|
|
51
|
+
const action = $objc("UIAction").$actionWithTitle_image_identifier_handler(item.title, item.symbol, null, $block("void, UIAction *", () => item.handler()));
|
|
52
|
+
if (item.destructive)
|
|
53
|
+
action.$setAttributes(1 << 1);
|
|
54
|
+
return action;
|
|
55
|
+
});
|
|
56
|
+
return $objc("UIMenu").$menuWithTitle_children(title, actions);
|
|
57
|
+
}));
|
|
90
58
|
}
|
|
91
|
-
|
|
92
|
-
|
|
59
|
+
createRuntimeView() {
|
|
60
|
+
this.defineOCClass();
|
|
61
|
+
const view = $objc(this._ocClassName).invoke("alloc.init");
|
|
62
|
+
const interaction = $objc("UIContextMenuInteraction")
|
|
63
|
+
.invoke("alloc")
|
|
64
|
+
.invoke("initWithDelegate", view);
|
|
65
|
+
view.$addInteraction(interaction);
|
|
66
|
+
return view;
|
|
93
67
|
}
|
|
94
68
|
}
|
|
95
69
|
exports.DynamicContextMenuView = DynamicContextMenuView;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const dynamic_contextmenu_view_1 = require("../components/dynamic-contextmenu-view");
|
|
4
|
+
let menuIndex = 0;
|
|
4
5
|
const menuList = [
|
|
5
6
|
{
|
|
6
7
|
title: "菜单1",
|
|
@@ -9,7 +10,7 @@ const menuList = [
|
|
|
9
10
|
title: "变成菜单1",
|
|
10
11
|
symbol: "plus",
|
|
11
12
|
handler: () => {
|
|
12
|
-
|
|
13
|
+
menuIndex = 0;
|
|
13
14
|
}
|
|
14
15
|
},
|
|
15
16
|
{
|
|
@@ -17,7 +18,7 @@ const menuList = [
|
|
|
17
18
|
symbol: "plus",
|
|
18
19
|
destructive: true,
|
|
19
20
|
handler: () => {
|
|
20
|
-
|
|
21
|
+
menuIndex = 1;
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
24
|
]
|
|
@@ -29,27 +30,24 @@ const menuList = [
|
|
|
29
30
|
title: "变成菜单1",
|
|
30
31
|
symbol: "plus",
|
|
31
32
|
handler: () => {
|
|
32
|
-
|
|
33
|
+
menuIndex = 0;
|
|
33
34
|
}
|
|
34
35
|
},
|
|
35
36
|
{
|
|
36
37
|
title: "变成菜单2",
|
|
37
38
|
symbol: "plus",
|
|
38
39
|
handler: () => {
|
|
39
|
-
|
|
40
|
+
menuIndex = 1;
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
43
|
]
|
|
43
44
|
}
|
|
44
45
|
];
|
|
45
46
|
const view = new dynamic_contextmenu_view_1.DynamicContextMenuView({
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
props: {
|
|
49
|
-
info: {
|
|
50
|
-
menuIndex: 0
|
|
51
|
-
}
|
|
47
|
+
generateContextMenu: (sender) => {
|
|
48
|
+
return menuList[menuIndex];
|
|
52
49
|
},
|
|
50
|
+
props: {},
|
|
53
51
|
layout: (make, view) => {
|
|
54
52
|
make.center.equalTo(view.super);
|
|
55
53
|
make.size.equalTo($size(100, 100));
|
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { DynamicContextMenuView } from "../components/dynamic-contextmenu-view";
|
|
2
2
|
|
|
3
|
+
let menuIndex = 0;
|
|
3
4
|
const menuList = [
|
|
4
5
|
{
|
|
5
6
|
title: "菜单1",
|
|
@@ -8,7 +9,7 @@ const menuList = [
|
|
|
8
9
|
title: "变成菜单1",
|
|
9
10
|
symbol: "plus",
|
|
10
11
|
handler: () => {
|
|
11
|
-
|
|
12
|
+
menuIndex = 0;
|
|
12
13
|
}
|
|
13
14
|
},
|
|
14
15
|
{
|
|
@@ -16,7 +17,7 @@ const menuList = [
|
|
|
16
17
|
symbol: "plus",
|
|
17
18
|
destructive: true,
|
|
18
19
|
handler: () => {
|
|
19
|
-
|
|
20
|
+
menuIndex = 1;
|
|
20
21
|
}
|
|
21
22
|
}
|
|
22
23
|
]
|
|
@@ -28,14 +29,14 @@ const menuList = [
|
|
|
28
29
|
title: "变成菜单1",
|
|
29
30
|
symbol: "plus",
|
|
30
31
|
handler: () => {
|
|
31
|
-
|
|
32
|
+
menuIndex = 0;
|
|
32
33
|
}
|
|
33
34
|
},
|
|
34
35
|
{
|
|
35
36
|
title: "变成菜单2",
|
|
36
37
|
symbol: "plus",
|
|
37
38
|
handler: () => {
|
|
38
|
-
|
|
39
|
+
menuIndex = 1;
|
|
39
40
|
}
|
|
40
41
|
}
|
|
41
42
|
]
|
|
@@ -43,13 +44,10 @@ const menuList = [
|
|
|
43
44
|
]
|
|
44
45
|
|
|
45
46
|
const view = new DynamicContextMenuView({
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
props: {
|
|
49
|
-
info: {
|
|
50
|
-
menuIndex: 0
|
|
51
|
-
}
|
|
47
|
+
generateContextMenu: (sender) => {
|
|
48
|
+
return menuList[menuIndex]
|
|
52
49
|
},
|
|
50
|
+
props: {},
|
|
53
51
|
layout: (make, view) => {
|
|
54
52
|
make.center.equalTo(view.super);
|
|
55
53
|
make.size.equalTo($size(100, 100));
|