@react-native-ohos/react-native-context-menu-view 1.19.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.
- package/LICENSE +21 -0
- package/README.OpenSource +11 -0
- package/README.md +13 -0
- package/harmony/context_menu/BuildProfile.ets +17 -0
- package/harmony/context_menu/build-profile.json5 +9 -0
- package/harmony/context_menu/hvigorfile.ts +2 -0
- package/harmony/context_menu/index.ets +26 -0
- package/harmony/context_menu/oh-package.json5 +12 -0
- package/harmony/context_menu/src/main/cpp/CMakeLists.txt +8 -0
- package/harmony/context_menu/src/main/cpp/ComponentDescriptors.h +18 -0
- package/harmony/context_menu/src/main/cpp/ContextMenuJSIBinder.h +59 -0
- package/harmony/context_menu/src/main/cpp/ContextMenuPackage.h +140 -0
- package/harmony/context_menu/src/main/cpp/ContextMenuTurboModule.cpp +36 -0
- package/harmony/context_menu/src/main/cpp/ContextMenuTurboModule.h +38 -0
- package/harmony/context_menu/src/main/cpp/EventEmitters.cpp +49 -0
- package/harmony/context_menu/src/main/cpp/EventEmitters.h +41 -0
- package/harmony/context_menu/src/main/cpp/Props.cpp +34 -0
- package/harmony/context_menu/src/main/cpp/Props.h +121 -0
- package/harmony/context_menu/src/main/cpp/RTNContextMenuComponentInstance.cpp +290 -0
- package/harmony/context_menu/src/main/cpp/RTNContextMenuComponentInstance.h +168 -0
- package/harmony/context_menu/src/main/cpp/ShadowNodes.cpp +15 -0
- package/harmony/context_menu/src/main/cpp/ShadowNodes.h +30 -0
- package/harmony/context_menu/src/main/cpp/States.cpp +15 -0
- package/harmony/context_menu/src/main/cpp/States.h +34 -0
- package/harmony/context_menu/src/main/ets/ContextMenuLongPress.ets +393 -0
- package/harmony/context_menu/src/main/ets/ContextMenuLongPressWithNoSelect.ets +375 -0
- package/harmony/context_menu/src/main/ets/ContextMenuPackage.ets +47 -0
- package/harmony/context_menu/src/main/ets/ContextMenuThreeMenu.ets +225 -0
- package/harmony/context_menu/src/main/ets/ContextMenuThreeMenuWithNoSelect.ets +222 -0
- package/harmony/context_menu/src/main/ets/ContextMenuTurboModule.ets +297 -0
- package/harmony/context_menu/src/main/ets/ContextMenuTwoMenu.ets +210 -0
- package/harmony/context_menu/src/main/ets/ContextMenuTwoMenuWithNoSelect.ets +208 -0
- package/harmony/context_menu/src/main/ets/Logger.ets +64 -0
- package/harmony/context_menu/src/main/module.json5 +7 -0
- package/harmony/context_menu/src/main/resources/base/element/string.json +8 -0
- package/harmony/context_menu/src/main/resources/base/media/airplane_fill.png +0 -0
- package/harmony/context_menu/src/main/resources/base/media/background.png +0 -0
- package/harmony/context_menu/src/main/resources/base/media/foreground.png +0 -0
- package/harmony/context_menu/src/main/resources/base/media/layered_image.json +7 -0
- package/harmony/context_menu/src/main/resources/base/media/startIcon.png +0 -0
- package/harmony/context_menu/src/main/resources/base/profile/backup_config.json +3 -0
- package/harmony/context_menu/src/main/resources/base/profile/main_pages.json +5 -0
- package/harmony/context_menu/src/main/resources/en_US/element/string.json +8 -0
- package/harmony/context_menu/src/main/resources/zh_CN/element/string.json +8 -0
- package/harmony/context_menu/ts.ets +26 -0
- package/harmony/context_menu.har +0 -0
- package/index.js +44 -0
- package/package.json +39 -0
- package/react-native-context-menu-view.podspec +26 -0
- package/src/RTNContextMenuNativeComponent.ts +50 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved
|
|
3
|
+
* Use of this source code is governed by a MIT license that can be
|
|
4
|
+
* found in the LICENSE file.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
#pragma once
|
|
8
|
+
|
|
9
|
+
#include <react/renderer/components/view/ViewProps.h>
|
|
10
|
+
#include <react/renderer/core/PropsParserContext.h>
|
|
11
|
+
#include <react/renderer/core/propsConversions.h>
|
|
12
|
+
#include <react/renderer/graphics/Color.h>
|
|
13
|
+
#include <vector>
|
|
14
|
+
|
|
15
|
+
namespace facebook {
|
|
16
|
+
namespace react {
|
|
17
|
+
|
|
18
|
+
struct RTNContextMenuActionsStruct {
|
|
19
|
+
std::string title;
|
|
20
|
+
std::string titleColor;
|
|
21
|
+
std::string subtitle = "";
|
|
22
|
+
std::string systemIcon;
|
|
23
|
+
std::string icon;
|
|
24
|
+
std::string iconColor;
|
|
25
|
+
bool destructive = false;
|
|
26
|
+
bool selected = false;
|
|
27
|
+
bool disabled = false;
|
|
28
|
+
bool inlineChildren = false;
|
|
29
|
+
std::vector<RTNContextMenuActionsStruct> actions;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
static inline void fromRawValue(const PropsParserContext &context, const RawValue &value,
|
|
33
|
+
RTNContextMenuActionsStruct &result) {
|
|
34
|
+
auto map = (std::unordered_map<std::string, RawValue>)value;
|
|
35
|
+
|
|
36
|
+
auto tmp_title = map.find("title");
|
|
37
|
+
if (tmp_title != map.end()) {
|
|
38
|
+
fromRawValue(context, tmp_title->second, result.title);
|
|
39
|
+
}
|
|
40
|
+
auto tmp_titleColor = map.find("titleColor");
|
|
41
|
+
if (tmp_titleColor != map.end()) {
|
|
42
|
+
fromRawValue(context, tmp_titleColor->second, result.titleColor);
|
|
43
|
+
}
|
|
44
|
+
auto tmp_subtitle = map.find("subtitle");
|
|
45
|
+
if (tmp_subtitle != map.end()) {
|
|
46
|
+
fromRawValue(context, tmp_subtitle->second, result.subtitle);
|
|
47
|
+
}
|
|
48
|
+
auto tmp_systemIcon = map.find("systemIcon");
|
|
49
|
+
if (tmp_systemIcon != map.end()) {
|
|
50
|
+
fromRawValue(context, tmp_systemIcon->second, result.systemIcon);
|
|
51
|
+
}
|
|
52
|
+
auto tmp_icon = map.find("icon");
|
|
53
|
+
if (tmp_icon != map.end()) {
|
|
54
|
+
fromRawValue(context, tmp_icon->second, result.icon);
|
|
55
|
+
}
|
|
56
|
+
auto tmp_iconColor = map.find("iconColor");
|
|
57
|
+
if (tmp_iconColor != map.end()) {
|
|
58
|
+
fromRawValue(context, tmp_iconColor->second, result.iconColor);
|
|
59
|
+
}
|
|
60
|
+
auto tmp_destructive = map.find("destructive");
|
|
61
|
+
if (tmp_destructive != map.end()) {
|
|
62
|
+
fromRawValue(context, tmp_destructive->second, result.destructive);
|
|
63
|
+
}
|
|
64
|
+
auto tmp_selected = map.find("selected");
|
|
65
|
+
if (tmp_selected != map.end()) {
|
|
66
|
+
fromRawValue(context, tmp_selected->second, result.selected);
|
|
67
|
+
}
|
|
68
|
+
auto tmp_disabled = map.find("disabled");
|
|
69
|
+
if (tmp_disabled != map.end()) {
|
|
70
|
+
fromRawValue(context, tmp_disabled->second, result.disabled);
|
|
71
|
+
}
|
|
72
|
+
auto tmp_inlineChildren = map.find("inlineChildren");
|
|
73
|
+
if (tmp_inlineChildren != map.end()) {
|
|
74
|
+
fromRawValue(context, tmp_inlineChildren->second, result.inlineChildren);
|
|
75
|
+
}
|
|
76
|
+
auto tmp_actions = map.find("actions");
|
|
77
|
+
if (tmp_actions != map.end()) {
|
|
78
|
+
fromRawValue(context, tmp_actions->second, result.actions);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
static inline std::string toString(const RTNContextMenuActionsStruct &value) {
|
|
83
|
+
return "[Object RTNContextMenuActionsStruct]";
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
static inline void fromRawValue(const PropsParserContext &context, const RawValue &value,
|
|
87
|
+
std::vector<RTNContextMenuActionsStruct> &result) {
|
|
88
|
+
auto items = (std::vector<RawValue>)value;
|
|
89
|
+
for (const auto &item : items) {
|
|
90
|
+
RTNContextMenuActionsStruct newItem;
|
|
91
|
+
fromRawValue(context, item, newItem);
|
|
92
|
+
result.emplace_back(newItem);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Props的定义域
|
|
97
|
+
class JSI_EXPORT RTNContextMenuProps final : public ViewProps {
|
|
98
|
+
public:
|
|
99
|
+
RTNContextMenuProps() = default;
|
|
100
|
+
RTNContextMenuProps(const PropsParserContext &context, const RTNContextMenuProps &sourceProps,
|
|
101
|
+
const RawProps &rawProps);
|
|
102
|
+
|
|
103
|
+
#pragma mark - Props
|
|
104
|
+
|
|
105
|
+
std::string title{};
|
|
106
|
+
std::vector<RTNContextMenuActionsStruct> actions{};
|
|
107
|
+
std::string previewBackgroundColor{};
|
|
108
|
+
bool dropdownMenuMode{};
|
|
109
|
+
bool disabled{};
|
|
110
|
+
std::string subtitle{};
|
|
111
|
+
std::string systemIcon{};
|
|
112
|
+
std::string icon{};
|
|
113
|
+
std::string iconColor{};
|
|
114
|
+
bool destructive{};
|
|
115
|
+
bool selected{};
|
|
116
|
+
bool inlineChildren{};
|
|
117
|
+
std::string fontName{};
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
} // namespace react
|
|
121
|
+
} // namespace facebook
|
|
@@ -0,0 +1,290 @@
|
|
|
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
|
+
#include "RTNContextMenuComponentInstance.h"
|
|
26
|
+
#include "Props.h"
|
|
27
|
+
#import "RNOH/arkui/StackNode.h"
|
|
28
|
+
#include <iostream>
|
|
29
|
+
#include <vector>
|
|
30
|
+
|
|
31
|
+
namespace rnoh {
|
|
32
|
+
|
|
33
|
+
RTNContextMenuComponentInstance::RTNContextMenuComponentInstance(Context context)
|
|
34
|
+
: CppComponentInstance(std::move(context)) {
|
|
35
|
+
// 单点事件
|
|
36
|
+
// m_contextMenuNode.setCustomNodeDelegate(this);
|
|
37
|
+
// 查看node生效的范围
|
|
38
|
+
// m_contextMenuNode.setBackgroundColor(facebook::react::SharedColor(0xff7700ff));
|
|
39
|
+
m_contextMenuNode.setStackNodeDelegate(this);
|
|
40
|
+
ArkUINodeRegistry::getInstance().registerTouchHandler(&m_contextMenuNode, this);
|
|
41
|
+
NativeNodeApi::getInstance()->registerNodeEvent(m_contextMenuNode.getArkUINodeHandle(), NODE_TOUCH_EVENT,
|
|
42
|
+
NODE_TOUCH_EVENT, 0);
|
|
43
|
+
auto rnInstance = m_deps->rnInstance.lock();
|
|
44
|
+
if (rnInstance) {
|
|
45
|
+
// postMessageToArkTS,创建组件发送消息
|
|
46
|
+
rnInstance->postMessageToArkTS("RNGH::ROOT_CREATED", m_tag);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
RTNContextMenuComponentInstance::~RTNContextMenuComponentInstance() {
|
|
51
|
+
NativeNodeApi::getInstance()->unregisterNodeEvent(m_contextMenuNode.getArkUINodeHandle(), NODE_TOUCH_EVENT);
|
|
52
|
+
ArkUINodeRegistry::getInstance().unregisterTouchHandler(&m_contextMenuNode);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
std::optional<std::string> RTNContextMenuComponentInstance::getTintColorFromDynamic(folly::dynamic value) {
|
|
56
|
+
auto rawPropsColor =
|
|
57
|
+
(value.count("backgroundColor") > 0) ? std::optional(value["backgroundColor"].asString()) : std::nullopt;
|
|
58
|
+
return rawPropsColor;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
void RTNContextMenuComponentInstance::onChildInserted(ComponentInstance::Shared const &childComponentInstance,
|
|
62
|
+
std::size_t index) {
|
|
63
|
+
// 添加子节点,rn框架自带
|
|
64
|
+
CppComponentInstance::onChildInserted(childComponentInstance, index);
|
|
65
|
+
m_contextMenuNode.insertChild(childComponentInstance->getLocalRootArkUINode(), index + 1);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
void RTNContextMenuComponentInstance::onChildRemoved(ComponentInstance::Shared const &childComponentInstance) {
|
|
69
|
+
// 删子节点,rn框架自带
|
|
70
|
+
CppComponentInstance::onChildRemoved(childComponentInstance);
|
|
71
|
+
m_contextMenuNode.removeChild(childComponentInstance->getLocalRootArkUINode());
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
void RTNContextMenuComponentInstance::onPropsChanged(SharedConcreteProps const &props) {
|
|
75
|
+
CppComponentInstance::onPropsChanged(props);
|
|
76
|
+
if (auto p = std::dynamic_pointer_cast<const facebook::react::RTNContextMenuProps>(props)) {
|
|
77
|
+
this->title = props->title;
|
|
78
|
+
this->dropdownMenuMode = props->dropdownMenuMode;
|
|
79
|
+
this->disabled = props->disabled;
|
|
80
|
+
this->previewBackgroundColor = props->previewBackgroundColor;
|
|
81
|
+
this->icon = props->icon;
|
|
82
|
+
this->subtitle = props->subtitle;
|
|
83
|
+
this->systemIcon = props->systemIcon;
|
|
84
|
+
this->iconColor = props->iconColor;
|
|
85
|
+
this->fontName = props->fontName;
|
|
86
|
+
// ios only
|
|
87
|
+
this->destructive = props->destructive;
|
|
88
|
+
this->selected = props->selected;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
StackNode &RTNContextMenuComponentInstance::getLocalRootArkUINode() {
|
|
93
|
+
return m_contextMenuNode;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
// 点击时候的传递的参数,从arkTS层发送
|
|
97
|
+
void RTNContextMenuComponentInstance::onClick(int index, std::vector<int> indexPath, std::string name) {
|
|
98
|
+
m_eventEmitter->onPress({index : index, indexPath : indexPath, name : name});
|
|
99
|
+
}
|
|
100
|
+
void RTNContextMenuComponentInstance::onCancel() {
|
|
101
|
+
m_eventEmitter->onCancel({});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
folly::dynamic
|
|
105
|
+
dynamicFromTouchableViews(const std::vector<RTNContextMenuComponentInstance::TouchableView> &touchableViews) {
|
|
106
|
+
folly::dynamic d_touchableViews = folly::dynamic::array();
|
|
107
|
+
for (auto touchableView : touchableViews) {
|
|
108
|
+
folly::dynamic d_touchableView = folly::dynamic::object;
|
|
109
|
+
d_touchableView["tag"] = touchableView.tag;
|
|
110
|
+
d_touchableView["x"] = touchableView.x;
|
|
111
|
+
d_touchableView["y"] = touchableView.y;
|
|
112
|
+
d_touchableView["width"] = touchableView.width;
|
|
113
|
+
d_touchableView["height"] = touchableView.height;
|
|
114
|
+
d_touchableViews.push_back(d_touchableView);
|
|
115
|
+
}
|
|
116
|
+
return d_touchableViews;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// 处理单个 RTNContextMenuActionsStruct 对象的函数
|
|
120
|
+
folly::dynamic convertToDynamic(const facebook::react::RTNContextMenuActionsStruct &action, int level) {
|
|
121
|
+
folly::dynamic touchViewChildActions = folly::dynamic::object;
|
|
122
|
+
touchViewChildActions["childActionsTag"] = level;
|
|
123
|
+
touchViewChildActions["title"] = action.title;
|
|
124
|
+
touchViewChildActions["titleColor"] = action.titleColor;
|
|
125
|
+
touchViewChildActions["subtitle"] = action.subtitle;
|
|
126
|
+
touchViewChildActions["systemIcon"] = action.systemIcon;
|
|
127
|
+
touchViewChildActions["icon"] = action.icon;
|
|
128
|
+
touchViewChildActions["iconColor"] = action.iconColor;
|
|
129
|
+
touchViewChildActions["destructive"] = action.destructive;
|
|
130
|
+
touchViewChildActions["selected"] = action.selected;
|
|
131
|
+
touchViewChildActions["disabled"] = action.disabled;
|
|
132
|
+
touchViewChildActions["inlineChildren"] = action.inlineChildren;
|
|
133
|
+
|
|
134
|
+
if (!action.actions.empty()) {
|
|
135
|
+
folly::dynamic childActionsArray = folly::dynamic::array;
|
|
136
|
+
for (const auto &childAction : action.actions) {
|
|
137
|
+
childActionsArray.push_back(convertToDynamic(childAction, level + 1));
|
|
138
|
+
}
|
|
139
|
+
touchViewChildActions["childActions"] = childActionsArray;
|
|
140
|
+
}
|
|
141
|
+
return touchViewChildActions;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
folly::dynamic convertNodeTouchPointToDynamic(ArkUI_UIInputEvent *e, int32_t index = 0) {
|
|
145
|
+
folly::dynamic result = folly::dynamic::object;
|
|
146
|
+
result["pointerId"] = OH_ArkUI_PointerEvent_GetPointerId(e, index);
|
|
147
|
+
result["windowX"] = OH_ArkUI_PointerEvent_GetWindowXByIndex(e, index);
|
|
148
|
+
result["windowY"] = OH_ArkUI_PointerEvent_GetWindowYByIndex(e, index);
|
|
149
|
+
|
|
150
|
+
return result;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// 1.首先触发touch事件
|
|
154
|
+
void RTNContextMenuComponentInstance::onTouchEvent(ArkUI_UIInputEvent *e) {
|
|
155
|
+
auto ancestor = this->getParent().lock();
|
|
156
|
+
while (ancestor != nullptr) {
|
|
157
|
+
auto ancestorRNGHRootView = std::dynamic_pointer_cast<RTNContextMenuComponentInstance>(ancestor);
|
|
158
|
+
if (ancestorRNGHRootView != nullptr) {
|
|
159
|
+
// If there are multiple nested GestureHandlerRootViews, the one nearest to the actual root will handle
|
|
160
|
+
// the touch.
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
ancestor = ancestor->getParent().lock();
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
auto ancestorTouchTarget = this->getTouchTargetParent();
|
|
167
|
+
auto rnInstance = m_deps->rnInstance.lock();
|
|
168
|
+
while (ancestorTouchTarget != nullptr) {
|
|
169
|
+
if (ancestorTouchTarget->isHandlingTouches()) {
|
|
170
|
+
// 这里同理发送给ArtTs的消息,CANCEL_TOUCHES
|
|
171
|
+
rnInstance->postMessageToArkTS("RNGH::CANCEL_TOUCHES", m_tag);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
ancestorTouchTarget = ancestorTouchTarget->getTouchTargetParent();
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
folly::dynamic payload = folly::dynamic::object;
|
|
178
|
+
payload["action"] = OH_ArkUI_UIInputEvent_GetAction(e);
|
|
179
|
+
folly::dynamic touchPoints = folly::dynamic::array();
|
|
180
|
+
auto activeWindowX = OH_ArkUI_PointerEvent_GetWindowX(e);
|
|
181
|
+
auto activeWindowY = OH_ArkUI_PointerEvent_GetWindowY(e);
|
|
182
|
+
|
|
183
|
+
// point relative to top left corner of this component(相对位置)
|
|
184
|
+
auto componentX = OH_ArkUI_PointerEvent_GetX(e);
|
|
185
|
+
auto componentY = OH_ArkUI_PointerEvent_GetY(e);
|
|
186
|
+
// 2.通过点击的xy,获取触发的点击视图
|
|
187
|
+
auto touchableViews = this->findTouchableViews(componentX, componentY);
|
|
188
|
+
|
|
189
|
+
std::stringstream touchableViewTags;
|
|
190
|
+
for (auto touchableView : touchableViews) {
|
|
191
|
+
touchableViewTags << touchableView.tag << ";";
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// 3.动态获取touchableViews,然后赋值给touchableViews
|
|
195
|
+
payload["touchableViews"] = dynamicFromTouchableViews(touchableViews);
|
|
196
|
+
|
|
197
|
+
int32_t pointerCount = OH_ArkUI_PointerEvent_GetPointerCount(e);
|
|
198
|
+
int activePointerIdx = 0;
|
|
199
|
+
|
|
200
|
+
for (int i = 0; i < pointerCount; i++) {
|
|
201
|
+
// 4.将触摸节点变成动态
|
|
202
|
+
auto touchPoint = convertNodeTouchPointToDynamic(e, i);
|
|
203
|
+
touchPoints.push_back(touchPoint);
|
|
204
|
+
if (activeWindowX == touchPoint["windowX"].asDouble() && activeWindowY == touchPoint["windowY"].asDouble()) {
|
|
205
|
+
activePointerIdx = i;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// 根据点击的视图传递view参数
|
|
209
|
+
payload["title"] = this->title;
|
|
210
|
+
payload["dropdownMenuMode"] = this->dropdownMenuMode;
|
|
211
|
+
payload["disabled"] = this->disabled;
|
|
212
|
+
payload["previewBackgroundColor"] = this->previewBackgroundColor;
|
|
213
|
+
payload["fontName"] = this->fontName;
|
|
214
|
+
|
|
215
|
+
folly::dynamic touchViewActions = folly::dynamic::array();
|
|
216
|
+
for (auto actions : m_props->actions) {
|
|
217
|
+
folly::dynamic touchViewAction = folly::dynamic::object;
|
|
218
|
+
touchViewAction["title"] = actions.title;
|
|
219
|
+
touchViewAction["titleColor"] = actions.titleColor;
|
|
220
|
+
touchViewAction["subtitle"] = actions.subtitle;
|
|
221
|
+
touchViewAction["systemIcon"] = actions.systemIcon;
|
|
222
|
+
touchViewAction["icon"] = actions.icon;
|
|
223
|
+
touchViewAction["iconColor"] = actions.iconColor;
|
|
224
|
+
touchViewAction["destructive"] = actions.destructive;
|
|
225
|
+
touchViewAction["selected"] = actions.selected;
|
|
226
|
+
touchViewAction["disabled"] = actions.disabled;
|
|
227
|
+
touchViewAction["inlineChildren"] = actions.inlineChildren;
|
|
228
|
+
if (actions.actions.size() > 0) {
|
|
229
|
+
folly::dynamic d_childActions = folly::dynamic::array;
|
|
230
|
+
for (const auto &childAction : actions.actions) {
|
|
231
|
+
d_childActions.push_back(convertToDynamic(childAction, 0));
|
|
232
|
+
touchViewAction["d_childActions"] = d_childActions;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
touchViewActions.push_back(touchViewAction);
|
|
236
|
+
}
|
|
237
|
+
payload["touchViewActions"] = touchViewActions;
|
|
238
|
+
|
|
239
|
+
payload["actionTouch"] = touchPoints[activePointerIdx];
|
|
240
|
+
payload["touchPoints"] = touchPoints;
|
|
241
|
+
payload["sourceType"] = OH_ArkUI_UIInputEvent_GetSourceType(e);
|
|
242
|
+
payload["timestamp"] = OH_ArkUI_UIInputEvent_GetEventTime(e);
|
|
243
|
+
payload["rootTag"] = m_tag;
|
|
244
|
+
|
|
245
|
+
if (rnInstance) {
|
|
246
|
+
// 点击事件可以在此处获取
|
|
247
|
+
rnInstance->getTurboModule("ContextMenuTurboModule");
|
|
248
|
+
rnInstance->postMessageToArkTS("RNGH::TOUCH_EVENT", payload);
|
|
249
|
+
} else {
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// findTouchableViews方法
|
|
254
|
+
std::vector<RTNContextMenuComponentInstance::TouchableView>
|
|
255
|
+
RTNContextMenuComponentInstance::findTouchableViews(float componentX, float componentY) {
|
|
256
|
+
auto touchTarget = findTargetForTouchPoint({.x = componentX, .y = componentY}, this->shared_from_this());
|
|
257
|
+
std::vector<TouchTarget::Shared> touchTargets{};
|
|
258
|
+
auto tmp = touchTarget;
|
|
259
|
+
while (tmp != nullptr) {
|
|
260
|
+
touchTargets.push_back(tmp);
|
|
261
|
+
tmp = tmp->getTouchTargetParent();
|
|
262
|
+
}
|
|
263
|
+
std::reverse(touchTargets.begin(), touchTargets.end()); // leaf / ... / root -> root / ... / leaf
|
|
264
|
+
std::vector<TouchableView> touchableViews{};
|
|
265
|
+
|
|
266
|
+
float offsetX = 0;
|
|
267
|
+
float offsetY = 0;
|
|
268
|
+
auto surface = this->getSurface().lock();
|
|
269
|
+
if (surface != nullptr) {
|
|
270
|
+
offsetX = surface->getLayoutContext().viewportOffset.x;
|
|
271
|
+
offsetY = surface->getLayoutContext().viewportOffset.y;
|
|
272
|
+
} else {
|
|
273
|
+
LOG(WARNING) << "Surface is nullptr";
|
|
274
|
+
}
|
|
275
|
+
for (auto &touchTarget : touchTargets) {
|
|
276
|
+
touchableViews.push_back({
|
|
277
|
+
.tag = touchTarget->getTouchTargetTag(),
|
|
278
|
+
.width = touchTarget->getLayoutMetrics().frame.size.width,
|
|
279
|
+
.height = touchTarget->getLayoutMetrics().frame.size.height,
|
|
280
|
+
.x = touchTarget->getLayoutMetrics().frame.origin.x + offsetX,
|
|
281
|
+
.y = touchTarget->getLayoutMetrics().frame.origin.y + offsetY,
|
|
282
|
+
});
|
|
283
|
+
offsetX += touchTarget->getLayoutMetrics().frame.origin.x;
|
|
284
|
+
offsetY += touchTarget->getLayoutMetrics().frame.origin.y;
|
|
285
|
+
offsetX -= touchTarget->getCurrentOffset().x;
|
|
286
|
+
offsetY -= touchTarget->getCurrentOffset().y;
|
|
287
|
+
}
|
|
288
|
+
return touchableViews;
|
|
289
|
+
};
|
|
290
|
+
} // namespace rnoh
|
|
@@ -0,0 +1,168 @@
|
|
|
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
|
+
#pragma once
|
|
26
|
+
#include "RNOH/CppComponentInstance.h"
|
|
27
|
+
#include "ShadowNodes.h"
|
|
28
|
+
#include "Props.h"
|
|
29
|
+
#include "RNOH/CppComponentInstance.h"
|
|
30
|
+
#include "RNOH/arkui/CustomNode.h"
|
|
31
|
+
#include "RNOH/arkui/TextNode.h"
|
|
32
|
+
#include "RNOH/arkui/StackNode.h"
|
|
33
|
+
#include "RNOH/arkui/ArkUINodeRegistry.h"
|
|
34
|
+
#include "RNOH/arkui/NativeNodeApi.h"
|
|
35
|
+
#include "RNOH/RNInstanceCAPI.h"
|
|
36
|
+
|
|
37
|
+
#include "RNOH/arkui/StackNode.h"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
namespace rnoh {
|
|
41
|
+
class RTNContextMenuComponentInstance : public CppComponentInstance<facebook::react::RTNContextMenuShadowNode>,
|
|
42
|
+
// public ContextMenuNodeDelegate
|
|
43
|
+
public StackNodeDelegate,
|
|
44
|
+
public TouchEventHandler {
|
|
45
|
+
|
|
46
|
+
using Point = facebook::react::Point;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* This function is borrowed from TouchEventDispatcher
|
|
50
|
+
*/
|
|
51
|
+
static TouchTarget::Shared findTargetForTouchPoint(Point const &point, TouchTarget::Shared const &target) {
|
|
52
|
+
bool canHandleTouch =
|
|
53
|
+
target->canHandleTouch() && target->containsPoint(point) && (target->getTouchEventEmitter() != nullptr);
|
|
54
|
+
bool canChildrenHandleTouch = target->canChildrenHandleTouch() && target->containsPointInBoundingBox(point);
|
|
55
|
+
|
|
56
|
+
if (canChildrenHandleTouch) {
|
|
57
|
+
auto children = target->getTouchTargetChildren();
|
|
58
|
+
// we want to check the children in reverse order, since the last child is the topmost one
|
|
59
|
+
std::reverse(children.begin(), children.end());
|
|
60
|
+
for (auto const &child : children) {
|
|
61
|
+
auto childPoint = target->computeChildPoint(point, child);
|
|
62
|
+
auto result = findTargetForTouchPoint(childPoint, child);
|
|
63
|
+
if (result != nullptr) {
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (canHandleTouch) {
|
|
69
|
+
return target;
|
|
70
|
+
}
|
|
71
|
+
return nullptr;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
public:
|
|
75
|
+
RTNContextMenuComponentInstance(Context context);
|
|
76
|
+
~RTNContextMenuComponentInstance();
|
|
77
|
+
|
|
78
|
+
// override属于覆写接口,需要实例化
|
|
79
|
+
void onChildInserted(ComponentInstance::Shared const &childComponentInstance, std::size_t index) override;
|
|
80
|
+
void onChildRemoved(ComponentInstance::Shared const &childComponentInstance) override;
|
|
81
|
+
|
|
82
|
+
// arkui为页面ui
|
|
83
|
+
StackNode &getLocalRootArkUINode() override;
|
|
84
|
+
|
|
85
|
+
void onPropsChanged(SharedConcreteProps const &props) override;
|
|
86
|
+
|
|
87
|
+
void setIsHandlingTouches(bool isHandlingTouches) { m_isHandlingTouches = isHandlingTouches; }
|
|
88
|
+
|
|
89
|
+
bool isHandlingTouches() const override { return m_isHandlingTouches; }
|
|
90
|
+
|
|
91
|
+
// StackNodeDelegate
|
|
92
|
+
void onClick(int index, std::vector<int> indexPath, std::string name);
|
|
93
|
+
void onCancel ();
|
|
94
|
+
void onTouchEvent(ArkUI_UIInputEvent *e) override;
|
|
95
|
+
|
|
96
|
+
struct TouchableView {
|
|
97
|
+
Tag tag;
|
|
98
|
+
facebook::react::Float width;
|
|
99
|
+
facebook::react::Float height;
|
|
100
|
+
facebook::react::Float x;
|
|
101
|
+
facebook::react::Float y;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
struct RTNContextMenuActionsStruct {
|
|
105
|
+
std::string title;
|
|
106
|
+
std::string titleColor;
|
|
107
|
+
std::string subtitle;
|
|
108
|
+
std::string systemIcon;
|
|
109
|
+
std::string icon;
|
|
110
|
+
std::string iconColor;
|
|
111
|
+
bool destructive;
|
|
112
|
+
bool selected;
|
|
113
|
+
bool disabled;
|
|
114
|
+
bool inlineChildren;
|
|
115
|
+
std::vector<RTNContextMenuActionsStruct> actions;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
private:
|
|
119
|
+
std::string title{};
|
|
120
|
+
RTNContextMenuActionsStruct actions{};
|
|
121
|
+
std::string previewBackgroundColor{};
|
|
122
|
+
bool dropdownMenuMode{};
|
|
123
|
+
bool disabled{};
|
|
124
|
+
std::string subtitle{};
|
|
125
|
+
std::string systemIcon{};
|
|
126
|
+
std::string icon{};
|
|
127
|
+
std::string iconColor{};
|
|
128
|
+
bool destructive{};
|
|
129
|
+
bool selected{};
|
|
130
|
+
bool inlineChildren{};
|
|
131
|
+
|
|
132
|
+
bool m_isHandlingTouches = false;
|
|
133
|
+
std::string fontName{};
|
|
134
|
+
|
|
135
|
+
StackNode m_contextMenuNode;
|
|
136
|
+
std::vector<TouchableView> findTouchableViews(float componentX, float componentY);
|
|
137
|
+
std::optional<std::string> getTintColorFromDynamic(folly::dynamic value);
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
Surface::Weak m_surface;
|
|
141
|
+
Surface::Weak getSurface() {
|
|
142
|
+
if (m_surface.lock() != nullptr) {
|
|
143
|
+
return m_surface;
|
|
144
|
+
}
|
|
145
|
+
auto rnInstance = m_deps->rnInstance.lock();
|
|
146
|
+
if (rnInstance == nullptr) {
|
|
147
|
+
m_surface.reset();
|
|
148
|
+
return m_surface;
|
|
149
|
+
}
|
|
150
|
+
ComponentInstance::Shared currentRoot = shared_from_this();
|
|
151
|
+
while (true) {
|
|
152
|
+
auto maybeNewCurrentRoot = currentRoot->getParent().lock();
|
|
153
|
+
if (maybeNewCurrentRoot == nullptr) {
|
|
154
|
+
break;
|
|
155
|
+
}
|
|
156
|
+
currentRoot = maybeNewCurrentRoot;
|
|
157
|
+
}
|
|
158
|
+
auto maybeSurface = rnInstance->getSurfaceByRootTag(currentRoot->getTag());
|
|
159
|
+
if (!maybeSurface.has_value()) {
|
|
160
|
+
m_surface.reset();
|
|
161
|
+
return m_surface;
|
|
162
|
+
}
|
|
163
|
+
m_surface = maybeSurface.value();
|
|
164
|
+
return m_surface;
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
} // namespace rnoh
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved
|
|
3
|
+
* Use of this source code is governed by a MIT license that can be
|
|
4
|
+
* found in the LICENSE file.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
#include <ShadowNodes.h>
|
|
8
|
+
|
|
9
|
+
namespace facebook {
|
|
10
|
+
namespace react {
|
|
11
|
+
|
|
12
|
+
extern const char RTNContextMenuComponentName[] = "RTNContextMenu";
|
|
13
|
+
|
|
14
|
+
} // namespace react
|
|
15
|
+
} // namespace facebook
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved
|
|
3
|
+
* Use of this source code is governed by a MIT license that can be
|
|
4
|
+
* found in the LICENSE file.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
#pragma once
|
|
8
|
+
|
|
9
|
+
#include <react/renderer/components/view/ConcreteViewShadowNode.h>
|
|
10
|
+
#include <jsi/jsi.h>
|
|
11
|
+
#include "EventEmitters.h"
|
|
12
|
+
#include "Props.h"
|
|
13
|
+
#include "States.h"
|
|
14
|
+
|
|
15
|
+
namespace facebook {
|
|
16
|
+
namespace react {
|
|
17
|
+
|
|
18
|
+
JSI_EXPORT extern const char RTNContextMenuComponentName[];
|
|
19
|
+
|
|
20
|
+
/*
|
|
21
|
+
* `ShadowNode` for <RTNContextMenu> component.
|
|
22
|
+
*/
|
|
23
|
+
using RTNContextMenuShadowNode = ConcreteViewShadowNode<
|
|
24
|
+
RTNContextMenuComponentName,
|
|
25
|
+
RTNContextMenuProps,
|
|
26
|
+
RTNContextMenuEventEmitter,
|
|
27
|
+
RTNContextMenuState>;
|
|
28
|
+
|
|
29
|
+
} // namespace react
|
|
30
|
+
} // namespace facebook
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved
|
|
3
|
+
* Use of this source code is governed by a MIT license that can be
|
|
4
|
+
* found in the LICENSE file.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
#include "States.h"
|
|
8
|
+
|
|
9
|
+
namespace facebook {
|
|
10
|
+
namespace react {
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
} // namespace react
|
|
15
|
+
} // namespace facebook
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved
|
|
3
|
+
* Use of this source code is governed by a MIT license that can be
|
|
4
|
+
* found in the LICENSE file.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
#pragma once
|
|
8
|
+
|
|
9
|
+
#ifdef ANDROID
|
|
10
|
+
#include <folly/dynamic.h>
|
|
11
|
+
#include <react/renderer/mapbuffer/MapBuffer.h>
|
|
12
|
+
#include <react/renderer/mapbuffer/MapBufferBuilder.h>
|
|
13
|
+
#endif
|
|
14
|
+
|
|
15
|
+
namespace facebook {
|
|
16
|
+
namespace react {
|
|
17
|
+
|
|
18
|
+
class RTNContextMenuState {
|
|
19
|
+
public:
|
|
20
|
+
RTNContextMenuState() = default;
|
|
21
|
+
|
|
22
|
+
#ifdef ANDROID
|
|
23
|
+
RTNContextMenuState(RTNContextMenuState const &previousState, folly::dynamic data){};
|
|
24
|
+
folly::dynamic getDynamic() const {
|
|
25
|
+
return {};
|
|
26
|
+
};
|
|
27
|
+
MapBuffer getMapBuffer() const {
|
|
28
|
+
return MapBufferBuilder::EMPTY();
|
|
29
|
+
};
|
|
30
|
+
#endif
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
} // namespace react
|
|
34
|
+
} // namespace facebook
|