@react-native-ohos/react-native-context-menu-view 1.16.1-rc.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.
Files changed (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.OpenSource +11 -0
  3. package/README.md +13 -0
  4. package/harmony/context_menu/BuildProfile.ets +17 -0
  5. package/harmony/context_menu/build-profile.json5 +12 -0
  6. package/harmony/context_menu/hvigorfile.ts +2 -0
  7. package/harmony/context_menu/index.ets +28 -0
  8. package/harmony/context_menu/oh-package.json5 +12 -0
  9. package/harmony/context_menu/src/main/cpp/CMakeLists.txt +8 -0
  10. package/harmony/context_menu/src/main/cpp/ComponentDescriptors.h +18 -0
  11. package/harmony/context_menu/src/main/cpp/ContextMenuJSIBinder.h +58 -0
  12. package/harmony/context_menu/src/main/cpp/ContextMenuPackage.h +140 -0
  13. package/harmony/context_menu/src/main/cpp/ContextMenuTurboModule.cpp +36 -0
  14. package/harmony/context_menu/src/main/cpp/ContextMenuTurboModule.h +38 -0
  15. package/harmony/context_menu/src/main/cpp/EventEmitters.cpp +49 -0
  16. package/harmony/context_menu/src/main/cpp/EventEmitters.h +41 -0
  17. package/harmony/context_menu/src/main/cpp/Props.cpp +33 -0
  18. package/harmony/context_menu/src/main/cpp/Props.h +115 -0
  19. package/harmony/context_menu/src/main/cpp/RTNContextMenuComponentInstance.cpp +286 -0
  20. package/harmony/context_menu/src/main/cpp/RTNContextMenuComponentInstance.h +165 -0
  21. package/harmony/context_menu/src/main/cpp/ShadowNodes.cpp +15 -0
  22. package/harmony/context_menu/src/main/cpp/ShadowNodes.h +30 -0
  23. package/harmony/context_menu/src/main/cpp/States.cpp +15 -0
  24. package/harmony/context_menu/src/main/cpp/States.h +34 -0
  25. package/harmony/context_menu/src/main/ets/ContextMenuLongPress.ets +374 -0
  26. package/harmony/context_menu/src/main/ets/ContextMenuLongPressWithNoSelect.ets +356 -0
  27. package/harmony/context_menu/src/main/ets/ContextMenuPackage.ets +48 -0
  28. package/harmony/context_menu/src/main/ets/ContextMenuThreeMenu.ets +224 -0
  29. package/harmony/context_menu/src/main/ets/ContextMenuThreeMenuWithNoSelect.ets +221 -0
  30. package/harmony/context_menu/src/main/ets/ContextMenuTurboModule.ets +293 -0
  31. package/harmony/context_menu/src/main/ets/ContextMenuTwoMenu.ets +209 -0
  32. package/harmony/context_menu/src/main/ets/ContextMenuTwoMenuWithNoSelect.ets +207 -0
  33. package/harmony/context_menu/src/main/ets/Logger.ets +64 -0
  34. package/harmony/context_menu/src/main/module.json5 +7 -0
  35. package/harmony/context_menu/src/main/resources/base/element/string.json +8 -0
  36. package/harmony/context_menu/src/main/resources/base/media/airplane_fill.png +0 -0
  37. package/harmony/context_menu/src/main/resources/base/media/background.png +0 -0
  38. package/harmony/context_menu/src/main/resources/base/media/foreground.png +0 -0
  39. package/harmony/context_menu/src/main/resources/base/media/layered_image.json +7 -0
  40. package/harmony/context_menu/src/main/resources/base/media/startIcon.png +0 -0
  41. package/harmony/context_menu/src/main/resources/base/profile/backup_config.json +3 -0
  42. package/harmony/context_menu/src/main/resources/base/profile/main_pages.json +5 -0
  43. package/harmony/context_menu/src/main/resources/en_US/element/string.json +8 -0
  44. package/harmony/context_menu/src/main/resources/zh_CN/element/string.json +8 -0
  45. package/harmony/context_menu/ts.ets +26 -0
  46. package/harmony/context_menu.har +0 -0
  47. package/index.js +44 -0
  48. package/package.json +49 -0
  49. package/react-native-context-menu-view.podspec +26 -0
  50. package/src/RTNContextMenuNativeComponent.ts +50 -0
@@ -0,0 +1,374 @@
1
+ /**
2
+ * MIT License
3
+ *
4
+ * Copyright (C) 2024 Huawei Device Co., Ltd.
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ * of this software and associated documentation files (the "Software"), to deal
8
+ * in the Software without restriction, including without limitation the rights
9
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ * copies of the Software, and to permit persons to whom the Software is
11
+ * furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice shall be included in all
14
+ * copies or substantial portions of the Software.
15
+ *
16
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
+ * SOFTWARE.
23
+ */
24
+
25
+ import { RNOHContext, } from '@rnoh/react-native-openharmony'
26
+ import Logger from './Logger';
27
+ import { SymbolGlyphModifier } from '@kit.ArkUI';
28
+ import { ContextMenuTwoMenu } from './ContextMenuTwoMenu';
29
+ import { ContextMenuTwoMenuWithNoSelect } from './ContextMenuTwoMenuWithNoSelect';
30
+
31
+ //这里的属性类型要和ContextMenuTurboModule.ets下的ContextMenuProps一致
32
+ interface ContextMenuProps {
33
+ tag?: number;
34
+ width?: number;
35
+ height?: number;
36
+ x?: number;
37
+ y?: number;
38
+ windowX?: number;
39
+ windowY?: number;
40
+ title?: string;
41
+ action?: string;
42
+ dropdownMenuMode?: boolean;
43
+ disabled?: boolean;
44
+ subtitle?: string;
45
+
46
+ // disabledArray?: Array<boolean>;
47
+ selected?: boolean;
48
+ previewBackgroundColor?: string;
49
+ actionsTitle?: string;
50
+ touchViewActions?: ContextMenuProps
51
+ ctx: RNOHContext
52
+ romWidth?: number;
53
+ romHeight?: number;
54
+ systemIcon?: string;
55
+ icon?: string;
56
+ destructive?: string
57
+ iconColor?: string;
58
+
59
+ //二级目录
60
+ inlineChildren?: boolean;
61
+ d_childActions?: ContextMenuProps;
62
+ childActionsTag?: number;
63
+
64
+ //2+目录
65
+ childActions?: ContextMenuProps;
66
+ }
67
+
68
+ @Component
69
+ export struct ContextMenuLongPress {
70
+ public static readonly NAME = "ContextMenuLongPress"
71
+ menuCtx!: RNOHContext;
72
+ menuTag: number = 0;
73
+ @State realViewPoint: Object = [];
74
+ @State listDate: ContextMenuProps[] = [];
75
+ @State menuTitle: string = '';
76
+ @State menuX: number = 0;
77
+ @State menuY: number = 0;
78
+ @State menuWidth: number = 0;
79
+ @State menuHeight: number = 0;
80
+ @State menuDisable: boolean = true;
81
+ @State menuRomWidth: number = 0;
82
+ @State menuRomHeight: number = 0;
83
+ @State menuWindowX: number = 0;
84
+ @State menuWindowY: number = 0;
85
+ @State menuIndexPath: number[] = [];
86
+ @State menuDestructive: string = '';
87
+ @State childActionsListDate: ESObject[] = [];
88
+ @State isTouch: boolean | undefined = false;
89
+ @State isTouchWithNoSelect: boolean | undefined = false;
90
+ @State isTouchViewNumber: number = 0;
91
+ @State isChildActionsTouchViewNumber: number = 0;
92
+ @State menuChildActions: ContextMenuProps[] = [];
93
+ @State menuChild: ESObject[] = [];
94
+ @State deepChildActions: ESObject[] = [];
95
+ @State isShow: boolean = false;
96
+ @State twoMenu: ESObject[] = [];
97
+ @State selectedFlag: number = 0;
98
+
99
+ aboutToAppear() {
100
+ let longPress: ESObject = this.realViewPoint;
101
+ //menu的大标题
102
+ this.menuTitle = longPress.title;
103
+ //获取menu的xy轴,以及view视图的长宽
104
+ this.menuX = longPress.x;
105
+ this.menuY = longPress.y;
106
+ this.menuWidth = longPress.width;
107
+ this.menuHeight = longPress.height;
108
+ this.menuCtx = longPress.ctx;
109
+ this.menuTag = longPress.tag;
110
+ //获取设备的长宽
111
+ this.menuRomWidth = longPress.romWidth;
112
+ this.menuRomHeight = longPress.romHeight;
113
+ //获取点击时候的点击事件的xy,基于屏幕左上角
114
+ this.menuWindowX = longPress.windowX;
115
+ this.menuWindowY = longPress.windowY;
116
+ this.listDate = longPress.touchViewActions;
117
+ //判断destructive(可破坏),默认false,表示不可破坏。
118
+ for (let i = 0; i < longPress.touchViewActions.length; i++) {
119
+ if (longPress.touchViewActions[i].destructive) {
120
+ //可破坏为红色
121
+ this.listDate[i].destructive = 'red';
122
+ } else {
123
+ //不可破坏为black
124
+ this.listDate[i].destructive = 'black';
125
+ }
126
+ }
127
+ // contextMenu入参为disabled,是否禁用选项,默认为false,表示不用禁用.
128
+ // 但是在harmony Next调用enable的入参,harmony Next:true = RN:false
129
+ for (let i = 0; i < longPress.touchViewActions.length; i++) {
130
+ if (longPress.touchViewActions[i].disabled) {
131
+ //为true,表示禁用,对应harmony next 的false
132
+ this.listDate[i].disabled = false;
133
+ } else {
134
+ //contextMenu的false 对标 harmony 的 true
135
+ this.listDate[i].disabled = true;
136
+ }
137
+ }
138
+ for (let i = 0; i < longPress.touchViewActions.length; i++) {
139
+ if (longPress.touchViewActions[i].selected) {
140
+ //复选框,默认为false
141
+ this.listDate[i].selected = true;
142
+ } else {
143
+ this.listDate[i].selected = false;
144
+ }
145
+ }
146
+
147
+ //遍历传递回前端的indexPath,indexPath只会计算子节点index
148
+ for (let i = 0; i < longPress.touchViewActions.length; i++) {
149
+ this.menuIndexPath[i] = i;
150
+ }
151
+
152
+ //二级目录,均和一级目录一致
153
+ // 遍历查询是否有二级目录
154
+ for (let i = 0; i < longPress.touchViewActions.length; i++) {
155
+ if (longPress.touchViewActions[i].d_childActions !== '' ||
156
+ longPress.touchViewActions[i].d_childActions !== undefined ||
157
+ longPress.touchViewActions[i].d_childActions !== null) {
158
+ //有二级菜单
159
+ this.childActionsListDate[i] = longPress.touchViewActions[i].d_childActions;
160
+ }
161
+ }
162
+ ;
163
+
164
+ for (let i = 0; i < this.childActionsListDate.length; i++) {
165
+ if (this.childActionsListDate[i] !== null && this.childActionsListDate[i] !== undefined &&
166
+ this.childActionsListDate[i] !== '') {
167
+ let j = i;
168
+ //默认为false,这里判断disabled
169
+ for (let k = 0; k < this.childActionsListDate[j].length; k++) {
170
+ this.menuIndexPath[k] = k;
171
+ if ((this.childActionsListDate[j])[k].disabled) {
172
+ (this.childActionsListDate[j])[k].disabled = false;
173
+ } else {
174
+ //contextMenu的false 对标 harmony 的 true
175
+ (this.childActionsListDate[j])[k].disabled = true;
176
+ }
177
+ if ((this.childActionsListDate[j])[k].selected) {
178
+ this.selectedFlag++;
179
+ }
180
+ }
181
+ }
182
+ }
183
+ }
184
+
185
+ //退出组件
186
+ aboutToDisappear() {
187
+ }
188
+
189
+ @Builder
190
+ twoMenuView() {
191
+ ContextMenuTwoMenu(
192
+ {
193
+ realViewPoint: this.twoMenu,
194
+ menuCtx: this.menuCtx,
195
+ menuTag: this.menuTag
196
+ });
197
+ }
198
+
199
+ @Builder
200
+ twoMenuViewWithNoSelect() {
201
+ ContextMenuTwoMenuWithNoSelect(
202
+ {
203
+ realViewPoint: this.twoMenu,
204
+ menuCtx: this.menuCtx,
205
+ menuTag: this.menuTag
206
+ });
207
+ }
208
+
209
+ build() {
210
+ Menu() {
211
+ MenuItemGroup({ header: this.menuTitle }) {
212
+ //遍历数据,把每个menuTitle塞入到对应的menu中
213
+ ForEach(this.listDate, (item: ContextMenuProps, index) => {
214
+ if (item.systemIcon) {
215
+ if (this.selectedFlag !== 0) {
216
+ MenuItem({
217
+ content: item.title,
218
+ symbolEndIcon: new SymbolGlyphModifier($r(item.systemIcon)).fontSize('24vp')
219
+ .fontColor([item.iconColor]),
220
+ labelInfo: item.subtitle,
221
+ })
222
+ .selected(item.selected)
223
+ .selectIcon(new SymbolGlyphModifier($r('sys.symbol.checkmark')).fontSize('24vp'))
224
+ .alignSelf(ItemAlign.Start)
225
+ .enabled(item.disabled)
226
+ .contentFontColor(item.destructive)
227
+ .onClick(() => {
228
+ //当item.inlineChildren默认为false,表示以二级目录展示
229
+ //true的时候,以同目录展示
230
+ this.isTouch = true && (!item.inlineChildren) && (item.d_childActions !== undefined);
231
+ this.isTouchWithNoSelect = this.isTouch && (this.selectedFlag == 0);
232
+ if (this.isTouchWithNoSelect && this.isTouch) {
233
+ this.isTouch = false;
234
+ }
235
+ this.isTouchViewNumber = index;
236
+ this.twoMenu = this.childActionsListDate[this.isTouchViewNumber]
237
+ console.log('2024touch:' + this.isTouch + ',' + 'inlineChildren:' + item.inlineChildren + ',' +
238
+ 'isTouchViewNumber:' + this.isTouchViewNumber);
239
+ //当item.inlineChildren默认为false,二级目录展示时候,点击一级目录,不关闭,在二级目录后关闭
240
+ //当item.inlineChildren为false的时候,就不需要关闭该窗口.
241
+ if (item.inlineChildren || (item.d_childActions == undefined)) {
242
+ this.menuCtx.rnInstance.postMessageToCpp('contextMenu::SET_NATIVE_RESPONDERS_BLOCK', {
243
+ itemTitle: item.title,
244
+ itemTag: this.menuTag,
245
+ itemIndex: index,
246
+ itemIndexPath: [0],
247
+ itemInlineChildren: item.inlineChildren
248
+ });
249
+ }
250
+ })//弹框,通过inlineChildren来判定是否有二级目录,ture有二级目录
251
+ .bindContextMenu(this.isTouch, this.twoMenuView())
252
+ } else {
253
+ MenuItem({
254
+ content: item.title,
255
+ symbolEndIcon: new SymbolGlyphModifier($r(item.systemIcon)).fontSize('24vp')
256
+ .fontColor([item.iconColor]),
257
+ labelInfo: item.subtitle,
258
+ })
259
+ .selected(item.selected)
260
+ .selectIcon(new SymbolGlyphModifier($r('sys.symbol.checkmark')).fontSize('24vp'))
261
+ .alignSelf(ItemAlign.Start)
262
+ .enabled(item.disabled)
263
+ .contentFontColor(item.destructive)
264
+ .onClick(() => {
265
+ //当item.inlineChildren默认为false,表示以二级目录展示
266
+ //true的时候,以同目录展示
267
+ this.isTouch = true && (!item.inlineChildren) && (item.d_childActions !== undefined);
268
+ this.isTouchWithNoSelect = this.isTouch && (this.selectedFlag == 0);
269
+ if (this.isTouchWithNoSelect && this.isTouch) {
270
+ this.isTouch = false;
271
+ }
272
+ this.isTouchViewNumber = index;
273
+ this.twoMenu = this.childActionsListDate[this.isTouchViewNumber]
274
+ console.log('2024touch:' + this.isTouch + ',' + 'inlineChildren:' + item.inlineChildren + ',' +
275
+ 'isTouchViewNumber:' + this.isTouchViewNumber);
276
+ //当item.inlineChildren默认为false,二级目录展示时候,点击一级目录,不关闭,在二级目录后关闭
277
+ //当item.inlineChildren为false的时候,就不需要关闭该窗口.
278
+ if (item.inlineChildren || (item.d_childActions == undefined)) {
279
+ this.menuCtx.rnInstance.postMessageToCpp('contextMenu::SET_NATIVE_RESPONDERS_BLOCK', {
280
+ itemTitle: item.title,
281
+ itemTag: this.menuTag,
282
+ itemIndex: index,
283
+ itemIndexPath: [0],
284
+ itemInlineChildren: item.inlineChildren
285
+ });
286
+ }
287
+ })//弹框,通过inlineChildren来判定是否有二级目录,ture有二级目录
288
+ .bindContextMenu(this.isTouchWithNoSelect, this.twoMenuViewWithNoSelect())
289
+ }
290
+ } else {
291
+ //如果没有systemIcon,则走自定义图标
292
+ if (this.selectedFlag !== 0) {
293
+ MenuItem({
294
+ content: item.title,
295
+ endIcon: $r(item.icon),
296
+ labelInfo: item.subtitle,
297
+ })
298
+ .selected(item.selected)
299
+ .selectIcon(new SymbolGlyphModifier($r('sys.symbol.checkmark')).fontSize('24vp'))
300
+ .alignSelf(ItemAlign.Start)
301
+ .enabled(item.disabled)
302
+ .contentFontColor(item.destructive)
303
+ .onClick(() => {
304
+ //当item.inlineChildren默认为false,表示以二级目录展示
305
+ //true的时候,以同目录展示
306
+ this.isTouch = true && (!item.inlineChildren) && (item.d_childActions !== undefined);
307
+ this.isTouchWithNoSelect = this.isTouch && (this.selectedFlag == 0);
308
+ if (this.isTouchWithNoSelect && this.isTouch) {
309
+ this.isTouch = false;
310
+ }
311
+ this.isTouchViewNumber = index;
312
+ this.twoMenu = this.childActionsListDate[this.isTouchViewNumber]
313
+ console.log('2024touch:' + this.isTouch + ',' + 'inlineChildren:' + item.inlineChildren + ',' +
314
+ 'isTouchViewNumber:' + this.isTouchViewNumber);
315
+ //当item.inlineChildren默认为false,二级目录展示时候,点击一级目录,不关闭,在二级目录后关闭
316
+ //当item.inlineChildren为false的时候,就不需要关闭该窗口.
317
+ if (item.inlineChildren || (item.d_childActions == undefined)) {
318
+ this.menuCtx.rnInstance.postMessageToCpp('contextMenu::SET_NATIVE_RESPONDERS_BLOCK', {
319
+ itemTitle: item.title,
320
+ itemTag: this.menuTag,
321
+ itemIndex: index,
322
+ itemIndexPath: [0],
323
+ itemInlineChildren: item.inlineChildren
324
+ });
325
+ }
326
+ })//弹框,通过inlineChildren来判定是否有二级目录,ture有二级目录
327
+ .bindContextMenu(this.isTouch, this.twoMenuView())
328
+ } else {
329
+ MenuItem({
330
+ content: item.title,
331
+ endIcon: $r(item.icon),
332
+ labelInfo: item.subtitle,
333
+ })
334
+ .selected(item.selected)
335
+ .selectIcon(new SymbolGlyphModifier($r('sys.symbol.checkmark')).fontSize('24vp'))
336
+ .alignSelf(ItemAlign.Start)
337
+ .enabled(item.disabled)
338
+ .contentFontColor(item.destructive)
339
+ .onClick(() => {
340
+ //当item.inlineChildren默认为false,表示以二级目录展示
341
+ //true的时候,以同目录展示
342
+ this.isTouch = true && (!item.inlineChildren) && (item.d_childActions !== undefined);
343
+ this.isTouchWithNoSelect = this.isTouch && (this.selectedFlag == 0);
344
+ if (this.isTouchWithNoSelect && this.isTouch) {
345
+ this.isTouch = false;
346
+ }
347
+ this.isTouchViewNumber = index;
348
+ this.twoMenu = this.childActionsListDate[this.isTouchViewNumber]
349
+ console.log('2024touch:' + this.isTouch + ',' + 'inlineChildren:' + item.inlineChildren + ',' +
350
+ 'isTouchViewNumber:' + this.isTouchViewNumber);
351
+ //当item.inlineChildren默认为false,二级目录展示时候,点击一级目录,不关闭,在二级目录后关闭
352
+ //当item.inlineChildren为false的时候,就不需要关闭该窗口.
353
+ if (item.inlineChildren || (item.d_childActions == undefined)) {
354
+ this.menuCtx.rnInstance.postMessageToCpp('contextMenu::SET_NATIVE_RESPONDERS_BLOCK', {
355
+ itemTitle: item.title,
356
+ itemTag: this.menuTag,
357
+ itemIndex: index,
358
+ itemIndexPath: [0],
359
+ itemInlineChildren: item.inlineChildren
360
+ });
361
+ }
362
+ })//弹框,通过inlineChildren来判定是否有二级目录,ture有二级目录
363
+ .bindContextMenu(this.isTouchWithNoSelect, this.twoMenuViewWithNoSelect())
364
+ }
365
+ }
366
+ })
367
+ }.backgroundColor('white')
368
+ }.onDisAppear(() => {
369
+ this.menuCtx.rnInstance.postMessageToCpp('contextMenu::onCancel', {
370
+ itemTag: this.menuTag,
371
+ });
372
+ })
373
+ }
374
+ }