1 /*
2 * Copyright (c) 2021-2022 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 "frameworks/bridge/declarative_frontend/jsview/js_form.h"
17
18 #include "base/geometry/dimension.h"
19 #include "base/geometry/ng/size_t.h"
20 #include "base/log/ace_scoring_log.h"
21 #include "base/log/log_wrapper.h"
22 #include "base/utils/string_utils.h"
23 #include "bridge/declarative_frontend/jsview/models/form_model_impl.h"
24 #include "core/components_ng/base/view_abstract.h"
25 #include "core/components_ng/pattern/form/form_model_ng.h"
26 #include "frameworks/bridge/declarative_frontend/jsview/js_utils.h"
27 #include "frameworks/bridge/declarative_frontend/view_stack_processor.h"
28
29 #if !defined(WEARABLE_PRODUCT)
30 #include "frameworks/core/components/form/form_component.h"
31 #endif
32
33 namespace OHOS::Ace {
34
35 std::unique_ptr<FormModel> FormModel::instance_ = nullptr;
36 std::mutex FormModel::mutex_;
37
GetInstance()38 FormModel* FormModel::GetInstance()
39 {
40 if (!instance_) {
41 std::lock_guard<std::mutex> lock(mutex_);
42 if (!instance_) {
43 #ifdef NG_BUILD
44 instance_.reset(new NG::FormModelNG());
45 #else
46 if (Container::IsCurrentUseNewPipeline()) {
47 instance_.reset(new NG::FormModelNG());
48 } else {
49 instance_.reset(new Framework::FormModelImpl());
50 }
51 #endif
52 }
53 }
54 return instance_.get();
55 }
56
57 } // namespace OHOS::Ace
58
59 namespace OHOS::Ace::Framework {
60
Create(const JSCallbackInfo & info)61 void JSForm::Create(const JSCallbackInfo& info)
62 {
63 if (info.Length() == 0 || !info[0]->IsObject()) {
64 return;
65 }
66 auto obj = JSRef<JSObject>::Cast(info[0]);
67 JSRef<JSVal> id = obj->GetProperty("id");
68 JSRef<JSVal> name = obj->GetProperty("name");
69 JSRef<JSVal> bundle = obj->GetProperty("bundle");
70 JSRef<JSVal> ability = obj->GetProperty("ability");
71 JSRef<JSVal> module = obj->GetProperty("module");
72 JSRef<JSVal> dimension = obj->GetProperty("dimension");
73 JSRef<JSVal> temporary = obj->GetProperty("temporary");
74 JSRef<JSVal> wantValue = obj->GetProperty("want");
75 JSRef<JSVal> renderingMode = obj->GetProperty("renderingMode");
76 JSRef<JSVal> shape = obj->GetProperty("shape");
77 RequestFormInfo formInfo;
78 if (id->IsString()) {
79 if (!StringUtils::IsNumber(id->ToString())) {
80 LOGE("Invalid form id : %{public}s", id->ToString().c_str());
81 return;
82 }
83 int64_t inputFormId = StringUtils::StringToLongInt(id->ToString().c_str(), -1);
84 if (inputFormId == -1) {
85 LOGE("StringToLongInt failed : %{public}s", id->ToString().c_str());
86 return;
87 }
88 formInfo.id = inputFormId;
89 } else if (id->IsNumber()) {
90 formInfo.id = id->ToNumber<int64_t>();
91 }
92 LOGI("JSForm Create, info.id: %{public}" PRId64, formInfo.id);
93 formInfo.cardName = name->ToString();
94 formInfo.bundleName = bundle->ToString();
95 formInfo.abilityName = ability->ToString();
96 formInfo.moduleName = module->ToString();
97 if (!dimension->IsNull() && !dimension->IsEmpty()) {
98 formInfo.dimension = dimension->ToNumber<int32_t>();
99 }
100 formInfo.temporary = temporary->ToBoolean();
101 if (!wantValue->IsNull() && wantValue->IsObject()) {
102 formInfo.wantWrap = CreateWantWrapFromNapiValue(wantValue);
103 }
104 if (!renderingMode->IsNull() && !renderingMode->IsEmpty()) {
105 formInfo.renderingMode = renderingMode->ToNumber<int32_t>();
106 }
107 if (!shape->IsNull() && !shape->IsEmpty()) {
108 formInfo.shape = shape->ToNumber<int32_t>();
109 }
110 FormModel::GetInstance()->Create(formInfo);
111 }
112
SetSize(const JSCallbackInfo & info)113 void JSForm::SetSize(const JSCallbackInfo& info)
114 {
115 JSViewAbstract::JsSize(info);
116
117 if (info.Length() == 0 || !info[0]->IsObject()) {
118 return;
119 }
120 Dimension width = 0.0_vp;
121 Dimension height = 0.0_vp;
122
123 JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(info[0]);
124 JSRef<JSVal> widthValue = sizeObj->GetProperty("width");
125 if (!widthValue->IsNull() && !widthValue->IsEmpty()) {
126 if (widthValue->IsNumber()) {
127 width = Dimension(widthValue->ToNumber<double>(), DimensionUnit::VP);
128 } else if (widthValue->IsString()) {
129 width = StringUtils::StringToDimension(widthValue->ToString(), true);
130 }
131 }
132
133 JSRef<JSVal> heightValue = sizeObj->GetProperty("height");
134 if (!heightValue->IsNull() && !heightValue->IsEmpty()) {
135 if (heightValue->IsNumber()) {
136 height = Dimension(heightValue->ToNumber<double>(), DimensionUnit::VP);
137 } else if (heightValue->IsString()) {
138 height = StringUtils::StringToDimension(heightValue->ToString(), true);
139 }
140 }
141 FormModel::GetInstance()->SetSize(width, height);
142 }
143
SetDimension(int32_t value)144 void JSForm::SetDimension(int32_t value)
145 {
146 FormModel::GetInstance()->SetDimension(value);
147 }
148
AllowUpdate(const JSCallbackInfo & info)149 void JSForm::AllowUpdate(const JSCallbackInfo& info)
150 {
151 if (info.Length() <= 0 || !info[0]->IsBoolean()) {
152 return;
153 }
154
155 auto allowUpdate = info[0]->ToBoolean();
156 FormModel::GetInstance()->AllowUpdate(allowUpdate);
157 }
158
SetVisibility(const JSCallbackInfo & info)159 void JSForm::SetVisibility(const JSCallbackInfo& info)
160 {
161 if (info.Length() <= 0 || !info[0]->IsNumber()) {
162 return;
163 }
164
165 auto type = info[0]->ToNumber<int32_t>();
166 FormModel::GetInstance()->SetVisibility(VisibleType(type));
167 }
168
SetModuleName(const JSCallbackInfo & info)169 void JSForm::SetModuleName(const JSCallbackInfo& info)
170 {
171 if (info.Length() <= 0 || !info[0]->IsString()) {
172 return;
173 }
174
175 auto moduleName = info[0]->ToString();
176 FormModel::GetInstance()->SetModuleName(moduleName);
177 }
178
JsOnAcquired(const JSCallbackInfo & info)179 void JSForm::JsOnAcquired(const JSCallbackInfo& info)
180 {
181 if (info[0]->IsFunction()) {
182 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
183 auto onAcquired = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
184 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
185 ACE_SCORING_EVENT("Form.onAcquired");
186 std::vector<std::string> keys = { "id", "idString" };
187 func->Execute(keys, param);
188 };
189 FormModel::GetInstance()->SetOnAcquired(std::move(onAcquired));
190 }
191 }
192
JsOnError(const JSCallbackInfo & info)193 void JSForm::JsOnError(const JSCallbackInfo& info)
194 {
195 if (info[0]->IsFunction()) {
196 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
197 auto onError = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
198 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
199 ACE_SCORING_EVENT("Form.onError");
200 std::vector<std::string> keys = { "errcode", "msg" };
201 func->Execute(keys, param);
202 };
203 FormModel::GetInstance()->SetOnError(std::move(onError));
204 }
205 }
206
JsOnUninstall(const JSCallbackInfo & info)207 void JSForm::JsOnUninstall(const JSCallbackInfo& info)
208 {
209 if (info[0]->IsFunction()) {
210 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
211 auto onUninstall = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
212 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
213 ACE_SCORING_EVENT("Form.onUninstall");
214 std::vector<std::string> keys = { "id", "idString" };
215 func->Execute(keys, param);
216 };
217 FormModel::GetInstance()->SetOnUninstall(std::move(onUninstall));
218 }
219 }
220
JsOnRouter(const JSCallbackInfo & info)221 void JSForm::JsOnRouter(const JSCallbackInfo& info)
222 {
223 if (info[0]->IsFunction()) {
224 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
225 auto onRouter = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
226 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
227 ACE_SCORING_EVENT("Form.onRouter");
228 std::vector<std::string> keys = { "action" };
229 func->Execute(keys, param);
230 };
231 FormModel::GetInstance()->SetOnRouter(std::move(onRouter));
232 }
233 }
234
JsOnLoad(const JSCallbackInfo & info)235 void JSForm::JsOnLoad(const JSCallbackInfo& info)
236 {
237 if (info[0]->IsFunction()) {
238 auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
239 auto onLoad = [execCtx = info.GetExecutionContext(), func = std::move(jsFunc)](const std::string& param) {
240 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
241 ACE_SCORING_EVENT("Form.onLoad");
242 std::vector<std::string> keys;
243 func->Execute(keys, param);
244 };
245 FormModel::GetInstance()->SetOnLoad(std::move(onLoad));
246 }
247 }
248
JsObscured(const JSCallbackInfo & info)249 void JSForm::JsObscured(const JSCallbackInfo& info)
250 {
251 if (info[0]->IsUndefined()) {
252 LOGE("Obscured reasons undefined");
253 return;
254 }
255 if (!info[0]->IsArray()) {
256 LOGE("Obscured reasons not Array");
257 return;
258 }
259 auto obscuredArray = JSRef<JSArray>::Cast(info[0]);
260 size_t size = obscuredArray->Length();
261 std::vector<ObscuredReasons> reasons;
262 reasons.reserve(size);
263 for (size_t i = 0; i < size; ++i) {
264 JSRef<JSVal> reason = obscuredArray->GetValueAt(i);
265 if (reason->IsNumber()) {
266 reasons.push_back(static_cast<ObscuredReasons>(reason->ToNumber<int32_t>()));
267 }
268 }
269 FormModel::GetInstance()->SetObscured(reasons);
270 }
271
JSBind(BindingTarget globalObj)272 void JSForm::JSBind(BindingTarget globalObj)
273 {
274 JSClass<JSForm>::Declare("FormComponent");
275 MethodOptions opt = MethodOptions::NONE;
276 JSClass<JSForm>::StaticMethod("create", &JSForm::Create, opt);
277 JSClass<JSForm>::StaticMethod("size", &JSForm::SetSize, opt);
278 JSClass<JSForm>::StaticMethod("dimension", &JSForm::SetDimension, opt);
279 JSClass<JSForm>::StaticMethod("allowUpdate", &JSForm::AllowUpdate, opt);
280 JSClass<JSForm>::StaticMethod("visibility", &JSForm::SetVisibility, opt);
281 JSClass<JSForm>::StaticMethod("moduleName", &JSForm::SetModuleName, opt);
282 JSClass<JSForm>::StaticMethod("clip", &JSViewAbstract::JsClip, opt);
283 JSClass<JSForm>::StaticMethod("obscured", &JSForm::JsObscured);
284
285 JSClass<JSForm>::StaticMethod("onAcquired", &JSForm::JsOnAcquired);
286 JSClass<JSForm>::StaticMethod("onError", &JSForm::JsOnError);
287 JSClass<JSForm>::StaticMethod("onUninstall", &JSForm::JsOnUninstall);
288 JSClass<JSForm>::StaticMethod("onRouter", &JSForm::JsOnRouter);
289 JSClass<JSForm>::StaticMethod("onLoad", &JSForm::JsOnLoad);
290 JSClass<JSForm>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
291 JSClass<JSForm>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
292 JSClass<JSForm>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
293 JSClass<JSForm>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
294 JSClass<JSForm>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
295 JSClass<JSForm>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
296 JSClass<JSForm>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
297 JSClass<JSForm>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
298
299 JSClass<JSForm>::InheritAndBind<JSViewAbstract>(globalObj);
300 }
301
302 } // namespace OHOS::Ace::Framework
303