• 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_COMPONENT_H
17 #define FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_JS_VIEW_JS_LAZY_FOREACH_COMPONENT_H
18 
19 #include <functional>
20 #include <set>
21 #include <string>
22 
23 #include "base/memory/ace_type.h"
24 #include "bridge/declarative_frontend/jsview/js_lazy_foreach_actuator.h"
25 #include "bridge/declarative_frontend/jsview/js_view.h"
26 #include "core/components_v2/foreach/lazy_foreach_component.h"
27 #include "uicast_interface/uicast_impl.h"
28 
29 namespace OHOS::Ace::Framework {
30 
31 class DefaultDataChangeListener : public V2::DataChangeListener {
32 public:
DefaultDataChangeListener(JSView * parentView)33     explicit DefaultDataChangeListener(JSView* parentView) : parentView_(parentView) {}
34     ~DefaultDataChangeListener() override = default;
35 
OnDataReloaded()36     void OnDataReloaded() override
37     {
38         if (parentView_ != nullptr) {
39             parentView_->MarkNeedUpdate();
40         }
41     }
OnDataAdded(size_t index)42     void OnDataAdded(size_t index) override
43     {
44         if (parentView_ != nullptr) {
45             parentView_->MarkNeedUpdate();
46         }
47     }
OnDataDeleted(size_t index)48     void OnDataDeleted(size_t index) override
49     {
50         if (parentView_ != nullptr) {
51             parentView_->MarkNeedUpdate();
52         }
53     }
OnDataChanged(size_t index)54     void OnDataChanged(size_t index) override
55     {
56         if (parentView_ != nullptr) {
57             parentView_->MarkNeedUpdate();
58         }
59     }
OnDataMoved(size_t from,size_t to)60     void OnDataMoved(size_t from, size_t to) override
61     {
62         if (parentView_ != nullptr) {
63             parentView_->MarkNeedUpdate();
64         }
65     }
66 
67 private:
68     JSView* parentView_ = nullptr;
69 
70     ACE_DISALLOW_COPY_AND_MOVE(DefaultDataChangeListener);
71 };
72 
73 class JSLazyForEachComponent : public V2::LazyForEachComponent, public JSLazyForEachActuator {
74     DECLARE_ACE_TYPE(JSLazyForEachComponent, V2::LazyForEachComponent, JSLazyForEachActuator);
75 
76 public:
JSLazyForEachComponent(const std::string & id)77     explicit JSLazyForEachComponent(const std::string& id) : V2::LazyForEachComponent(id) {}
78     ~JSLazyForEachComponent() override = default;
79 
OnGetTotalCount()80     size_t OnGetTotalCount() override
81     {
82         return static_cast<size_t>(GetTotalIndexCount());
83     }
84 
ExpandChildrenOnInitial()85     void ExpandChildrenOnInitial()
86     {
87         auto totalIndex = GetTotalIndexCount();
88         auto* stack = ViewStackProcessor::GetInstance();
89         JSRef<JSVal> params[2];
90         for (auto index = 0; index < totalIndex; index++) {
91             params[0] = CallJSFunction(getDataFunc_, dataSourceObj_, index);
92             params[1] = JSRef<JSVal>::Make(ToJSValue(index));
93             std::string key = keyGenFunc_(params[0], index);
94             auto multiComposed = AceType::MakeRefPtr<MultiComposedComponent>(key, "LazyForEach");
95             stack->Push(multiComposed);
96             stack->PushKey(key);
97             itemGenFunc_->Call(JSRef<JSObject>(), 2, params);
98             stack->PopContainer();
99             stack->PopKey();
100         }
101     }
102 
OnGetChildByIndex(size_t index)103     RefPtr<Component> OnGetChildByIndex(size_t index) override
104     {
105         JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(executionContext_, nullptr);
106         if (getDataFunc_.IsEmpty()) {
107             return nullptr;
108         }
109 
110         JSRef<JSVal> params[2];
111         params[0] = CallJSFunction(getDataFunc_, dataSourceObj_, index);
112         params[1] = JSRef<JSVal>::Make(ToJSValue(index));
113         std::string key = keyGenFunc_(params[0], index);
114 
115         ScopedViewStackProcessor scopedViewStackProcessor;
116         auto* viewStack = ViewStackProcessor::GetInstance();
117         auto multiComposed = AceType::MakeRefPtr<MultiComposedComponent>(key, "LazyForEach");
118         viewStack->Push(multiComposed);
119         if (parentView_) {
120             parentView_->MarkLazyForEachProcess(key);
121         }
122         viewStack->PushKey(key);
123 
124         {
125             std::string pviewID = parentView_ ? std::to_string(parentView_->UICastGetUniqueId()) : "-1";
126             std::string para = R"({"viewId":")" + GetId() + R"(","parentViewId":")" +
127                 pviewID + R"(","index":)" + std::to_string(index) + R"(})";
128             UICastImpl::CacheCmd("UICAST::LazyForEach::ItemCreate", para);
129         }
130 
131         itemGenFunc_->Call(JSRef<JSObject>(), 2, params);
132 
133         {
134             UICastImpl::SendCmd();
135         }
136 
137         viewStack->PopContainer();
138         viewStack->PopKey();
139         if (parentView_) {
140             parentView_->ResetLazyForEachProcess();
141         }
142         auto component = viewStack->Finish();
143         ACE_DCHECK(multiComposed == component);
144 
145         while (multiComposed) {
146             const auto& children = multiComposed->GetChildren();
147             if (children.empty()) {
148                 return AceType::MakeRefPtr<ComposedComponent>(key, "LazyForEachItem");
149             }
150 
151             component = children.front();
152             multiComposed = AceType::DynamicCast<MultiComposedComponent>(component);
153         }
154 
155         return AceType::MakeRefPtr<ComposedComponent>(key, "LazyForEachItem", component);
156     }
157 
ReleaseChildGroupByComposedId(const std::string & composedId)158     void ReleaseChildGroupByComposedId(const std::string& composedId) override
159     {
160         JSLazyForEachActuator::ReleaseChildGroupByComposedId(composedId);
161     }
162 
RegisterDataChangeListener(const RefPtr<V2::DataChangeListener> & listener)163     void RegisterDataChangeListener(const RefPtr<V2::DataChangeListener>& listener) override
164     {
165         JSLazyForEachActuator::RegisterListener(listener);
166     }
167 
UnregisterDataChangeListener(const RefPtr<V2::DataChangeListener> & listener)168     void UnregisterDataChangeListener(const RefPtr<V2::DataChangeListener>& listener) override
169     {
170         JSLazyForEachActuator::UnregisterListener(listener);
171     }
172 
173 private:
ExpandChildren()174     std::list<RefPtr<Component>>& ExpandChildren() override
175     {
176         // Register data change listener while expanding the lazy foreach component
177         if (!Expanded()) {
178             defaultListener_ = Referenced::MakeRefPtr<DefaultDataChangeListener>(parentView_);
179             RegisterDataChangeListener(defaultListener_);
180         }
181         return LazyForEachComponent::ExpandChildren();
182     }
183 
184     ACE_DISALLOW_COPY_AND_MOVE(JSLazyForEachComponent);
185 };
186 
187 } // namespace OHOS::Ace::Framework
188 
189 #endif // FRAMEWORKS_BRIDGE_DECLARATIVE_FRONTEND_JS_VIEW_JS_LAZY_FOREACH_COMPONENT_H
190