• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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