Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
mhoran committed Apr 17, 2024
1 parent 5f320f0 commit 2353889
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 82 deletions.
45 changes: 27 additions & 18 deletions __tests__/usecase/buffers/ui/Buffer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import {
fireEvent,
render,
screen,
waitFor
waitFor,
within
} from '@testing-library/react-native';
import React from 'react';
import { ScrollView } from 'react-native';
import Buffer from '../../../../src/usecase/buffers/ui/Buffer';
import { CellContainer } from '@shopify/flash-list';

jest.useFakeTimers();

Expand Down Expand Up @@ -60,53 +62,60 @@ describe(Buffer, () => {

measureNickWidth();

// Simulate layout event for the FlatList
const listElement = screen.getByLabelText('Message list');
fireEvent(listElement, 'layout', {
// Simulate layout event for the ScrollView
const scrollView = screen.UNSAFE_getByType(ScrollView);
fireEvent(scrollView, 'layout', {
nativeEvent: {
layout: { height: 26.5, width: 1024, x: 0, y: 0 }
}
});

// Simulate layout event for first line
let message = screen.getByTestId('renderCell(0)');
fireEvent(message, 'layout', {
let messageCell = screen
.UNSAFE_getAllByType(CellContainer)
.find((container) => within(container).queryByText('Second message'));
expect(messageCell).toBeDefined();
fireEvent(messageCell, 'layout', {
nativeEvent: {
layout: { height: 26.5, width: 1024, x: 0, y: 0 }
layout: { height: 50, width: 1024, x: 0, y: 0 }
}
});

jest.advanceTimersToNextTimer();

bufferRef.current?.scrollToLine('86c2fefd0');

expect(ScrollView.prototype.scrollTo).toHaveBeenNthCalledWith(1, {
animated: false,
y: 0
x: 0,
y: 50
});

// This is effectively a no-op, we are already at 0, 0. However, scrollTo
// triggers this and the VirtualizedList will update internal state based
// on the layout properties, so fire it here as well.
fireEvent.scroll(listElement, {
fireEvent.scroll(scrollView, {
nativeEvent: {
contentInset: { bottom: 0, left: 0, right: 0, top: 0 },
contentOffset: { x: 0, y: 0 },
contentSize: { height: 26.5, width: 1024 },
contentOffset: { x: 0, y: 50 },
contentSize: { height: 50, width: 1024 },
layoutMeasurement: { height: 26.5, width: 1024 }
}
});

// Simulate layout event for second line
message = screen.getByTestId('renderCell(1)');
fireEvent(message, 'layout', {
messageCell = screen
.UNSAFE_getAllByType(CellContainer)
.find((container) => within(container).queryByText('First message'));
expect(messageCell).toBeDefined();
fireEvent(messageCell, 'layout', {
nativeEvent: {
layout: { height: 26.5, width: 1024, x: 0, y: 26.5 }
layout: { height: 26.5, width: 1024, x: 0, y: 50 }
}
});

await waitFor(() => {
expect(ScrollView.prototype.scrollTo).toHaveBeenNthCalledWith(2, {
animated: false,
y: 26.5
x: 0,
y: 50
});
});
});
Expand Down
39 changes: 39 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
"react-redux": "^8.0.2",
"redux": "^4.0.5",
"redux-persist": "^6.0.0",
"redux-thunk": "^2.4.2"
"redux-thunk": "^2.4.2",
"@shopify/flash-list": "1.6.3"
},
"devDependencies": {
"@babel/core": "^7.19.3",
Expand Down
87 changes: 26 additions & 61 deletions src/usecase/buffers/ui/Buffer.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
import * as React from 'react';
import {
Button,
CellRendererProps,
FlatList,
ListRenderItem,
Text,
View
} from 'react-native';
import { Button, Text, View } from 'react-native';

import { FlashList, ListRenderItem } from '@shopify/flash-list';
import { useEffect, useState } from 'react';
import { ParseShape } from 'react-native-parsed-text';
import BufferLine from './BufferLine';
Expand Down Expand Up @@ -63,7 +57,7 @@ interface State {
export default class Buffer extends React.PureComponent<Props, State> {
static readonly DEFAULT_LINE_INCREMENT = 300;

linesList = React.createRef<FlatList<WeechatLine>>();
linesList = React.createRef<FlashList<WeechatLine>>();

state: State = {
nickWidth: 0,
Expand All @@ -90,38 +84,31 @@ export default class Buffer extends React.PureComponent<Props, State> {
}
}

onCellLayout?: (index: number) => void;

onScrollToIndexFailed = async (info: {
index: number;
highestMeasuredFrameIndex: number;
averageItemLength: number;
}) => {
this.linesList.current?.scrollToIndex({
index: info.highestMeasuredFrameIndex,
animated: false
});

await new Promise<void>((resolve) => {
this.onCellLayout = (index: number) => {
if (index > info.highestMeasuredFrameIndex) resolve();
};
});
this.onCellLayout = undefined;

this.linesList.current?.scrollToIndex({
index: info.index,
animated: false,
viewPosition: 0.5
});
};
resolveViewableItems?: () => void;

scrollToLine = async (lineId: string) => {
const index = this.props.lines.findIndex(
(line) => line.pointers[line.pointers.length - 1] === lineId
);
if (index < 0) return;

const listView = this.linesList.current?.recyclerlistview_unsafe;
if (!listView) return;

while (!listView.getLayout(index)?.isOverridden) {
this.linesList.current?.scrollToIndex({
index: index,
animated: false
});

console.log('waiting')
await new Promise<void>((resolve) => {
this.resolveViewableItems = resolve;
});
this.resolveViewableItems = undefined;
console.log('done')
}

this.linesList.current?.scrollToIndex({
index: index,
animated: false,
Expand Down Expand Up @@ -151,26 +138,6 @@ export default class Buffer extends React.PureComponent<Props, State> {
);
};

renderCell: React.FC<CellRendererProps<WeechatLine>> = ({
index,
children,
onLayout,
style
}) => {
return (
<View
testID={`renderCell(${index})`}
style={style}
onLayout={(event) => {
onLayout?.(event);
this.onCellLayout?.(index);
}}
>
{children}
</View>
);
};

render() {
const { bufferId, lines, fetchMoreLines, notificationLineId } = this.props;
const resetList = notificationLineId && !this.state.listReset;
Expand All @@ -191,7 +158,7 @@ export default class Buffer extends React.PureComponent<Props, State> {
}

return (
<FlatList
<FlashList
ref={this.linesList}
accessibilityLabel="Message list"
data={resetList ? [] : lines}
Expand All @@ -200,19 +167,17 @@ export default class Buffer extends React.PureComponent<Props, State> {
keyboardDismissMode="interactive"
keyExtractor={keyExtractor}
renderItem={this.renderBuffer}
initialNumToRender={35}
maxToRenderPerBatch={35}
removeClippedSubviews={true}
windowSize={15}
CellRendererComponent={this.renderCell}
ListFooterComponent={
<Header
bufferId={bufferId}
lines={lines.length}
fetchMoreLines={fetchMoreLines}
/>
}
onScrollToIndexFailed={this.onScrollToIndexFailed}
onViewableItemsChanged={() => {
this.resolveViewableItems?.();
}}
estimatedItemSize={26.5}
/>
);
}
Expand Down
3 changes: 1 addition & 2 deletions src/usecase/buffers/ui/BufferLine.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { formatDateDayChange } from '../../../lib/helpers/date-formatter';
import { cof } from '../../../lib/weechat/colors';
import Default, { styles } from './themes/Default';
import { isSameDay } from 'date-fns';
import { memo } from 'react';

interface Props {
line: WeechatLine;
Expand Down Expand Up @@ -56,4 +55,4 @@ const BufferLine: React.FC<Props> = ({
);
};

export default memo(BufferLine);
export default BufferLine;

0 comments on commit 2353889

Please sign in to comment.