• 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 #ifndef FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_JS_VIEW_JS_LAZY_FOREACH_ACTUATOR_H
17 #define FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_JS_VIEW_JS_LAZY_FOREACH_ACTUATOR_H
18 
19 #include <functional>
20 #include <set>
21 #include <string>
22 
23 #include "base/memory/ace_type.h"
24 #include "bridge/declarative_frontend/engine/bindings.h"
25 #include "bridge/declarative_frontend/engine/js_ref_ptr.h"
26 #include "bridge/declarative_frontend/jsview/js_data_change_listener.h"
27 #include "bridge/declarative_frontend/jsview/js_view.h"
28 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
29 #include "core/components_ng/syntax/lazy_for_each_model.h"
30 
31 namespace OHOS::Ace::Framework {
32 
33 using ItemKeyGenerator = std::function<std::string(const JSRef<JSVal>&, size_t)>;
34 
35 template<class... T>
CallJSFunction(const JSRef<JSFunc> & func,const JSRef<JSObject> & obj,T &&...args)36 JSRef<JSVal> CallJSFunction(const JSRef<JSFunc>& func, const JSRef<JSObject>& obj, T&&... args)
37 {
38     JSRef<JSVal> params[] = { ConvertToJSValue(std::forward<T>(args))... };
39     return func->Call(obj, ArraySize(params), params);
40 }
41 
42 class JSLazyForEachActuator : public LazyForEachActuator {
43     DECLARE_ACE_TYPE(JSLazyForEachActuator, LazyForEachActuator);
44 
45 public:
46     JSLazyForEachActuator() = default;
~JSLazyForEachActuator()47     ~JSLazyForEachActuator() override
48     {
49         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext_);
50         JSRef<JSObject> listenerObj = listenerProxyObj_.Lock();
51         if (listenerObj.IsEmpty() || unregisterListenerFunc_.IsEmpty()) {
52             return;
53         }
54 
55         JSRef<JSVal> args[] = { listenerObj };
56         unregisterListenerFunc_->Call(dataSourceObj_, ArraySize(args), args);
57     }
58 
GetTotalIndexCount()59     int32_t GetTotalIndexCount()
60     {
61         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext_, 0);
62         if (totalCountFunc_.IsEmpty()) {
63             return 0;
64         }
65 
66         int32_t value = 0;
67         if (!ConvertFromJSValue(totalCountFunc_->Call(dataSourceObj_), value)) {
68             return 0;
69         }
70         if (value < 0) {
71             return 0;
72         }
73         return value;
74     }
75 
RegisterListener(const RefPtr<V2::DataChangeListener> & listener)76     void RegisterListener(const RefPtr<V2::DataChangeListener>& listener)
77     {
78         if (!listener) {
79             return;
80         }
81 
82         auto listenerProxy = listenerProxy_.Upgrade();
83         if (listenerProxy) {
84             listenerProxy->AddListener(listener);
85             return;
86         }
87 
88         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext_);
89         if (registerListenerFunc_.IsEmpty()) {
90             return;
91         }
92 
93         JSRef<JSObject> listenerObj = JSClass<JSDataChangeListener>::NewInstance();
94         auto* unwrapObj = listenerObj->Unwrap<JSDataChangeListener>();
95         if (unwrapObj == nullptr) {
96             return;
97         }
98         listenerProxy = Referenced::Claim(unwrapObj);
99         listenerProxy->AddListener(listener);
100         listenerProxyObj_ = listenerObj;
101         listenerProxy_ = listenerProxy;
102 
103         JSRef<JSVal> args[] = { listenerObj };
104         registerListenerFunc_->Call(dataSourceObj_, ArraySize(args), args);
105     }
106 
UnregisterListener(V2::DataChangeListener * listener)107     void UnregisterListener(V2::DataChangeListener* listener)
108     {
109         if (!listener) {
110             return;
111         }
112 
113         auto listenerProxy = listenerProxy_.Upgrade();
114         if (listenerProxy) {
115             listenerProxy->RemoveListener(Referenced::WeakClaim(listener));
116         }
117     }
118 
SetJSExecutionContext(const JSExecutionContext & context)119     void SetJSExecutionContext(const JSExecutionContext& context)
120     {
121         executionContext_ = context;
122     }
123 
SetParentViewObj(const JSRef<JSObject> & parentViewObj)124     void SetParentViewObj(const JSRef<JSObject>& parentViewObj)
125     {
126         AceType* aceType = parentViewObj->Unwrap<AceType>();
127         CHECK_NULL_VOID(aceType);
128         std::string typeName = AceType::TypeName(aceType);
129         if (typeName != "JSBaseNode") {
130             parentView_ = JSView::GetNativeView(parentViewObj);
131         }
132     }
133 
SetDataSourceObj(const JSRef<JSObject> & dataSourceObj)134     void SetDataSourceObj(const JSRef<JSObject>& dataSourceObj)
135     {
136         dataSourceObj_ = dataSourceObj;
137         totalCountFunc_ = GetFunctionFromObject(dataSourceObj, "totalCount");
138         getDataFunc_ = GetFunctionFromObject(dataSourceObj, "getData");
139         registerListenerFunc_ = GetFunctionFromObject(dataSourceObj, "registerDataChangeListener");
140         unregisterListenerFunc_ = GetFunctionFromObject(dataSourceObj, "unregisterDataChangeListener");
141     }
142 
SetItemGenerator(const JSRef<JSFunc> & itemGenFunc,ItemKeyGenerator && keyGenFunc)143     void SetItemGenerator(const JSRef<JSFunc>& itemGenFunc, ItemKeyGenerator&& keyGenFunc)
144     {
145         itemGenFunc_ = itemGenFunc;
146         keyGenFunc_ = std::move(keyGenFunc);
147     }
148 
SetUpdateChangedNodeFlag(const bool updateChangedNodeFlag)149     void SetUpdateChangedNodeFlag(const bool updateChangedNodeFlag)
150     {
151         updateChangedNodeFlag_ = updateChangedNodeFlag;
152     }
153 
ReleaseChildGroupByComposedId(const std::string & composedId)154     void ReleaseChildGroupByComposedId(const std::string& composedId)
155     {
156         if (parentView_ != nullptr) {
157             parentView_->RemoveChildGroupById(composedId);
158         }
159     }
160 
161 private:
GetFunctionFromObject(const JSRef<JSObject> & obj,const char * funcName)162     inline JSRef<JSFunc> GetFunctionFromObject(const JSRef<JSObject>& obj, const char* funcName)
163     {
164         JSRef<JSVal> jsVal = obj->GetProperty(funcName);
165         if (jsVal->IsFunction()) {
166             return JSRef<JSFunc>::Cast(jsVal);
167         }
168         return JSRef<JSFunc>();
169     }
170 
171 protected:
172     JSExecutionContext executionContext_;
173     JSView* parentView_ = nullptr;
174     JSRef<JSObject> dataSourceObj_;
175     JSRef<JSFunc> totalCountFunc_;
176     JSRef<JSFunc> getDataFunc_;
177     JSRef<JSFunc> registerListenerFunc_;
178     JSRef<JSFunc> unregisterListenerFunc_;
179     JSRef<JSFunc> itemGenFunc_;
180     ItemKeyGenerator keyGenFunc_;
181     bool updateChangedNodeFlag_ = false;
182 
183     JSWeak<JSObject> listenerProxyObj_;
184     WeakPtr<JSDataChangeListener> listenerProxy_;
185     RefPtr<V2::DataChangeListener> defaultListener_;
186 };
187 
188 } // namespace OHOS::Ace::Framework
189 
190 #endif // FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_JS_VIEW_JS_LAZY_FOREACH_ACTUATOR_H
191