Skip to content

Commit

Permalink
Merge branch 'main' into fix/checkSendReachEndEvent
Browse files Browse the repository at this point in the history
  • Loading branch information
siguangli authored Oct 30, 2024
2 parents 2b4c2a4 + 2125b52 commit ec93e3b
Show file tree
Hide file tree
Showing 30 changed files with 358 additions and 184 deletions.
3 changes: 2 additions & 1 deletion docs/api/hippy-react/components.md
Original file line number Diff line number Diff line change
Expand Up @@ -550,7 +550,8 @@ import icon from './qb_icon_new.png';
| interItemSpacing | item 间的垂直间距 | `number` | `Android、iOS、Voltron` |
| contentInset | 内容缩进 ,默认值 `{ top:0, left:0, bottom:0, right:0 }` | `Object` | `Android、iOS、Voltron` |
| renderItem | 这里的入参是当前 item 的 index,在这里可以凭借 index 获取到瀑布流一个具体单元格的数据,从而决定如何渲染这个单元格。 | `(index: number) => React.ReactElement` | `Android、iOS、Voltron` |
| renderBanner | 如何渲染 Banner。 | `() => React.ReactElement` | `Android、iOS、Voltron`
| renderBanner | 如何渲染 Banner (即Header,显示在内容顶部) | `() => React.ReactElement` | `Android、iOS、Voltron` |
| renderFooter | 如何渲染 Footer(与renderBanner对应,Footer显示在内容底部) | `() => React.ReactElement` | `iOS`(3.3.2版本起支持) |
| getItemStyle | 设置`WaterfallItem`容器的样式。 | `(index: number) => styleObject` | `Android、iOS、Voltron` |
| getItemType | 指定一个函数,在其中返回对应条目的类型(返回Number类型的自然数,默认是0),List 将对同类型条目进行复用,所以合理的类型拆分,可以很好地提升list 性能。 | `(index: number) => number` | `Android、iOS、Voltron` |
| getItemKey | 指定一个函数,在其中返回对应条目的 Key 值,详见 [React 官文](//reactjs.org/docs/lists-and-keys.html) | `(index: number) => any` | `Android、iOS、Voltron` |
Expand Down
4 changes: 3 additions & 1 deletion docs/api/hippy-vue/external-components.md
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ export default {
| columnSpacing | 瀑布流每列之前的水平间距 | `number` | `Android、iOS、Voltron` |
| interItemSpacing | item 间的垂直间距 | `number` | `Android、iOS、Voltron` |
| contentInset | 内容缩进 ,默认值 `{ top:0, left:0, bottom:0, right:0 }` | `Object` | `Android、iOS、Voltron` |
| containBannerView | 是否包含`bannerView`,只能有一个bannerView,`Android` 暂不支持 | `boolean` | `iOS、Voltron` |
| containBannerView | 是否包含`bannerView`,只能有一个bannerView, (`Android` 暂不支持`iOS` 3.3.2版本起已废弃该属性,请使用`waterfall-item`组件`isHeader/isFooter`属性代替) | `boolean` | `iOS、Voltron` |
| containPullHeader | 是否包含`pull-header``Android` 暂不支持,可以用 `ul-refresh` 组件替代 | `boolean` | `iOS、Voltron` |
| containPullFooter | 是否包含 `pull-footer` | `boolean` | `Android、iOS、Voltron` |
| numberOfColumns | 瀑布流列数量,Default: 2 | `number` | `Android、iOS、Voltron` |
Expand Down Expand Up @@ -323,3 +323,5 @@ export default {
| --------------------- | ------------------------------------------------------------ | ----------------------------------------------------------- | -------- |
| type | 指定一个函数,在其中返回对应条目的类型(返回Number类型的自然数,默认是0),List 将对同类型条目进行复用,所以合理的类型拆分,可以很好地提升 List 性能。 | `number` | `Android、iOS、Voltron` |
| key | 指定一个函数,在其中返回对应条目的 Key 值,详见 [Vue 官网](//vuejs.org/v2/guide/list.html) | `string` | `Android、iOS、Voltron` |
| isHeader | 指定该Item是否为Header(即bannerView,显示在内容区顶部) | `boolean` | `iOS`(3.3.2版本起支持) |
| isFooter | 指定该Item是否为Footer(显示在内容区底部) | `boolean` | `iOS`(3.3.2版本起支持) |
12 changes: 6 additions & 6 deletions dom/include/dom/dom_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,10 @@ class DomManager : public std::enable_shared_from_this<DomManager> {
static byte_string GetSnapShot(const std::shared_ptr<RootNode>& root_node);
bool SetSnapShot(const std::shared_ptr<RootNode>& root_node, const byte_string& buffer);

void RecordDomStartTimePoint();
void RecordDomEndTimePoint();
inline auto GetDomStartTimePoint() { return dom_start_time_point_; }
inline auto GetDomEndTimePoint() { return dom_end_time_point_; }
void RecordDomStartTimePoint(uint32_t root_id);
void RecordDomEndTimePoint(uint32_t root_id);
inline auto GetDomStartTimePoint(uint32_t root_id) { return dom_start_time_point_[root_id]; }
inline auto GetDomEndTimePoint(uint32_t root_id) { return dom_end_time_point_[root_id]; }

private:
friend class DomNode;
Expand All @@ -152,8 +152,8 @@ class DomManager : public std::enable_shared_from_this<DomManager> {
std::shared_ptr<TaskRunner> task_runner_;
std::shared_ptr<Worker> worker_;

footstone::TimePoint dom_start_time_point_;
footstone::TimePoint dom_end_time_point_;
std::unordered_map<uint32_t, footstone::TimePoint> dom_start_time_point_;
std::unordered_map<uint32_t, footstone::TimePoint> dom_end_time_point_;
};

} // namespace dom
Expand Down
14 changes: 7 additions & 7 deletions dom/src/dom/dom_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -272,16 +272,16 @@ bool DomManager::SetSnapShot(const std::shared_ptr<RootNode>& root_node, const b
return true;
}

void DomManager::RecordDomStartTimePoint() {
if (dom_start_time_point_.ToEpochDelta() == TimeDelta::Zero()) {
dom_start_time_point_ = footstone::TimePoint::SystemNow();
void DomManager::RecordDomStartTimePoint(uint32_t root_id) {
if (dom_start_time_point_[root_id].ToEpochDelta() == TimeDelta::Zero()) {
dom_start_time_point_[root_id] = footstone::TimePoint::SystemNow();
}
}

void DomManager::RecordDomEndTimePoint() {
if (dom_end_time_point_.ToEpochDelta() == TimeDelta::Zero()
&& dom_start_time_point_.ToEpochDelta() != TimeDelta::Zero()) {
dom_end_time_point_ = footstone::TimePoint::SystemNow();
void DomManager::RecordDomEndTimePoint(uint32_t root_id) {
if (dom_end_time_point_[root_id].ToEpochDelta() == TimeDelta::Zero()
&& dom_start_time_point_[root_id].ToEpochDelta() != TimeDelta::Zero()) {
dom_end_time_point_[root_id] = footstone::TimePoint::SystemNow();
}
}

Expand Down
2 changes: 1 addition & 1 deletion dom/src/dom/root_node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ void RootNode::SyncWithRenderManager(const std::shared_ptr<RenderManager>& rende
TDF_PERF_LOG("RootNode::DoAndFlushLayout Done");
auto dom_manager = dom_manager_.lock();
if (dom_manager) {
dom_manager->RecordDomEndTimePoint();
dom_manager->RecordDomEndTimePoint(this->GetId());
}
render_manager->EndBatch(GetWeakSelf());
TDF_PERF_LOG("RootNode::SyncWithRenderManager End");
Expand Down
8 changes: 4 additions & 4 deletions dom/src/dom/scene_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@
*/

#include "dom/scene_builder.h"

#include "dom/dom_listener.h"

#include "dom/root_node.h"
#include "footstone/logging.h"
#include "footstone/string_view_utils.h"

Expand All @@ -33,8 +32,9 @@ void SceneBuilder::Create(const std::weak_ptr<DomManager>& weak_dom_manager,
std::vector<std::shared_ptr<DomInfo>>&& nodes,
bool needSortByIndex) {
auto dom_manager = weak_dom_manager.lock();
if (dom_manager) {
dom_manager->RecordDomStartTimePoint();
auto rootNode = root_node.lock();
if (dom_manager && rootNode) {
dom_manager->RecordDomStartTimePoint(rootNode->GetId());
dom_manager->CreateDomNodes(root_node, std::move(nodes), needSortByIndex);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export default class ListExample extends React.Component {
this.onHeaderPulling = this.onHeaderPulling.bind(this);
this.onFooterPulling = this.onFooterPulling.bind(this);
this.renderBanner = this.renderBanner.bind(this);
this.renderFooter = this.renderFooter.bind(this);
this.getItemStyle = this.getItemStyle.bind(this);
this.getHeaderStyle = this.getHeaderStyle.bind(this);
this.onScroll = this.onScroll.bind(this);
Expand Down Expand Up @@ -236,10 +237,10 @@ export default class ListExample extends React.Component {
}

onScroll(obj) {

console.log('onScroll', obj);
}

// render banner(it is not supported on Android yet)
// render banner
renderBanner() {
if (this.state.dataSource.length === 0) return null;
return (<View style={{
Expand All @@ -257,6 +258,24 @@ export default class ListExample extends React.Component {
</View>);
}

// render footer (currently only iOS support)
renderFooter() {
if (this.state.dataSource.length === 0) return null;
return (<View style={{
backgroundColor: 'grey',
height: 100,
justifyContent: 'center',
alignItems: 'center',
}}>
<Text style={{
fontSize: 20,
color: 'white',
lineHeight: 100,
height: 100,
}}>Footer View</Text>
</View>);
}

renderItem(index) {
const { dataSource } = this.state;
let styleUI = null;
Expand Down Expand Up @@ -362,7 +381,9 @@ export default class ListExample extends React.Component {
style={{ flex: 1 }}
onScroll={this.onScroll}
renderBanner={this.renderBanner}
renderFooter={this.renderFooter}
renderPullHeader={this.renderPullHeader}
renderPullFooter={this.renderPullFooter}
onEndReached={this.onEndReached}
onFooterReleased={this.onEndReached}
onHeaderReleased={this.onHeaderReleased}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,18 @@
</p>
</pull-header>
<div
v-if="!isAndroid"
v-if="!isAndroid && !isiOS"
class="banner-view"
>
<span>BannerView</span>
</div>
</div>
<waterfall-item
v-else
v-else
:fullSpan="true",
:isHeader="true",
class="banner-view"
>

Check failure on line 38 in driver/js/examples/hippy-vue-demo/src/components/native-demos/demo-waterfall.vue

View workflow job for this annotation

GitHub Actions / frontend_build_tests (16.x)

Parsing error: duplicate-attribute

Check failure on line 38 in driver/js/examples/hippy-vue-demo/src/components/native-demos/demo-waterfall.vue

View workflow job for this annotation

GitHub Actions / frontend_build_tests (16.x)

Duplicate attribute ','

Check failure on line 38 in driver/js/examples/hippy-vue-demo/src/components/native-demos/demo-waterfall.vue

View workflow job for this annotation

GitHub Actions / frontend_build_tests (17.x)

Parsing error: duplicate-attribute

Check failure on line 38 in driver/js/examples/hippy-vue-demo/src/components/native-demos/demo-waterfall.vue

View workflow job for this annotation

GitHub Actions / frontend_build_tests (17.x)

Duplicate attribute ','
<span>BannerView</span>
<span>Banner View</span>
</waterfall-item>
<waterfall-item
v-for="(ui, index) in dataSource"
Expand All @@ -57,6 +58,13 @@
:item-bean="ui.itemBean"
/>
</waterfall-item>
<waterfall-item
:fullSpan="true",
:isFooter="true",
class="banner-view"
>
<span>Footer View</span>
</waterfall-item>

Check failure on line 67 in driver/js/examples/hippy-vue-demo/src/components/native-demos/demo-waterfall.vue

View workflow job for this annotation

GitHub Actions / frontend_build_tests (16.x)

Parsing error: duplicate-attribute

Check failure on line 67 in driver/js/examples/hippy-vue-demo/src/components/native-demos/demo-waterfall.vue

View workflow job for this annotation

GitHub Actions / frontend_build_tests (16.x)

Duplicate attribute ','

Check failure on line 67 in driver/js/examples/hippy-vue-demo/src/components/native-demos/demo-waterfall.vue

View workflow job for this annotation

GitHub Actions / frontend_build_tests (17.x)

Parsing error: duplicate-attribute

Check failure on line 67 in driver/js/examples/hippy-vue-demo/src/components/native-demos/demo-waterfall.vue

View workflow job for this annotation

GitHub Actions / frontend_build_tests (17.x)

Duplicate attribute ','
<pull-footer
ref="pullFooter"
class="pull-footer"
Expand Down Expand Up @@ -91,6 +99,7 @@ export default {
footerRefreshText: '正在加载...',
isLoading: false,
isAndroid: Vue.Native.Platform === 'android',
isiOS: Vue.Native.Platform === 'android',
};
},
mounted() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
ref="gridView"
:content-inset="contentInset"
:column-spacing="columnSpacing"
:contain-banner-view="!isAndroid"
:contain-pull-footer="true"
:inter-item-spacing="interItemSpacing"
:number-of-columns="numberOfColumns"
Expand All @@ -25,17 +24,18 @@
</p>
</pull-header>
<div
v-if="!isAndroid"
v-if="!isAndroid && !isiOS"
class="banner-view"
>
<span>BannerView</span>
</div>
<waterfall-item
v-else
:full-span="true"
:isHeader="true"
class="banner-view"
>
<span>BannerView</span>
<span>Banner View</span>
</waterfall-item>
<waterfall-item
v-for="(ui, index) in dataSource"
Expand All @@ -57,6 +57,12 @@
:item-bean="ui.itemBean"
/>
</waterfall-item>
<waterfall-item
:isFooter="true"
class="banner-view"
>
<span>Footer View</span>
</waterfall-item>
<pull-footer
ref="pullFooter"
class="pull-footer"
Expand Down Expand Up @@ -95,6 +101,7 @@ const numberOfColumns = 2;
// inner content padding
const contentInset = { top: 0, left: 5, bottom: 0, right: 5 };
const isAndroid = Native.Platform === 'android';
const isiOS = Native.Platform === 'ios';
const mockFetchData = async (): Promise<any> => new Promise((resolve) => {
setTimeout(() => {
Expand Down Expand Up @@ -249,6 +256,7 @@ export default defineComponent({
onEndReached,
onClickItem,
isAndroid,
isiOS,
onHeaderPulling,
onFooterPulling,
onHeaderIdle,
Expand Down
30 changes: 26 additions & 4 deletions driver/js/packages/hippy-react/src/components/waterfall-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,12 @@ interface WaterfallViewProps {
// Declare whether banner view exists
containBannerView?: boolean

// Return banner view element
// Return banner view element (header)
renderBanner?: () => React.ReactElement;

// Return footer banner view element
renderFooter?: () => React.ReactElement;

/**
* Passing the data and returns the row component.
*
Expand Down Expand Up @@ -253,6 +256,7 @@ class WaterfallView extends React.Component<WaterfallViewProps> {
const {
style = {},
renderBanner,
renderFooter,
numberOfColumns = 2,
columnSpacing = 0,
interItemSpacing = 0,
Expand Down Expand Up @@ -293,17 +297,18 @@ class WaterfallView extends React.Component<WaterfallViewProps> {
if (typeof renderBanner === 'function') {
const banner = renderBanner();
if (banner) {
if (Device.platform.OS === 'ios' || Device.platform.OS === 'ohos') {
if (Device.platform.OS === 'ohos') {
itemList.push((
<View key="bannerView">
{React.cloneElement(banner)}
</View>
));
nativeProps.containBannerView = true;
} else if (Device.platform.OS === 'android') {
} else {
const itemProps = {
key: 'bannerView',
fullSpan: true,
isHeader: true,
fullSpan: true, // only for android
style: {},
};
itemList.push((
Expand Down Expand Up @@ -357,6 +362,23 @@ class WaterfallView extends React.Component<WaterfallViewProps> {
warn('Waterfall attribute [renderItem] is not Function');
}

// only ios support currently
if (typeof renderFooter === 'function') {
const footer = renderFooter();
if (footer) {
const itemProps = {
key: 'WaterfallFooterView',
isFooter: true,
style: {},
};
itemList.push((
<WaterfallViewItem{...itemProps}>
{React.cloneElement(footer)}
</WaterfallViewItem>
));
}
}

return (
// @ts-ignore
<ul
Expand Down
3 changes: 2 additions & 1 deletion driver/js/src/modules/ui_layout_module.cc
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ inline namespace module {
GEN_INVOKE_CB(LayoutModule, ResetLayoutCache)

void LayoutModule::ResetLayoutCache(CallbackInfo& info, void* data) {
auto scope_wrapper = reinterpret_cast<ScopeWrapper*>(std::any_cast<void*>(info.GetSlot()));
std::any slot_any = info.GetSlot();
auto scope_wrapper = reinterpret_cast<ScopeWrapper*>(std::any_cast<void*>(&slot_any));
auto scope = scope_wrapper->scope.lock();
FOOTSTONE_CHECK(scope);
if (!scope) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ void SetDomManager(JNIEnv* j_env,

void OnNativeInitEnd(JNIEnv* j_env, jobject j_object, jint j_scope_id, jlong startTime, jlong endTime);

void OnFirstPaintEnd(JNIEnv* j_env, jobject j_object, jint j_scope_id, jlong time);
void OnFirstPaintEnd(JNIEnv* j_env, jobject j_object, jint j_scope_id, jlong time, jint j_root_id);

void OnFirstContentfulPaintEnd(JNIEnv* j_env, jobject j_object, jint j_scope_id, jlong time);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ REGISTER_JNI("com/openhippy/connector/JsDriver", // NOLINT(cert-err58-cpp)

REGISTER_JNI("com/openhippy/connector/JsDriver", // NOLINT(cert-err58-cpp)
"onFirstPaintEnd",
"(IJ)V",
"(IJI)V",
OnFirstPaintEnd)

REGISTER_JNI("com/openhippy/connector/JsDriver", // NOLINT(cert-err58-cpp)
Expand Down Expand Up @@ -192,7 +192,7 @@ void OnNativeInitEnd(JNIEnv* j_env, jobject j_object, jint j_scope_id, jlong sta
}
}

void OnFirstPaintEnd(JNIEnv* j_env, jobject j_object, jint j_scope_id, jlong time) {
void OnFirstPaintEnd(JNIEnv* j_env, jobject j_object, jint j_scope_id, jlong time, jint j_root_id) {
auto scope = GetScope(j_scope_id);
if (!scope) {
return;
Expand All @@ -204,7 +204,7 @@ void OnFirstPaintEnd(JNIEnv* j_env, jobject j_object, jint j_scope_id, jlong tim
auto runner = engine->GetJsTaskRunner();
if (runner) {
std::weak_ptr<Scope> weak_scope = scope;
auto task = [weak_scope, time]() {
auto task = [weak_scope, time, j_root_id]() {
auto scope = weak_scope.lock();
if (!scope) {
return;
Expand All @@ -214,10 +214,11 @@ void OnFirstPaintEnd(JNIEnv* j_env, jobject j_object, jint j_scope_id, jlong tim
return;
}
auto entry = scope->GetPerformance()->PerformanceNavigation("hippyInit");
entry->SetHippyRunApplicationEnd(dom_manager->GetDomStartTimePoint());
entry->SetHippyDomStart(dom_manager->GetDomStartTimePoint());
entry->SetHippyDomEnd(dom_manager->GetDomEndTimePoint());
entry->SetHippyFirstFrameStart(dom_manager->GetDomEndTimePoint());
auto rootId = footstone::checked_numeric_cast<jint, uint32_t>(j_root_id);
entry->SetHippyRunApplicationEnd(dom_manager->GetDomStartTimePoint(rootId));
entry->SetHippyDomStart(dom_manager->GetDomStartTimePoint(rootId));
entry->SetHippyDomEnd(dom_manager->GetDomEndTimePoint(rootId));
entry->SetHippyFirstFrameStart(dom_manager->GetDomEndTimePoint(rootId));
entry->SetHippyFirstFrameEnd(footstone::TimePoint::FromEpochDelta(footstone::TimeDelta::FromMilliseconds(time)));
};
runner->PostTask(std::move(task));
Expand Down
Loading

0 comments on commit ec93e3b

Please sign in to comment.