• 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_navdestination_context.h"
26 #include "bridge/declarative_frontend/jsview/js_navigation.h"
27 #include "bridge/declarative_frontend/jsview/js_utils.h"
28 #include "core/components_ng/base/view_stack_model.h"
29 #include "core/components_ng/base/view_stack_processor.h"
30 #include "core/components_ng/pattern/navrouter/navdestination_model_ng.h"
31 
32 namespace OHOS::Ace {
33 std::unique_ptr<NavDestinationModel> NavDestinationModel::instance_ = nullptr;
34 std::mutex NavDestinationModel::mutex_;
35 
GetInstance()36 NavDestinationModel* NavDestinationModel::GetInstance()
37 {
38     if (!instance_) {
39         std::lock_guard<std::mutex> lock(mutex_);
40         instance_.reset(new NG::NavDestinationModelNG());
41     }
42     return instance_.get();
43 }
44 
45 } // namespace OHOS::Ace
46 
47 namespace OHOS::Ace::Framework {
48 
49 namespace {
50 
ParseCommonTitle(const JSRef<JSObject> & jsObj)51 bool ParseCommonTitle(const JSRef<JSObject>& jsObj)
52 {
53     JSRef<JSVal> subtitle = jsObj->GetProperty("sub");
54     JSRef<JSVal> title = jsObj->GetProperty("main");
55     bool hasSub = subtitle->IsString();
56     bool hasMain = title->IsString();
57     if (hasSub || hasMain) {
58         return NG::NavDestinationModelNG::GetInstance()->ParseCommonTitle(
59             hasSub, hasMain, subtitle->ToString(), title->ToString());
60     }
61     return false;
62 }
63 
64 } // namespace
65 
Create()66 void JSNavDestination::Create()
67 {
68     NavDestinationModel::GetInstance()->Create();
69 }
70 
Create(const JSCallbackInfo & info)71 void JSNavDestination::Create(const JSCallbackInfo& info)
72 {
73     if (info.Length() <= 0 && !info[0]->IsFunction()) {
74         NavDestinationModel::GetInstance()->Create();
75         return;
76     }
77 
78     auto builderFunctionJS = info[0];
79     auto builderFunc = [context = info.GetExecutionContext(), builder = std::move(builderFunctionJS)]() {
80         JAVASCRIPT_EXECUTION_SCOPE(context)
81         JSRef<JSFunc>::Cast(builder)->Call(JSRef<JSObject>());
82     };
83     auto ctx = AceType::MakeRefPtr<JSNavDestinationContext>();
84     auto navPathInfo = AceType::MakeRefPtr<JSNavPathInfo>();
85     ctx->SetNavPathInfo(navPathInfo);
86     NavDestinationModel::GetInstance()->Create(std::move(builderFunc), std::move(ctx));
87 }
88 
SetHideTitleBar(bool hide)89 void JSNavDestination::SetHideTitleBar(bool hide)
90 {
91     NavDestinationModel::GetInstance()->SetHideTitleBar(hide);
92 }
93 
SetTitle(const JSCallbackInfo & info)94 void JSNavDestination::SetTitle(const JSCallbackInfo& info)
95 {
96     // Resource and string type.
97     std::string title;
98     if (ParseJsString(info[0], title)) {
99         NavDestinationModel::GetInstance()->ParseCommonTitle(false, true, "", title);
100     } else if (info[0]->IsObject()) {
101         JSRef<JSObject> jsObj = JSRef<JSObject>::Cast(info[0]);
102         do {
103             // NavigationCommonTitle
104             if (ParseCommonTitle(jsObj)) {
105                 break;
106             }
107             // CustomBuilder | NavigationCustomTitle
108             CalcDimension titleHeight;
109             if (!jsObj->HasProperty("height")) {
110                 NavDestinationModel::GetInstance()->SetTitleHeight(titleHeight, false);
111                 break;
112             }
113             JSRef<JSVal> height = jsObj->GetProperty("height");
114             bool isValid = JSContainerBase::ParseJsDimensionVpNG(height, titleHeight);
115             if (height->IsString()) {
116                 std::string heightValue;
117                 ParseJsString(height, heightValue);
118                 if (heightValue == NG::TITLE_MAIN_WITH_SUB) {
119                     NavDestinationModel::GetInstance()->SetTitleHeight(NG::DOUBLE_LINE_TITLEBAR_HEIGHT);
120                     break;
121                 }
122                 if (heightValue == NG::TITLE_MAIN) {
123                     NavDestinationModel::GetInstance()->SetTitleHeight(NG::SINGLE_LINE_TITLEBAR_HEIGHT);
124                     break;
125                 }
126             }
127             if (!isValid || titleHeight.Value() < 0) {
128                 NavDestinationModel::GetInstance()->SetTitleHeight(Dimension(), true);
129                 break;
130             }
131             NavDestinationModel::GetInstance()->SetTitleHeight(titleHeight);
132         } while (0);
133         JSRef<JSVal> builderObject = jsObj->GetProperty("builder");
134         if (builderObject->IsFunction()) {
135             ViewStackModel::GetInstance()->NewScope();
136             JsFunction jsBuilderFunc(info.This(), JSRef<JSObject>::Cast(builderObject));
137             ACE_SCORING_EVENT("Navdestination.title.builder");
138             jsBuilderFunc.Execute();
139             auto customNode = ViewStackModel::GetInstance()->Finish();
140             NavDestinationModel::GetInstance()->SetCustomTitle(customNode);
141         }
142     } else {
143         TAG_LOGI(AceLogTag::ACE_NAVIGATION, "SetTitle is undefined");
144         NavDestinationModel::GetInstance()->ParseCommonTitle(false, false, "", "");
145     }
146 }
147 
SetBackButtonIcon(const JSCallbackInfo & info)148 void JSNavDestination::SetBackButtonIcon(const JSCallbackInfo& info)
149 {
150     // srcType、pixmap、string
151     if (info.Length() < 1) {
152         return;
153     }
154     std::string src;
155     auto noPixMap = ParseJsMedia(info[0], src);
156 
157     RefPtr<PixelMap> pixMap = nullptr;
158 #if defined(PIXEL_MAP_SUPPORTED)
159     if (!noPixMap) {
160         pixMap = CreatePixelMapFromNapiValue(info[0]);
161     }
162 #endif
163     std::string bundleName;
164     std::string moduleName;
165     GetJsMediaBundleInfo(info[0], bundleName, moduleName);
166     NavDestinationModel::GetInstance()->SetBackButtonIcon(src, noPixMap, pixMap, bundleName, moduleName);
167 }
168 
SetOnShown(const JSCallbackInfo & info)169 void JSNavDestination::SetOnShown(const JSCallbackInfo& info)
170 {
171     if (!info[0]->IsFunction()) {
172         return;
173     }
174 
175     auto onShownCallback = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
176     WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
177     auto onShown = [execCtx = info.GetExecutionContext(), func = std::move(onShownCallback), node = targetNode]() {
178         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
179         ACE_SCORING_EVENT("NavDestination.onShown");
180         PipelineContext::SetCallBackNode(node);
181         JSRef<JSVal> params[1];
182         params[0] = JSRef<JSVal>::Make(ToJSValue("undefined"));
183         func->ExecuteJS(1, params);
184     };
185     NavDestinationModel::GetInstance()->SetOnShown(std::move(onShown));
186     info.ReturnSelf();
187 }
188 
SetOnHidden(const JSCallbackInfo & info)189 void JSNavDestination::SetOnHidden(const JSCallbackInfo& info)
190 {
191     if (!info[0]->IsFunction()) {
192         return;
193     }
194     auto onHiddenCallback = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
195     WeakPtr<NG::FrameNode> targetNode = NG::ViewStackProcessor::GetInstance()->GetMainFrameNode();
196     auto onHidden = [execCtx = info.GetExecutionContext(), func = std::move(onHiddenCallback), node = targetNode]() {
197         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
198         ACE_SCORING_EVENT("NavDestination.onHidden");
199         PipelineContext::SetCallBackNode(node);
200         func->ExecuteJS();
201     };
202     NavDestinationModel::GetInstance()->SetOnHidden(std::move(onHidden));
203     info.ReturnSelf();
204 }
205 
SetOnBackPressed(const JSCallbackInfo & info)206 void JSNavDestination::SetOnBackPressed(const JSCallbackInfo& info)
207 {
208     if (!info[0]->IsFunction()) {
209         return;
210     }
211     auto onBackPressedCallback = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
212     auto onBackPressed = [execCtx = info.GetExecutionContext(), func = std::move(onBackPressedCallback)]() -> bool {
213         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx, false);
214         ACE_SCORING_EVENT("NavDestination.onBackPressed");
215         return (func->ExecuteJS())->ToBoolean();
216     };
217     NavDestinationModel::GetInstance()->SetOnBackPressed(std::move(onBackPressed));
218     info.ReturnSelf();
219 }
220 
SetOnReady(const JSCallbackInfo & info)221 void JSNavDestination::SetOnReady(const JSCallbackInfo& info)
222 {
223     if (!info[0]->IsFunction()) {
224         return;
225     }
226     auto onReadyCallback = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(info[0]));
227     auto onReady = [execCtx = info.GetExecutionContext(), func = std::move(onReadyCallback)](
228                        RefPtr<NG::NavDestinationContext> context) {
229         auto jsContext = AceType::DynamicCast<JSNavDestinationContext>(context);
230         CHECK_NULL_VOID(jsContext);
231         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
232         ACE_SCORING_EVENT("NavDestination.onReady");
233         JSRef<JSVal> params[1];
234         params[0] = jsContext->CreateJSObject();
235         func->ExecuteJS(1, params);
236     };
237     NavDestinationModel::GetInstance()->SetOnReady(std::move(onReady));
238     info.ReturnSelf();
239 }
240 
SetMode(const JSCallbackInfo & info)241 void JSNavDestination::SetMode(const JSCallbackInfo& info)
242 {
243     if (!info[0]->IsNumber()) {
244         // set default back ground color
245         NavDestinationModel::GetInstance()->SetNavDestinationMode(NG::NavDestinationMode::STANDARD);
246         return;
247     }
248     auto mode = info[0]->ToNumber<int32_t>();
249     NavDestinationModel::GetInstance()->SetNavDestinationMode(static_cast<NG::NavDestinationMode>(mode));
250 }
251 
JSBind(BindingTarget globalObj)252 void JSNavDestination::JSBind(BindingTarget globalObj)
253 {
254     JSClass<JSNavDestination>::Declare("NavDestination");
255     JSClass<JSNavDestination>::StaticMethod("create", &JSNavDestination::Create);
256     JSClass<JSNavDestination>::StaticMethod("title", &JSNavDestination::SetTitle);
257     JSClass<JSNavDestination>::StaticMethod("hideTitleBar", &JSNavDestination::SetHideTitleBar);
258     JSClass<JSNavDestination>::StaticMethod("backButtonIcon", &JSNavDestination::SetBackButtonIcon);
259     JSClass<JSNavDestination>::StaticMethod("onShown", &JSNavDestination::SetOnShown);
260     JSClass<JSNavDestination>::StaticMethod("onHidden", &JSNavDestination::SetOnHidden);
261     JSClass<JSNavDestination>::StaticMethod("onBackPressed", &JSNavDestination::SetOnBackPressed);
262     JSClass<JSNavDestination>::StaticMethod("onReady", &JSNavDestination::SetOnReady);
263     JSClass<JSNavDestination>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
264     JSClass<JSNavDestination>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
265     JSClass<JSNavDestination>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
266     JSClass<JSNavDestination>::StaticMethod("id", &JSViewAbstract::JsId);
267     JSClass<JSNavDestination>::StaticMethod("mode", &JSNavDestination::SetMode);
268     JSClass<JSNavDestination>::InheritAndBind<JSContainerBase>(globalObj);
269 }
270 
271 } // namespace OHOS::Ace::Framework
272