1 /*
2 * Copyright (c) 2024 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 "cj_prompt_ffi.h"
17
18 #include <malloc.h>
19
20 #include "cj_lambda.h"
21 #include "bridge/cj_frontend/interfaces/cj_ffi/utils.h"
22 #include "bridge/cj_frontend/frontend/cj_frontend_abstract.h"
23
24 using namespace OHOS::Ace;
25 using namespace OHOS::Ace::Framework;
26
27 namespace {
28 const int32_t SHOW_DIALOG_BUTTON_NUM_MAX = 3;
29 const int32_t SHOW_ACTION_MENU_BUTTON_NUM_MAX = 6;
30 const std::vector<DialogAlignment> DIALOG_ALIGNMENT = { DialogAlignment::TOP, DialogAlignment::CENTER,
31 DialogAlignment::BOTTOM, DialogAlignment::DEFAULT, DialogAlignment::TOP_START, DialogAlignment::TOP_END,
32 DialogAlignment::CENTER_START, DialogAlignment::CENTER_END, DialogAlignment::BOTTOM_START,
33 DialogAlignment::BOTTOM_END };
34
CheckFrontendLegality(int32_t size,CButtonInfo * buttonsInfo)35 RefPtr<OHOS::Ace::CJFrontendAbstract> CheckFrontendLegality(int32_t size, CButtonInfo* buttonsInfo)
36 {
37 auto frontend = AceType::DynamicCast<CJFrontendAbstract>(Utils::GetCurrentFrontend());
38 if (!frontend) {
39 LOGE("Can not get frontend.");
40 return nullptr;
41 }
42 if (size < 0 || buttonsInfo == nullptr) {
43 LOGE("Invalid buttons info");
44 return nullptr;
45 }
46 return frontend;
47 }
48
CreateButtonInfoVector(CButtonInfo * buttonsInfo,int32_t size,int32_t numMax)49 std::vector<ButtonInfo> CreateButtonInfoVector(CButtonInfo* buttonsInfo, int32_t size, int32_t numMax)
50 {
51 std::vector<ButtonInfo> buttons;
52 if (size > numMax) {
53 size = numMax;
54 LOGE("Supports 1 - %{public}d buttons", numMax);
55 }
56 for (int i = 0; i < size; ++i) {
57 auto curInfo = buttonsInfo + i;
58 ButtonInfo button { .text = curInfo->text, .textColor = Color(curInfo->textColor).ColorToString() };
59 buttons.emplace_back(button);
60 }
61 return buttons;
62 }
63 } // namespace
64
65 extern "C" {
FfiPromptMallocButtons(int64_t size)66 void* FfiPromptMallocButtons(int64_t size)
67 {
68 if (size <= 0) {
69 return nullptr;
70 }
71
72 CButtonInfo* pButton = (CButtonInfo*)malloc(sizeof(CButtonInfo) * size);
73 if (pButton == nullptr) {
74 printf("Fail to malloc pButton.");
75 return nullptr;
76 }
77 return pButton;
78 }
79
FfiPromptShowToast(const char * message,int32_t duration,const char * bottom,int32_t mode)80 void FfiPromptShowToast(const char* message, int32_t duration, const char* bottom, int32_t mode)
81 {
82 auto frontend = AceType::DynamicCast<CJFrontendAbstract>(Utils::GetCurrentFrontend());
83 if (!frontend) {
84 LOGE("Can not get frontend.");
85 return;
86 }
87 frontend->ShowToast(message, duration, bottom, NG::ToastShowMode(mode));
88 }
89
FfiPromptShowDialog(const char * title,const char * message,int32_t size,CButtonInfo * buttonsInfo,ShowDialogCallBack callbackRef)90 void FfiPromptShowDialog(const char* title, const char* message, int32_t size,
91 CButtonInfo* buttonsInfo, ShowDialogCallBack callbackRef)
92 {
93 auto frontend = CheckFrontendLegality(size, buttonsInfo);
94 if (!frontend) {
95 return;
96 }
97 std::vector<ButtonInfo> buttons = CreateButtonInfoVector(buttonsInfo, size, SHOW_DIALOG_BUTTON_NUM_MAX);
98 std::set<std::string> callbacks;
99 callbacks.emplace("success");
100 callbacks.emplace("cancel");
101
102 auto callback = [ffiOnClick = CJLambda::Create(callbackRef)](
103 int32_t callbackType, int32_t successType) { ffiOnClick(callbackType, successType); };
104 frontend->ShowDialog(title, message, buttons, std::move(callback), callbacks);
105 }
106
FfiPromptShowActionMenu(const char * title,int32_t size,CButtonInfo * buttonsInfo,ShowActionMenuCallBack callbackRef)107 void FfiPromptShowActionMenu(
108 const char* title, int32_t size, CButtonInfo* buttonsInfo, ShowActionMenuCallBack callbackRef)
109 {
110 auto frontend = CheckFrontendLegality(size, buttonsInfo);
111 if (!frontend) {
112 return;
113 }
114 std::vector<ButtonInfo> buttons = CreateButtonInfoVector(buttonsInfo, size, SHOW_ACTION_MENU_BUTTON_NUM_MAX);
115 auto callback = [ffiOnClick = CJLambda::Create(callbackRef)](
116 int callbackType, int successType) { ffiOnClick(callbackType, successType); };
117 frontend->ShowActionMenu(title, buttons, std::move(callback));
118 }
119
FfiPromptOpenCustomDialog(void (* builder)(),NativeBaseOption options,void (* callback)(int32_t))120 void FfiPromptOpenCustomDialog(void(*builder)(), NativeBaseOption options, void(*callback)(int32_t))
121 {
122 auto frontend = AceType::DynamicCast<CJFrontendAbstract>(Utils::GetCurrentFrontend());
123 if (!frontend) {
124 LOGE("Can not get frontend.");
125 return;
126 }
127
128 auto builderFunc = [func = CJLambda::Create(builder)]() {
129 func();
130 };
131 auto callbackFunc = [func = CJLambda::Create(callback)](int32_t customId) {
132 func(customId);
133 };
134
135 std::function<void(const int32_t& info)> onWillDismiss = nullptr;
136
137 auto alignment = DIALOG_ALIGNMENT[options.alignment];
138
139 // parse maskRect
140 Dimension xDimen = Dimension(options.maskRect.x, static_cast<DimensionUnit>(options.maskRect.xUnit));
141 Dimension yDimen = Dimension(options.maskRect.y, static_cast<DimensionUnit>(options.maskRect.yUnit));
142 Dimension widthDimen =
143 Dimension(options.maskRect.width, static_cast<DimensionUnit>(options.maskRect.widthUnit));
144 Dimension heightDimen =
145 Dimension(options.maskRect.height, static_cast<DimensionUnit>(options.maskRect.heightUnit));
146 DimensionOffset offsetDimen(xDimen, yDimen);
147 auto maskRect = DimensionRect(widthDimen, heightDimen, offsetDimen);
148
149 // parse offset
150 double dxVal = options.offset.dx.value;
151 int32_t dxType = options.offset.dx.unitType;
152 CalcDimension dx = CalcDimension(dxVal, static_cast<DimensionUnit>(dxType));
153 double dyVal = options.offset.dy.value;
154 int32_t dyType = options.offset.dy.unitType;
155 CalcDimension dy = CalcDimension(dyVal, static_cast<DimensionUnit>(dyType));
156 auto offset = DimensionOffset(dx, dy);
157
158 PromptDialogAttr promptDialogAttr = {
159 .showInSubWindow = options.showInSubWindow,
160 .isModal = options.isModal,
161 .customBuilder = std::move(builderFunc),
162 .customOnWillDismiss = std::move(onWillDismiss),
163 .alignment = alignment,
164 .offset = offset,
165 .maskRect = maskRect,
166 };
167
168 frontend->OpenCustomDialog(promptDialogAttr, std::move(callbackFunc));
169 }
170
FfiPromptCloseCustomDialog(int32_t id)171 void FfiPromptCloseCustomDialog(int32_t id)
172 {
173 auto frontend = AceType::DynamicCast<CJFrontendAbstract>(Utils::GetCurrentFrontend());
174 if (!frontend) {
175 LOGE("Can not get frontend.");
176 return;
177 }
178
179 frontend->CloseCustomDialog(id);
180 }
181 }
182