1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <ani.h>
17 #include <array>
18 #include <iostream>
19 #include <string>
20 #include <vector>
21
22 #include "frameworks/base/utils/utils.h"
23 #include "frameworks/bridge/common/utils/engine_helper.h"
24 #include "frameworks/core/components_ng/pattern/toast/toast_layout_property.h"
25 #include "frameworks/base/utils/system_properties.h"
26 #include "frameworks/base/geometry/dimension.h"
27 #include "frameworks/core/components/common/properties/shadow.h"
28 #include "promptActionUtils.h"
29
30 namespace OHOS::Ace::NG {
ContainerIsService()31 bool ContainerIsService()
32 {
33 auto containerId = Container::CurrentIdSafely();
34 // Get active container when current instanceid is less than 0
35 if (containerId < 0) {
36 auto container = Container::GetActive();
37 if (container) {
38 containerId = container->GetInstanceId();
39 }
40 }
41 // for pa service
42 return containerId >= MIN_PA_SERVICE_ID || containerId < 0;
43 }
44
ContainerIsScenceBoard()45 bool ContainerIsScenceBoard()
46 {
47 auto container = Container::CurrentSafely();
48 if (!container) {
49 container = Container::GetActive();
50 }
51 return container && container->IsSceneBoardWindow();
52 }
53 } // OHOS::Ace::NG
54
55 std::unordered_map<std::string, int> alignmentMap = {
56 {"TopStart", 0},
57 {"Top", 1},
58 {"TopEnd", 2},
59 {"Start", 3},
60 {"Center", 4},
61 {"End", 5},
62 {"BottomStart", 6},
63 {"Bottom", 7},
64 {"BottomEnd", 8}
65 };
66
GetToastMessage(ani_env * env,ani_object options,std::string & messageString)67 bool GetToastMessage(ani_env *env, ani_object options, std::string& messageString)
68 {
69 ani_ref message_ref;
70 if (ANI_OK != env->Object_GetPropertyByName_Ref(options, "message", &message_ref)) {
71 return false;
72 }
73 if (GetIsStringObject(env, message_ref)) {
74 auto stringContent = ANIUtils_ANIStringToStdString(env, static_cast<ani_string>(message_ref));
75 messageString = stringContent;
76 return true;
77 }
78 if (GetIsResourceObject(env, message_ref)) {
79 ResourceInfo resourceInfo;
80 std::string messageStr;
81 if (!ParseResourceParam(env, static_cast<ani_object>(message_ref), resourceInfo)) {
82 return false;
83 }
84 if (!ParseString(resourceInfo, messageStr)) {
85 return false;
86 }
87 if (messageStr.size() == 0) {
88 return false;
89 }
90 messageString = messageStr;
91 }
92 return true;
93 }
GetToastDuration(ani_env * env,ani_object options,int32_t & durationInt)94 bool GetToastDuration(ani_env *env, ani_object options, int32_t& durationInt)
95 {
96 ani_ref duration_ref;
97 if (ANI_OK != env->Object_GetPropertyByName_Ref(options, "duration", &duration_ref)) {
98 return false;
99 }
100 if (GetIsUndefinedObject(env, duration_ref)) {
101 return false;
102 }
103 ani_double duration;
104 if (ANI_OK !=env->Object_CallMethodByName_Double(
105 static_cast<ani_object>(duration_ref), "doubleValue", nullptr, &duration)) {
106 return false;
107 }
108 durationInt = static_cast<int32_t>(duration);
109 return true;
110 }
GetToastBottom(ani_env * env,ani_object options,std::string & bottomString)111 bool GetToastBottom(ani_env *env, ani_object options, std::string& bottomString)
112 {
113 ani_ref bottom_ref;
114 if (ANI_OK != env->Object_GetPropertyByName_Ref(options, "bottom", &bottom_ref)) {
115 return false;
116 }
117 if (GetIsUndefinedObject(env, bottom_ref)) {
118 return false;
119 }
120 if (GetIsStringObject(env, bottom_ref)) {
121 auto stringContent = ANIUtils_ANIStringToStdString(env, static_cast<ani_string>(bottom_ref));
122 bottomString = stringContent;
123 return true;
124 }
125 if (GetIsNumberObject(env, bottom_ref)) {
126 ani_double bottom;
127 if (ANI_OK !=env->Object_CallMethodByName_Double(
128 static_cast<ani_object>(bottom_ref), "doubleValue", nullptr, &bottom)) {
129 return false;
130 }
131 double botm = static_cast<double>(bottom);
132 bottomString = std::to_string(botm);
133 }
134 return true;
135 }
GetToastShowMode(ani_env * env,ani_object options,OHOS::Ace::NG::ToastShowMode & showMode)136 bool GetToastShowMode(ani_env *env, ani_object options, OHOS::Ace::NG::ToastShowMode& showMode)
137 {
138 ani_ref showMode_ref;
139 if (ANI_OK != env->Object_GetPropertyByName_Ref(options, "showMode", &showMode_ref)) {
140 return false;
141 }
142 if (GetIsUndefinedObject(env, showMode_ref)) {
143 return false;
144 }
145 if (!GetIsToastShowModeEnum(env, showMode_ref)) {
146 return false;
147 }
148 ani_int showMode_int;
149 if (ANI_OK != env->EnumItem_GetValue_Int(static_cast<ani_enum_item>(showMode_ref), &showMode_int)) {
150 return false;
151 }
152 showMode = static_cast<OHOS::Ace::NG::ToastShowMode>(showMode_int);
153 return true;
154 }
GetToastAlignment(ani_env * env,ani_object options,int32_t & alignment)155 bool GetToastAlignment(ani_env *env, ani_object options, int32_t& alignment)
156 {
157 ani_ref alignment_ref;
158 if (ANI_OK != env->Object_GetPropertyByName_Ref(options, "alignment", &alignment_ref)) {
159 return false;
160 }
161 if (GetIsUndefinedObject(env, alignment_ref)) {
162 return false;
163 }
164 if (!GetIsAlignmentEnum(env, alignment_ref)) {
165 return false;
166 }
167 ani_string stringValue;
168 if (ANI_OK != env->EnumItem_GetValue_String(static_cast<ani_enum_item>(alignment_ref), &stringValue)) {
169 return false;
170 }
171 auto stringContent = ANIUtils_ANIStringToStdString(env, static_cast<ani_string>(stringValue));
172 auto it = alignmentMap.find(stringContent);
173 if (it != alignmentMap.end()) {
174 alignment = static_cast<int32_t>(it->second);
175 } else {
176 alignment = -1;
177 return false;
178 }
179 return true;
180 }
GetToastBackgroundBlurStyle(ani_env * env,ani_object options,std::optional<int32_t> & backgroundBlurStyle)181 bool GetToastBackgroundBlurStyle(ani_env *env, ani_object options, std::optional<int32_t>& backgroundBlurStyle)
182 {
183 ani_ref blurStyle_ref;
184 if (ANI_OK != env->Object_GetPropertyByName_Ref(options, "backgroundBlurStyle", &blurStyle_ref)) {
185 return false;
186 }
187 if (GetIsUndefinedObject(env, blurStyle_ref)) {
188 return false;
189 }
190 if (!GetIsBlurStyleEnum(env, blurStyle_ref)) {
191 return false;
192 }
193 ani_int blueStyle_int;
194 if (ANI_OK != env->EnumItem_GetValue_Int(static_cast<ani_enum_item>(blurStyle_ref), &blueStyle_int)) {
195 return false;
196 }
197 backgroundBlurStyle = static_cast<int32_t>(blueStyle_int);
198 std::cerr << "GetToastBackgroundBlurStyle blueStyle " << static_cast<int32_t>(blueStyle_int) << std::endl;
199 return true;
200 }
GetToastOffset(ani_env * env,ani_object options,std::optional<OHOS::Ace::DimensionOffset> & offset)201 bool GetToastOffset(ani_env *env, ani_object options, std::optional<OHOS::Ace::DimensionOffset>& offset)
202 {
203 ani_ref offset_ref;
204 if (ANI_OK != env->Object_GetPropertyByName_Ref(options, "offset", &offset_ref)) {
205 return false;
206 }
207 if (GetIsUndefinedObject(env, offset_ref)) {
208 return false;
209 }
210 ani_ref dx_ref;
211 if (ANI_OK != env->Object_GetPropertyByName_Ref(static_cast<ani_object>(offset_ref), "dx", &dx_ref)) {
212 return false;
213 }
214 ani_ref dy_ref;
215 if (ANI_OK != env->Object_GetPropertyByName_Ref(static_cast<ani_object>(offset_ref), "dy", &dy_ref)) {
216 return false;
217 }
218 OHOS::Ace::CalcDimension dx;
219 OHOS::Ace::CalcDimension dy;
220 if (!ParseLengthToDimension(env, dx_ref, OHOS::Ace::DimensionUnit::VP, dx)) {
221 return false;
222 }
223 if (!ParseLengthToDimension(env, dy_ref, OHOS::Ace::DimensionUnit::VP, dy)) {
224 return false;
225 }
226 offset = OHOS::Ace::DimensionOffset { dx, dy };
227 return true;
228 }
GetToastShadow(ani_env * env,ani_object options,std::optional<OHOS::Ace::Shadow> & shadow,bool & isTypeStyleShadow)229 bool GetToastShadow(ani_env *env, ani_object options, std::optional<OHOS::Ace::Shadow>& shadow,
230 bool& isTypeStyleShadow)
231 {
232 ani_ref shadow_ref;
233 if (ANI_OK != env->Object_GetPropertyByName_Ref(options, "shadow", &shadow_ref)) {
234 return false;
235 }
236 if (GetIsUndefinedObject(env, shadow_ref)) {
237 return false;
238 }
239 OHOS::Ace::Shadow shadowProps;
240 if (GetIsShadowStyleEnum(env, shadow_ref)) {
241 ani_int shadow_int;
242 if (ANI_OK != env->EnumItem_GetValue_Int(static_cast<ani_enum_item>(shadow_ref), &shadow_int)) {
243 return false;
244 }
245 auto style = static_cast<OHOS::Ace::ShadowStyle>(shadow_int);
246 GetShadowFromTheme(style, shadowProps);
247 shadow = shadowProps;
248 return true;
249 }
250 if (GetIsShadowOptionsObject(env, shadow_ref)) {
251 bool ret = GetToastObjectShadow(env, static_cast<ani_object>(shadow_ref), shadowProps);
252 isTypeStyleShadow = false;
253 return ret;
254 }
255 return true;
256 }
GetToastBackgroundColor(ani_env * env,ani_object options,std::optional<OHOS::Ace::Color> & backgroundColor)257 bool GetToastBackgroundColor(ani_env* env, ani_object options, std::optional<OHOS::Ace::Color>& backgroundColor)
258 {
259 ani_ref resourceColor_ref;
260 if (ANI_OK != env->Object_GetPropertyByName_Ref(options, "backgroundColor", &resourceColor_ref)) {
261 return false;
262 }
263 if (GetIsUndefinedObject(env, resourceColor_ref)) {
264 return false;
265 }
266 OHOS::Ace::Color resourceColor;
267 if (ParseAniColor(env, resourceColor_ref, resourceColor)) {
268 backgroundColor = resourceColor;
269 return true;
270 }
271 return false;
272 }
GetToastTextColor(ani_env * env,ani_object options,std::optional<OHOS::Ace::Color> & textColor)273 bool GetToastTextColor(ani_env* env, ani_object options, std::optional<OHOS::Ace::Color>& textColor)
274 {
275 ani_ref resourceColor_ref;
276 if (ANI_OK != env->Object_GetPropertyByName_Ref(options, "textColor", &resourceColor_ref)) {
277 return false;
278 }
279 if (GetIsUndefinedObject(env, resourceColor_ref)) {
280 return false;
281 }
282 OHOS::Ace::Color resourceColor;
283 if (ParseAniColor(env, resourceColor_ref, resourceColor)) {
284 textColor = resourceColor;
285 return true;
286 }
287 return false;
288 }
GetToastEnableHoverMode(ani_env * env,ani_object options,bool & enableHoverMode)289 bool GetToastEnableHoverMode(ani_env* env, ani_object options, bool& enableHoverMode)
290 {
291 ani_ref mode_ref;
292 if (ANI_OK != env->Object_GetPropertyByName_Ref(options, "enableHoverMode", &mode_ref)) {
293 return false;
294 }
295 if (GetIsUndefinedObject(env, mode_ref)) {
296 return false;
297 }
298 ani_boolean modeValue;
299 if (ANI_OK != env->Object_CallMethodByName_Boolean(
300 static_cast<ani_object>(mode_ref), "unboxed", nullptr, &modeValue)) {
301 return false;
302 }
303 enableHoverMode = static_cast<bool>(modeValue);
304 return true;
305 }
GetToastHoverModeArea(ani_env * env,ani_object options,OHOS::Ace::HoverModeAreaType & hoverModeArea)306 bool GetToastHoverModeArea(ani_env* env, ani_object options, OHOS::Ace::HoverModeAreaType& hoverModeArea)
307 {
308 ani_ref area_ref;
309 if (ANI_OK != env->Object_GetPropertyByName_Ref(options, "hoverModeArea", &area_ref)) {
310 return false;
311 }
312 if (GetIsUndefinedObject(env, area_ref)) {
313 return false;
314 }
315 if (!GetIsHoverModeAreaEnum(env, area_ref)) {
316 return false;
317 }
318 ani_int area_int;
319 if (ANI_OK != env->EnumItem_GetValue_Int(static_cast<ani_enum_item>(area_ref), &area_int)) {
320 return false;
321 }
322 hoverModeArea = static_cast<OHOS::Ace::HoverModeAreaType>(area_int);
323 return true;
324 }
GetToastParams(ani_env * env,ani_object options,OHOS::Ace::NG::ToastInfo toastInfo)325 bool GetToastParams(ani_env* env, ani_object options, OHOS::Ace::NG::ToastInfo toastInfo)
326 {
327 if (GetIsUndefinedObject(env, options)) {
328 return false;
329 }
330 if (!GetIsShowToastOptionsObject(env, options)) {
331 return false;
332 }
333 GetToastMessage(env, options, toastInfo.message);
334 std::cout << "GetToastMessage :" << toastInfo.message.c_str() << std::endl;
335 GetToastDuration(env, options, toastInfo.duration);
336 std::cout << "GetToastDuration :" << toastInfo.duration << std::endl;
337 GetToastBottom(env, options, toastInfo.bottom);
338 std::cout << "GetToastBottom :" << toastInfo.bottom.c_str() << std::endl;
339 GetToastShowMode(env, options, toastInfo.showMode);
340 std::cout << "GetToastShowMode :" << static_cast<int32_t>(toastInfo.showMode) << std::endl;
341 GetToastAlignment(env, options, toastInfo.alignment);
342 std::cout << "GetToastAlignment :" << static_cast<int32_t>(toastInfo.alignment) << std::endl;
343 GetToastBackgroundBlurStyle(env, options, toastInfo.backgroundBlurStyle);
344 GetToastBackgroundColor(env, options, toastInfo.backgroundColor);
345 std::cout << "GetToastBackgroundColor :" << toastInfo.backgroundColor->ToString().c_str() << std::endl;
346 GetToastTextColor(env, options, toastInfo.textColor);
347 std::cout << "GetToastTextColor :" << toastInfo.textColor->ToString().c_str() << std::endl;
348 GetToastOffset(env, options, toastInfo.offset);
349 GetToastShadow(env, options, toastInfo.shadow, toastInfo.isTypeStyleShadow);
350 GetToastEnableHoverMode(env, options, toastInfo.enableHoverMode);
351 std::cout << "GetToastEnableHoverModer :" << toastInfo.enableHoverMode << std::endl;
352 GetToastHoverModeArea(env, options, toastInfo.hoverModeArea);
353 std::cout << "GetToastHoverModeArea :" << (int)toastInfo.hoverModeArea << std::endl;
354 return true;
355 }
HandleShowToast(OHOS::Ace::NG::ToastInfo & toastInfo,std::function<void (int32_t)> & toastCallback)356 bool HandleShowToast(OHOS::Ace::NG::ToastInfo& toastInfo, std::function<void(int32_t)>& toastCallback)
357 {
358 if ((OHOS::Ace::SystemProperties::GetExtSurfaceEnabled() || !OHOS::Ace::NG::ContainerIsService())
359 && !OHOS::Ace::NG::ContainerIsScenceBoard() && toastInfo.showMode == OHOS::Ace::NG::ToastShowMode::DEFAULT) {
360 auto delegate = OHOS::Ace::EngineHelper::GetCurrentDelegateSafely();
361 if (!delegate) {
362 return false;
363 }
364 delegate->ShowToast(toastInfo, std::move(toastCallback));
365 }
366 return true;
367 }
showToast(ani_env * env,ani_object options)368 static void showToast([[maybe_unused]] ani_env* env, ani_object options)
369 {
370 std::cout << "ani showToast start" << std::endl;
371 auto toastInfo = OHOS::Ace::NG::ToastInfo { .duration = -1,
372 .showMode = OHOS::Ace::NG::ToastShowMode::DEFAULT,
373 .alignment = -1 };
374 if (!GetToastParams(env, options, toastInfo)) {
375 return;
376 }
377 std::function<void(int32_t)> toastCallback = nullptr;
378 HandleShowToast(toastInfo, toastCallback);
379 std::cerr << "ShowToast end" << std::endl;
380 }
ANI_Constructor(ani_vm * vm,uint32_t * result)381 ANI_EXPORT ani_status ANI_Constructor(ani_vm *vm, uint32_t *result)
382 {
383 std::cout << "ani ANI_Constructor start" << std::endl;
384
385 ani_env *env;
386 if (ANI_OK != vm->GetEnv(ANI_VERSION_1, &env)) {
387 return ANI_ERROR;
388 }
389
390 ani_namespace ns;
391 if (ANI_OK != env->FindNamespace("L@ohos/promptAction/promptAction;", &ns)) {
392 return ANI_ERROR;
393 }
394 std::array methods = {
395 ani_native_function {"showToast", nullptr, reinterpret_cast<void *>(showToast)},
396 };
397 if (ANI_OK != env->Namespace_BindNativeFunctions(ns, methods.data(), methods.size())) {
398 return ANI_ERROR;
399 }
400
401 *result = ANI_VERSION_1;
402 std::cout << "ani ANI_Constructor end" << std::endl;
403 return ANI_OK;
404 }
405