1 /*
2  * Copyright (c) 2021-2023 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 "bridge/declarative_frontend/jsview/js_pattern_lock.h"
17 
18 #include "bridge/declarative_frontend/jsview/models/patternlock_model_impl.h"
19 #include "bridge/declarative_frontend/view_stack_processor.h"
20 #include "bridge/declarative_frontend/ark_theme/theme_apply/js_pattern_lock_theme.h"
21 #include "core/components_ng/base/view_stack_processor.h"
22 #include "core/components_ng/pattern/patternlock/patternlock_model_ng.h"
23 #include "core/components_v2/pattern_lock/pattern_lock_component.h"
24 
25 namespace OHOS::Ace {
26 
27 std::unique_ptr<PatternLockModel> PatternLockModel::instance_ = nullptr;
28 std::mutex PatternLockModel::mutex_;
29 const std::vector<V2::PatternLockChallengeResult> CHALLENGE_RESULT = { V2::PatternLockChallengeResult::CORRECT,
30     V2::PatternLockChallengeResult::WRONG };
31 
GetInstance()32 PatternLockModel* PatternLockModel::GetInstance()
33 {
34     if (!instance_) {
35         std::lock_guard<std::mutex> lock(mutex_);
36         if (!instance_) {
37 #ifdef NG_BUILD
38             instance_.reset(new NG::PatternLockModelNG());
39 #else
40             if (Container::IsCurrentUseNewPipeline()) {
41                 instance_.reset(new NG::PatternLockModelNG());
42             } else {
43                 instance_.reset(new Framework::PatternLockModelImpl());
44             }
45 #endif
46         }
47     }
48     return instance_.get();
49 }
50 
51 } // namespace OHOS::Ace
52 
53 namespace OHOS::Ace::Framework {
ChoosePointToJSValue(std::vector<int> input)54 JSRef<JSArray> JSPatternLock::ChoosePointToJSValue(std::vector<int> input)
55 {
56     JSRef<JSArray> arr = JSRef<JSArray>::New();
57     for (size_t i = 0; i < input.size(); i++) {
58         arr->SetValueAt(i, ConvertToJSValue(input[i]));
59     }
60     return arr;
61 }
Create(const JSCallbackInfo & info)62 void JSPatternLock::Create(const JSCallbackInfo& info)
63 {
64     auto controller = PatternLockModel::GetInstance()->Create();
65     JSPatternLockTheme::ApplyTheme();
66 
67     if (info.Length() > 0 && info[0]->IsObject()) {
68         auto* jsController = JSRef<JSObject>::Cast(info[0])->Unwrap<JSPatternLockController>();
69         if (jsController) {
70             jsController->SetController(controller);
71         }
72     }
73 }
JSBind(BindingTarget globalObj)74 void JSPatternLock::JSBind(BindingTarget globalObj)
75 {
76     JSClass<JSPatternLock>::Declare("PatternLock");
77     MethodOptions opt = MethodOptions::NONE;
78     JSClass<JSPatternLock>::StaticMethod("create", &JSPatternLock::Create, opt);
79     JSClass<JSPatternLock>::StaticMethod("onPatternComplete", &JSPatternLock::SetPatternComplete);
80     JSClass<JSPatternLock>::StaticMethod("regularColor", &JSPatternLock::SetRegularColor, MethodOptions::NONE);
81     JSClass<JSPatternLock>::StaticMethod("selectedColor", &JSPatternLock::SetSelectedColor, MethodOptions::NONE);
82     JSClass<JSPatternLock>::StaticMethod("activeColor", &JSPatternLock::SetActiveColor, MethodOptions::NONE);
83     JSClass<JSPatternLock>::StaticMethod("pathColor", &JSPatternLock::SetPathColor, MethodOptions::NONE);
84     JSClass<JSPatternLock>::StaticMethod("pathStrokeWidth", &JSPatternLock::SetPathStrokeWidth);
85     JSClass<JSPatternLock>::StaticMethod("circleRadius", &JSPatternLock::SetCircleRadius, MethodOptions::NONE);
86     JSClass<JSPatternLock>::StaticMethod("sideLength", &JSPatternLock::SetSideLength, MethodOptions::NONE);
87     JSClass<JSPatternLock>::StaticMethod("autoReset", &JSPatternLock::SetAutoReset, MethodOptions::NONE);
88     JSClass<JSPatternLock>::StaticMethod("activateCircleStyle", &JSPatternLock::SetActivateCircleStyle);
89     JSClass<JSPatternLock>::StaticMethod("onDotConnect", &JSPatternLock::SetDotConnect);
90     JSClass<JSPatternLock>::StaticMethod("onDetach", &JSInteractableView::JsOnDetach);
91     JSClass<JSPatternLock>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
92     JSClass<JSPatternLock>::StaticMethod("onAttach", &JSInteractableView::JsOnAttach);
93     JSClass<JSPatternLock>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
94     JSClass<JSPatternLock>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
95     JSClass<JSPatternLock>::InheritAndBind<JSViewAbstract>(globalObj);
96 }
SetDefaultTheme(OHOS::Ace::RefPtr<OHOS::Ace::V2::PatternLockComponent> & patternLock)97 void JSPatternLock::SetDefaultTheme(OHOS::Ace::RefPtr<OHOS::Ace::V2::PatternLockComponent>& patternLock)
98 {
99     auto lockTheme = GetTheme<V2::PatternLockTheme>();
100     if (!lockTheme) {
101         return;
102     }
103     patternLock->SetRegularColor(lockTheme->GetRegularColor());
104     patternLock->SetSelectedColor(lockTheme->GetSelectedColor());
105     patternLock->SetActiveColor(lockTheme->GetActiveColor());
106     patternLock->SetPathColor(lockTheme->GetPathColor());
107 }
108 
SetPatternComplete(const JSCallbackInfo & args)109 void JSPatternLock::SetPatternComplete(const JSCallbackInfo& args)
110 {
111     if (!args[0]->IsFunction()) {
112         return;
113     }
114 
115     auto onComplete = [execCtx = args.GetExecutionContext(), func = JSRef<JSFunc>::Cast(args[0])](
116                           const BaseEventInfo* event) {
117         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
118         const auto* eventInfo = TypeInfoHelper::DynamicCast<V2::PatternCompleteEvent>(event);
119         CHECK_NULL_VOID(eventInfo);
120         JSRef<JSVal> params[] = { ChoosePointToJSValue(eventInfo->GetInput()) };
121         func->Call(JSRef<JSObject>(), ArraySize(params), params);
122     };
123 
124     PatternLockModel::GetInstance()->SetPatternComplete(std::move(onComplete));
125 }
SetSelectedColor(const JSCallbackInfo & info)126 void JSPatternLock::SetSelectedColor(const JSCallbackInfo& info)
127 {
128     if (info.Length() < 1) {
129         return;
130     }
131     Color selectedColor;
132     if (!ParseJsColor(info[0], selectedColor)) {
133         RefPtr<V2::PatternLockTheme> patternLockTheme = GetTheme<V2::PatternLockTheme>();
134         CHECK_NULL_VOID(patternLockTheme);
135         selectedColor = patternLockTheme->GetSelectedColor();
136     }
137 
138     PatternLockModel::GetInstance()->SetSelectedColor(selectedColor);
139 }
SetAutoReset(const JSCallbackInfo & info)140 void JSPatternLock::SetAutoReset(const JSCallbackInfo& info)
141 {
142     if (info.Length() < 1) {
143         return;
144     }
145     if (!info[0]->IsBoolean()) {
146         PatternLockModel::GetInstance()->SetAutoReset(true);
147         return;
148     }
149     PatternLockModel::GetInstance()->SetAutoReset(info[0]->ToBoolean());
150 }
151 
SetPathColor(const JSCallbackInfo & info)152 void JSPatternLock::SetPathColor(const JSCallbackInfo& info)
153 {
154     if (info.Length() < 1) {
155         return;
156     }
157     Color pathColor;
158     if (!ParseJsColor(info[0], pathColor)) {
159         RefPtr<V2::PatternLockTheme> patternLockTheme = GetTheme<V2::PatternLockTheme>();
160         CHECK_NULL_VOID(patternLockTheme);
161         pathColor = patternLockTheme->GetPathColor();
162     }
163 
164     PatternLockModel::GetInstance()->SetPathColor(pathColor);
165 }
SetActiveColor(const JSCallbackInfo & info)166 void JSPatternLock::SetActiveColor(const JSCallbackInfo& info)
167 {
168     if (info.Length() < 1) {
169         return;
170     }
171     Color activeColor;
172     if (!ParseJsColor(info[0], activeColor)) {
173         RefPtr<V2::PatternLockTheme> patternLockTheme = GetTheme<V2::PatternLockTheme>();
174         CHECK_NULL_VOID(patternLockTheme);
175         activeColor = patternLockTheme->GetActiveColor();
176     }
177 
178     PatternLockModel::GetInstance()->SetActiveColor(activeColor);
179 }
SetRegularColor(const JSCallbackInfo & info)180 void JSPatternLock::SetRegularColor(const JSCallbackInfo& info)
181 {
182     if (info.Length() < 1) {
183         return;
184     }
185     Color regularColor;
186     if (!ParseJsColor(info[0], regularColor)) {
187         RefPtr<V2::PatternLockTheme> patternLockTheme = GetTheme<V2::PatternLockTheme>();
188         CHECK_NULL_VOID(patternLockTheme);
189         regularColor = patternLockTheme->GetRegularColor();
190     }
191 
192     PatternLockModel::GetInstance()->SetRegularColor(regularColor);
193 }
SetCircleRadius(const JSCallbackInfo & info)194 void JSPatternLock::SetCircleRadius(const JSCallbackInfo& info)
195 {
196     if (info.Length() < 1) {
197         return;
198     }
199     CalcDimension radius;
200     if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
201         if (!ParseJsDimensionVp(info[0], radius)) {
202             return;
203         }
204         if (radius.IsNonNegative()) {
205             PatternLockModel::GetInstance()->SetCircleRadius(radius);
206         }
207     } else {
208         if (!ParseJsDimensionVp(info[0], radius) || radius.IsNonPositive()) {
209             RefPtr<V2::PatternLockTheme> patternLockTheme = GetTheme<V2::PatternLockTheme>();
210             CHECK_NULL_VOID(patternLockTheme);
211             radius = patternLockTheme->GetCircleRadius();
212         }
213         PatternLockModel::GetInstance()->SetCircleRadius(radius);
214     }
215 }
SetSideLength(const JSCallbackInfo & info)216 void JSPatternLock::SetSideLength(const JSCallbackInfo& info)
217 {
218     if (info.Length() < 1) {
219         return;
220     }
221     CalcDimension sideLength;
222     if (!ParseJsDimensionVp(info[0], sideLength)) {
223         RefPtr<V2::PatternLockTheme> patternLockTheme = GetTheme<V2::PatternLockTheme>();
224         CHECK_NULL_VOID(patternLockTheme);
225         sideLength = patternLockTheme->GetSideLength();
226     }
227 
228     PatternLockModel::GetInstance()->SetSideLength(sideLength);
229 }
SetPathStrokeWidth(const JSCallbackInfo & info)230 void JSPatternLock::SetPathStrokeWidth(const JSCallbackInfo& info)
231 {
232     if (info.Length() < 1) {
233         return;
234     }
235     CalcDimension lineWidth;
236     if (!ParseJsDimensionVp(info[0], lineWidth)) {
237         RefPtr<V2::PatternLockTheme> patternLockTheme = GetTheme<V2::PatternLockTheme>();
238         CHECK_NULL_VOID(patternLockTheme);
239         lineWidth = patternLockTheme->GetPathStrokeWidth();
240     }
241 
242     PatternLockModel::GetInstance()->SetStrokeWidth(lineWidth);
243 }
SetDotConnect(const JSCallbackInfo & args)244 void JSPatternLock::SetDotConnect(const JSCallbackInfo& args)
245 {
246     if (!args[0]->IsFunction()) {
247         return;
248     }
249 
250     auto jsFunc = AceType::MakeRefPtr<JsFunction>(JSRef<JSObject>(), JSRef<JSFunc>::Cast(args[0]));
251     WeakPtr<NG::FrameNode> targetNode = AceType::WeakClaim(NG::ViewStackProcessor::GetInstance()->GetMainFrameNode());
252     auto onDotConnect = [execCtx = args.GetExecutionContext(), func = std::move(jsFunc), node = targetNode](
253                             int32_t code) {
254         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
255         PipelineContext::SetCallBackNode(node);
256         JSRef<JSVal> newJSVal = JSRef<JSVal>::Make(ToJSValue(code));
257         func->ExecuteJS(1, &newJSVal);
258     };
259 
260     PatternLockModel::GetInstance()->SetDotConnect(std::move(onDotConnect));
261 }
SetActiveCircleColor(const JSRef<JSVal> & info)262 void JSPatternLock::SetActiveCircleColor(const JSRef<JSVal>& info)
263 {
264     Color activeColor;
265     if (!ParseJsColor(info, activeColor)) {
266         activeColor = Color::TRANSPARENT;
267     }
268     PatternLockModel::GetInstance()->SetActiveCircleColor(activeColor);
269 }
SetActiveCircleRadius(const JSRef<JSVal> & info)270 void JSPatternLock::SetActiveCircleRadius(const JSRef<JSVal>& info)
271 {
272     CalcDimension radius;
273     if (!ParseLengthMetricsToPositiveDimension(info, radius) || radius.IsNonPositive()) {
274         radius = Dimension(0.0f, DimensionUnit::VP);
275     }
276     PatternLockModel::GetInstance()->SetActiveCircleRadius(radius);
277 }
SetEnableWaveEffect(const JSRef<JSVal> & info)278 void JSPatternLock::SetEnableWaveEffect(const JSRef<JSVal>& info)
279 {
280     if (!info->IsBoolean()) {
281         PatternLockModel::GetInstance()->SetEnableWaveEffect(true);
282         return;
283     }
284     PatternLockModel::GetInstance()->SetEnableWaveEffect(info->ToBoolean());
285 }
SetActivateCircleStyle(const JSCallbackInfo & info)286 void JSPatternLock::SetActivateCircleStyle(const JSCallbackInfo& info)
287 {
288     if (info.Length() < 1 || info[0]->IsNull() || !info[0]->IsObject()) {
289         PatternLockModel::GetInstance()->SetActiveCircleColor(Color::TRANSPARENT);
290         PatternLockModel::GetInstance()->SetActiveCircleRadius(Dimension(0.0f, DimensionUnit::VP));
291         PatternLockModel::GetInstance()->SetEnableWaveEffect(true);
292         return;
293     }
294     auto paramObject = JSRef<JSObject>::Cast(info[0]);
295     JSRef<JSVal> jsColor = paramObject->GetProperty("color");
296     JSRef<JSVal> jsRadius = paramObject->GetProperty("radius");
297     JSRef<JSVal> jsEnable = paramObject->GetProperty("enableWaveEffect");
298     SetActiveCircleColor(jsColor);
299     SetActiveCircleRadius(jsRadius);
300     SetEnableWaveEffect(jsEnable);
301 }
JSBind(BindingTarget globalObj)302 void JSPatternLockController::JSBind(BindingTarget globalObj)
303 {
304     JSClass<JSPatternLockController>::Declare("PatternLockController");
305     JSClass<JSPatternLockController>::CustomMethod("reset", &JSPatternLockController::Reset);
306     JSClass<JSPatternLockController>::CustomMethod("setChallengeResult", &JSPatternLockController::SetChallengeResult);
307     JSClass<JSPatternLockController>::Bind(
308         globalObj, JSPatternLockController::Constructor, JSPatternLockController::Destructor);
309 }
Reset(const JSCallbackInfo & args)310 void JSPatternLockController::Reset(const JSCallbackInfo& args)
311 {
312     if (controller_) {
313         controller_->Reset();
314     }
315 }
SetChallengeResult(const JSCallbackInfo & args)316 void JSPatternLockController::SetChallengeResult(const JSCallbackInfo& args)
317 {
318     if (controller_) {
319         if (!args[0]->IsNumber()) {
320             return;
321         }
322         int32_t value = args[0]->ToNumber<int32_t>();
323         if (value >= 1 && value <= static_cast<int32_t>(CHALLENGE_RESULT.size())) {
324             controller_->SetChallengeResult(CHALLENGE_RESULT[value - 1]);
325         }
326     }
327 }
Constructor(const JSCallbackInfo & args)328 void JSPatternLockController::Constructor(const JSCallbackInfo& args)
329 {
330     auto controller = Referenced::MakeRefPtr<JSPatternLockController>();
331     controller->IncRefCount();
332     args.SetReturnValue(Referenced::RawPtr(controller));
333 }
Destructor(JSPatternLockController * controller)334 void JSPatternLockController::Destructor(JSPatternLockController* controller)
335 {
336     if (controller != nullptr) {
337         controller->DecRefCount();
338     }
339 }
340 } // namespace OHOS::Ace::Framework
341