1 /*
2  * Copyright (c) 2024 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 <string>
17 
18 #include "base/memory/referenced.h"
19 #include "core/components_ng/syntax/repeat_model_ng.h"
20 #include "bridge/declarative_frontend/jsview/js_repeat.h"
21 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
22 
23 
24 namespace OHOS::Ace {
GetInstance()25 RepeatModel* RepeatModel::GetInstance()
26 {
27     static NG::RepeatModelNG instance;
28     return &instance;
29 }
30 } // namespace OHOS::Ace
31 
32 
33 namespace OHOS::Ace::Framework {
34 
StartRender()35 void JSRepeat::StartRender()
36 {
37     RepeatModel::GetInstance()->StartRender();
38 }
39 
FinishRender(const JSCallbackInfo & info)40 void JSRepeat::FinishRender(const JSCallbackInfo& info)
41 {
42     std::list<int32_t> removedElmtIds;
43 
44     if ((info.Length() != 1) || !info[0]->IsArray()) {
45         TAG_LOGW(AceLogTag::ACE_REPEAT, "Invalid arguments for Repeat.FinishRender");
46         return;
47     }
48     RepeatModel::GetInstance()->FinishRender(removedElmtIds);
49 
50     if (!removedElmtIds.size()) {
51         return;
52     }
53 
54     // convert list of removed elmtIds: std::list to JSArray<number>
55     JSRef<JSArray> jsArr = JSRef<JSArray>::Cast(info[0]);
56     size_t index = jsArr->Length();
57     for (const auto& rmElmtId : removedElmtIds) {
58         jsArr->SetValueAt(index++, JSRef<JSVal>::Make(ToJSValue(rmElmtId)));
59     }
60 }
61 
62 // signature is
63 // fromIndex: number
MoveChild(const JSCallbackInfo & info)64 void JSRepeat::MoveChild(const JSCallbackInfo& info)
65 {
66     if ((info.Length() != 1) || !info[0]->IsNumber()) {
67         TAG_LOGW(AceLogTag::ACE_REPEAT, "Invalid arguments for Repeat.MoveChild");
68         return;
69     }
70 
71     const auto fromIndex = info[0]->ToNumber<uint32_t>();
72     RepeatModel::GetInstance()->MoveChild(fromIndex);
73 }
74 
75 // signature is
76 // id: string
77 // parentView? : JSView
CreateNewChildStart(const JSCallbackInfo & info)78 void JSRepeat::CreateNewChildStart(const JSCallbackInfo& info)
79 {
80     if ((info.Length() < 1) || !info[0]->IsString()) {
81         TAG_LOGW(AceLogTag::ACE_REPEAT, "Invalid arguments for Repeat.CreateNewChildStart");
82         return;
83     }
84 
85     const auto key = info[0]->ToString();
86     RepeatModel::GetInstance()->CreateNewChildStart(key);
87 }
88 
89 // signature is
90 // id: string
91 // parentView? : JSView
CreateNewChildFinish(const JSCallbackInfo & info)92 void JSRepeat::CreateNewChildFinish(const JSCallbackInfo& info)
93 {
94     if ((info.Length() < 1) || !info[0]->IsString()) {
95         TAG_LOGW(AceLogTag::ACE_REPEAT, "Invalid arguments for Repeat.CreateNewChildFinish");
96         return;
97     }
98 
99     const auto key = info[0]->ToString();
100     RepeatModel::GetInstance()->CreateNewChildFinish(key);
101 }
102 
OnMove(const JSCallbackInfo & info)103 void JSRepeat::OnMove(const JSCallbackInfo& info)
104 {
105     if (info[0]->IsFunction()) {
106         auto onMove = [execCtx = info.GetExecutionContext(), func = JSRef<JSFunc>::Cast(info[0])]
107             (int32_t from, int32_t to) {
108                 auto params = ConvertToJSValues(from, to);
109                 func->Call(JSRef<JSObject>(), params.size(), params.data());
110             };
111         RepeatModel::GetInstance()->OnMove(std::move(onMove));
112     } else {
113         RepeatModel::GetInstance()->OnMove(nullptr);
114     }
115 }
116 
JSBind(BindingTarget globalObj)117 void JSRepeat::JSBind(BindingTarget globalObj)
118 {
119     JSClass<JSRepeat>::Declare("RepeatNative");
120     JSClass<JSRepeat>::StaticMethod("startRender", &JSRepeat::StartRender);
121     JSClass<JSRepeat>::StaticMethod("finishRender", &JSRepeat::FinishRender);
122     JSClass<JSRepeat>::StaticMethod("moveChild", &JSRepeat::MoveChild);
123     JSClass<JSRepeat>::StaticMethod("createNewChildStart", &JSRepeat::CreateNewChildStart);
124     JSClass<JSRepeat>::StaticMethod("createNewChildFinish", &JSRepeat::CreateNewChildFinish);
125     JSClass<JSRepeat>::StaticMethod("onMove", &JSRepeat::OnMove);
126     JSClass<JSRepeat>::Bind<>(globalObj);
127 }
128 
129 } // namespace OHOS::Ace::Framework
130