1 /*
2 * Copyright (c) 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_navdestination.h"
17
18 #include "base/log/ace_scoring_log.h"
19 #include "base/memory/ace_type.h"
20 #include "base/utils/utils.h"
21 #include "bridge/declarative_frontend/engine/functions/js_function.h"
22 #include "bridge/declarative_frontend/engine/js_execution_scope_defines.h"
23 #include "bridge/declarative_frontend/engine/js_ref_ptr.h"
24 #include "bridge/declarative_frontend/engine/js_types.h"
25 #include "bridge/declarative_frontend/jsview/js_utils.h"
26 #include "core/components_ng/base/view_stack_model.h"
27 #include "core/components_ng/pattern/navrouter/navdestination_model_ng.h"
28
29 namespace OHOS::Ace {
30 std::unique_ptr<NavDestinationModel> NavDestinationModel::instance_ = nullptr;
31 std::mutex NavDestinationModel::mutex_;
32
GetInstance()33 NavDestinationModel* NavDestinationModel::GetInstance()
34 {
35 if (!instance_) {
36 std::lock_guard<std::mutex> lock(mutex_);
37 instance_.reset(new NG::NavDestinationModelNG());
38 }
39 return instance_.get();
40 }
41
42 } // namespace OHOS::Ace
43
44 namespace OHOS::Ace::Framework {
45
46 namespace {
47
ParseCommonTitle(const JSRef<JSVal> & jsValue)48 bool ParseCommonTitle(const JSRef<JSVal>& jsValue)
49 {
50 auto jsObj = JSRef<JSObject>::Cast(jsValue);
51 bool isCommonTitle = false;
52 bool hasSubTitle = false;
53 auto subtitle = jsObj->GetProperty("sub");
54 if (subtitle->IsString()) {
55 NavDestinationModel::GetInstance()->SetSubtitle(subtitle->ToString());
56 isCommonTitle = true;
57 hasSubTitle = true;
58 }
59 auto title = jsObj->GetProperty("main");
60 if (title->IsString()) {
61 NavDestinationModel::GetInstance()->SetTitle(title->ToString(), hasSubTitle);
62 isCommonTitle = true;
63 }
64
65 return isCommonTitle;
66 }
67
68 } // namespace
69
Create()70 void JSNavDestination::Create()
71 {
72 NavDestinationModel::GetInstance()->Create();
73 }
74
Create(const JSCallbackInfo & info)75 void JSNavDestination::Create(const JSCallbackInfo& info)
76 {
77 if (info.Length() <= 0 && !info[0]->IsFunction()) {
78 NavDestinationModel::GetInstance()->Create();
79 return;
80 }
81
82 auto builderFunctionJS = info[0];
83 auto builderFunc = [context = info.GetExecutionContext(), builder = std::move(builderFunctionJS)]() {
84 JAVASCRIPT_EXECUTION_SCOPE(context)
85 JSRef<JSFunc>::Cast(builder)->Call(JSRef<JSObject>());
86 };
87 NavDestinationModel::GetInstance()->Create(std::move(builderFunc));
88 }
89
SetHideTitleBar(bool hide)90 void JSNavDestination::SetHideTitleBar(bool hide)
91 {
92 NavDestinationModel::GetInstance()->SetHideTitleBar(hide);
93 }
94
SetTitle(const JSCallbackInfo & info)95 void JSNavDestination::SetTitle(const JSCallbackInfo& info)
96 {
97 if (info.Length() < 1) {
98 LOGW("The arg is wrong, it is supposed to have at least 1 argument");
99 return;
100 }
101
102 if (info[0]->IsString()) {
103 NavDestinationModel::GetInstance()->SetTitle(info[0]->ToString(), false);
104 } else if (info[0]->IsObject()) {
105 if (ParseCommonTitle(info[0])) {
106 return;
107 }
108
109 // CustomBuilder | NavigationCustomTitle
110 JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[0]);
111 JSRef<JSVal> builderObject = jsObj->GetProperty("builder");
112 if (builderObject->IsFunction()) {
113 ViewStackModel::GetInstance()->NewScope();
114 JsFunction jsBuilderFunc(info.This(), JSRef<JSObject>::Cast(builderObject));
115 ACE_SCORING_EVENT("Navdestination.title.builder");
116 jsBuilderFunc.Execute();
117 auto customNode = ViewStackModel::GetInstance()->Finish();
118 NavDestinationModel::GetInstance()->SetCustomTitle(customNode);
119 }
120 JSRef<JSVal> height = jsObj->GetProperty("height");
121 if (height->IsNumber()) {
122 if (height->ToNumber<int32_t>() == 0 || height->ToNumber<int32_t>() == 1) {
123 NavDestinationModel::GetInstance()->SetTitleHeight(height->ToNumber<int32_t>());
124 return;
125 }
126 CalcDimension titleHeight;
127 if (!JSContainerBase::ParseJsDimensionVp(height, titleHeight) || titleHeight.Value() < 0) {
128 return;
129 }
130 NavDestinationModel::GetInstance()->SetTitleHeight(titleHeight);
131 return;
132 } else {
133 CalcDimension titleHeight;
134 if (!JSContainerBase::ParseJsDimensionVp(height, titleHeight) || titleHeight.Value() <= 0) {
135 return;
136 }
137 NavDestinationModel::GetInstance()->SetTitleHeight(titleHeight);
138 }
139 } else {
140 LOGE("arg is not [String|Function].");
141 NavDestinationModel::GetInstance()->SetTitle("", false);
142 }
143 }
144
SetOnShown(const JSCallbackInfo & info)145 void JSNavDestination::SetOnShown(const JSCallbackInfo& info)
146 {
147 if (info.Length() < 1) {
148 LOGW("The arg is wrong, it is supposed to have at least one argument");
149 return;
150 }
151 if (!info[0]->IsFunction()) {
152 return;
153 }
154
155 auto onShownCallback = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
156 auto onShown = [execCtx = info.GetExecutionContext(), func = std::move(onShownCallback)]() {
157 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
158 ACE_SCORING_EVENT("NavDestination.onShown");
159 JSRef<JSVal> params[1];
160 params[0] = JSRef<JSVal>::Make(ToJSValue("undefined"));
161 func->ExecuteJS(1, params);
162 };
163 NavDestinationModel::GetInstance()->SetOnShown(std::move(onShown));
164 info.ReturnSelf();
165 }
166
SetOnHidden(const JSCallbackInfo & info)167 void JSNavDestination::SetOnHidden(const JSCallbackInfo& info)
168 {
169 if (info.Length() < 1) {
170 LOGW("The arg is wrong, it is supposed to have at least one argument");
171 return;
172 }
173 if (!info[0]->IsFunction()) {
174 return;
175 }
176 auto onHiddenCallback = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
177 auto onHidden = [execCtx = info.GetExecutionContext(), func = std::move(onHiddenCallback)]() {
178 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
179 ACE_SCORING_EVENT("NavDestination.onHidden");
180 func->ExecuteJS();
181 };
182 NavDestinationModel::GetInstance()->SetOnHidden(std::move(onHidden));
183 info.ReturnSelf();
184 }
185
SetOnBackPressed(const JSCallbackInfo & info)186 void JSNavDestination::SetOnBackPressed(const JSCallbackInfo& info)
187 {
188 if (info.Length() < 1) {
189 LOGW("The arg is wrong, it is supposed to have at least one argument");
190 return;
191 }
192 if (!info[0]->IsFunction()) {
193 return;
194 }
195 auto onBackPressedCallback = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
196 auto onBackPressed = [execCtx = info.GetExecutionContext(), func = std::move(onBackPressedCallback)]() -> bool {
197 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, false);
198 ACE_SCORING_EVENT("NavDestination.onBackPressed");
199 return (func->ExecuteJS())->ToBoolean();
200 };
201 NavDestinationModel::GetInstance()->SetOnBackPressed(std::move(onBackPressed));
202 info.ReturnSelf();
203 }
204
JSBind(BindingTarget globalObj)205 void JSNavDestination::JSBind(BindingTarget globalObj)
206 {
207 JSClass<JSNavDestination>::Declare("NavDestination");
208 JSClass<JSNavDestination>::StaticMethod("create", &JSNavDestination::Create);
209 JSClass<JSNavDestination>::StaticMethod("title", &JSNavDestination::SetTitle);
210 JSClass<JSNavDestination>::StaticMethod("hideTitleBar", &JSNavDestination::SetHideTitleBar);
211 JSClass<JSNavDestination>::StaticMethod("onShown", &JSNavDestination::SetOnShown);
212 JSClass<JSNavDestination>::StaticMethod("onHidden", &JSNavDestination::SetOnHidden);
213 JSClass<JSNavDestination>::StaticMethod("onBackPressed", &JSNavDestination::SetOnBackPressed);
214 JSClass<JSNavDestination>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
215 JSClass<JSNavDestination>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
216 JSClass<JSNavDestination>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
217 JSClass<JSNavDestination>::StaticMethod("id", &JSViewAbstract::JsId);
218 JSClass<JSNavDestination>::InheritAndBind<JSContainerBase>(globalObj);
219 }
220
221 } // namespace OHOS::Ace::Framework
222