Skip to content

Commit 25e1fa8

Browse files
onrefresh functionality
1 parent 3fd3c39 commit 25e1fa8

File tree

12 files changed

+2968
-294
lines changed

12 files changed

+2968
-294
lines changed

example/app.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
22
"name": "BidirectionalInfiniteScrollExample",
3-
"displayName": "BidirectionalInfiniteScroll Example"
3+
"displayName": "BidirectionalInfiniteScrollExample"
44
}

example/index.tsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
1-
import { AppRegistry } from 'react-native';
1+
import { AppRegistry, Platform } from 'react-native';
22
import App from './src/App';
33
import { name as appName } from './app.json';
4-
4+
console.log('>>>> ', appName)
55
AppRegistry.registerComponent(appName, () => App);
6+
7+
if (Platform.OS === 'web') {
8+
const rootTag = document.getElementById('root');
9+
AppRegistry.runApplication(appName, { rootTag });
10+
}

example/package.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,21 @@
1010
},
1111
"dependencies": {
1212
"@stream-io/flat-list-mvcp": "0.10.0",
13+
"expo": "^40.0.1",
1314
"react": "16.13.1",
15+
"react-dom": "^17.0.2",
1416
"react-native": "0.63.4",
15-
"react-native-bidirectional-infinite-scroll": "link:../"
17+
"react-native-bidirectional-infinite-scroll": "link:../",
18+
"react-native-web": "^0.15.6",
19+
"react-virtuoso": "^1.6.0"
1620
},
1721
"devDependencies": {
1822
"@babel/core": "^7.12.10",
23+
"@babel/preset-typescript": "^7.13.0",
1924
"@babel/runtime": "^7.12.5",
25+
"@types/react": "^17.0.3",
26+
"@types/react-dom": "^17.0.3",
27+
"@types/react-native": "^0.64.2",
2028
"babel-plugin-module-resolver": "^4.0.0",
2129
"metro-react-native-babel-preset": "^0.64.0"
2230
}

example/src/MessageBubble.tsx

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,38 +6,51 @@ type Props = {
66
item: Message;
77
};
88

9-
export const MessageBubble: React.FC<Props> = ({ item }) => {
9+
export const MessageBubble: React.FC<Props> = ({ item, index }) => {
1010
if (item.isMyMessage) {
1111
return (
12-
<View
13-
key={`${item.id}`}
14-
style={[styles.messageBubble, styles.myMessageBubble]}
15-
>
16-
<Text style={styles.myMessageText}>{item.text}</Text>
12+
<View style={styles.container} key={`item-${item.id}`}>
13+
<View
14+
style={[styles.messageBubble, styles.myMessageBubble]}
15+
>
16+
<Text style={styles.myMessageText}>{item.text}</Text>
17+
<Text style={[styles.myMessageText, {
18+
marginTop: 10,
19+
fontWeight: 'bold'
20+
}]}>ID: {item.id} Index: {index}</Text>
21+
</View>
1722
</View>
1823
);
1924
}
2025

2126
return (
22-
<View key={`${item.id}`} style={styles.messageBubble}>
23-
<Text style={styles.messageText}>{item.text}</Text>
27+
<View style={styles.container} key={`item-${item.id}`}>
28+
<View style={styles.messageBubble}>
29+
<Text style={styles.messageText}>{item.text}</Text>
30+
<Text style={[styles.messageText, {
31+
marginTop: 10,
32+
fontWeight: 'bold'
33+
}]}>ID: {item.id} Index: {index}</Text>
34+
</View>
2435
</View>
2536
);
2637
};
2738

2839
const styles = StyleSheet.create({
40+
container: {
41+
width: '100%'
42+
},
2943
messageBubble: {
3044
maxWidth: 300,
3145
padding: 10,
3246
borderRadius: 10,
3347
marginVertical: 5,
3448
marginHorizontal: 5,
3549
backgroundColor: '#F1F0F0',
50+
height: 100
3651
},
3752
myMessageBubble: {
3853
alignSelf: 'flex-end',
39-
// borderColor: '#989898',
40-
// borderWidth: 1,
4154
backgroundColor: '#3784FF',
4255
},
4356
messageText: {

example/src/MessageListExample.tsx

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
1-
import React, { useEffect, useState } from 'react';
1+
import React, { useCallback, useEffect, useRef, useState } from 'react';
22
import { SafeAreaView, StyleSheet, Text, View } from 'react-native';
33

44
import { FlatList } from 'react-native-bidirectional-infinite-scroll';
55
import { MessageBubble } from './MessageBubble';
66
import { Message, queryMoreMessages } from './utils';
77

8+
const ItemSeparatorComponent = () => <View style={{
9+
borderBottomColor: 'black',
10+
height: 0,
11+
borderBottomWidth: 1,
12+
marginVertical: 10
13+
}} />;
14+
815
const App = () => {
916
const [messages, setMessages] = useState<Array<Message>>([]);
17+
const flRef = useRef(null);
1018
useEffect(() => {
1119
const initChat = async () => {
12-
const initialMessages = await queryMoreMessages(50);
20+
const initialMessages = await queryMoreMessages(50, null, null);
1321
if (!initialMessages) return;
1422

1523
setMessages(initialMessages);
@@ -19,18 +27,19 @@ const App = () => {
1927
}, []);
2028

2129
const loadMoreOlderMessages = async () => {
22-
const newMessages = await queryMoreMessages(10);
23-
setMessages((m) => {
24-
return m.concat(newMessages);
25-
});
30+
const newMessages = await queryMoreMessages(10, null, messages[messages.length - 1].id);
31+
setMessages((m) => {
32+
return m.concat(newMessages);
33+
});
2634
};
2735

28-
const loadMoreRecentMessages = async () => {
29-
const newMessages = await queryMoreMessages(10);
36+
const loadMoreRecentMessages = useCallback(async () => {
37+
const newMessages = await queryMoreMessages(10, messages[0].id, null);
38+
console.log('loadMoreRecentMessages before ', messages[0].id)
3039
setMessages((m) => {
3140
return newMessages.concat(m);
3241
});
33-
};
42+
}, [messages]);
3443

3544
if (!messages.length) {
3645
return null;
@@ -43,9 +52,11 @@ const App = () => {
4352
</View>
4453
<FlatList
4554
data={messages}
46-
inverted
55+
ref={flRef}
4756
onEndReached={loadMoreOlderMessages}
4857
onStartReached={loadMoreRecentMessages}
58+
// inverted
59+
// onRefresh={loadMoreRecentMessages}
4960
renderItem={MessageBubble}
5061
/>
5162
</SafeAreaView>

example/src/utils.ts

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,31 +8,52 @@ export const generateUniqueKey = () =>
88
`_${Math.random().toString(36).substr(2, 9)}`;
99

1010
export type Message = {
11-
id: string;
11+
id: number;
1212
text: string;
1313
isMyMessage: boolean;
1414
};
1515

1616
// Mocks the api call to query 'n' number of messages.
17-
export const queryMoreMessages: (n: number) => Promise<Array<Message>> = (
18-
n
17+
export const queryMoreMessages: (n: number, before: number | null, after: number | null) => Promise<Array<Message>> = (
18+
n,
19+
before,
20+
after
1921
) => {
2022
return new Promise((resolve) => {
2123
const newMessages: Array<Message> = [];
2224

23-
for (let i = 0; i < n; i++) {
24-
const messageText = testMessages[getRandomInt(0, testMessages.length)];
25-
newMessages.push({
26-
id: generateUniqueKey(),
27-
text: messageText,
28-
isMyMessage: Boolean(getRandomInt(0, 2)), // Randomly assign true or false.
29-
});
25+
if (before !== null) {
26+
for (let i = before - n; i < before; i++) {
27+
const messageText = testMessages[getRandomInt(0, testMessages.length)];
28+
newMessages.push({
29+
id: i,
30+
text: messageText,
31+
isMyMessage: Boolean(getRandomInt(0, 2)), // Randomly assign true or false.
32+
});
33+
}
34+
} else if (after !== null) {
35+
for (let i = after + 1; i <= n + after; i++) {
36+
const messageText = testMessages[getRandomInt(0, testMessages.length)];
37+
newMessages.push({
38+
id: i,
39+
text: messageText,
40+
isMyMessage: Boolean(getRandomInt(0, 2)), // Randomly assign true or false.
41+
});
42+
}
43+
} else {
44+
for (let i = 0; i < n; i++) {
45+
const messageText = testMessages[getRandomInt(0, testMessages.length)];
46+
newMessages.push({
47+
id: i,
48+
text: messageText,
49+
isMyMessage: Boolean(getRandomInt(0, 2)), // Randomly assign true or false.
50+
});
51+
}
3052
}
31-
32-
// Lets resolve after 500 ms, to simulate network latency.
33-
setTimeout(() => {
34-
resolve(newMessages);
35-
}, 500);
53+
// Lets resolve after 500 ms, to simulate network latency.
54+
setTimeout(() => {
55+
resolve(newMessages);
56+
}, 2000);
3657
});
3758
};
3859

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/* eslint-env browser */
2+
3+
if ('serviceWorker' in navigator) {
4+
window.addEventListener('load', function () {
5+
navigator.serviceWorker
6+
.register('/expo-service-worker.js', { scope: '/' })
7+
.then(function (info) {
8+
// console.info('Registered service-worker', info);
9+
})
10+
.catch(function (error) {
11+
console.info('Failed to register service-worker', error);
12+
});
13+
});
14+
}

example/web/index.html

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
<!DOCTYPE html>
2+
<html lang="%LANG_ISO_CODE%">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
6+
<!--
7+
This viewport works for phones with notches.
8+
It's optimized for gestures by disabling global zoom.
9+
-->
10+
<meta
11+
name="viewport"
12+
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1.00001, viewport-fit=cover"
13+
/>
14+
<title>%WEB_TITLE%</title>
15+
<style>
16+
/**
17+
* Extend the react-native-web reset:
18+
* https://github.com/necolas/react-native-web/blob/master/packages/react-native-web/src/exports/StyleSheet/initialRules.js
19+
*/
20+
html,
21+
body,
22+
#root {
23+
overscroll-behavior-y: none !important; /* disable pull to refresh, keeps glow effects */
24+
overflow: hidden;
25+
width: 100%;
26+
/* To smooth any scrolling behavior */
27+
-webkit-overflow-scrolling: touch;
28+
margin: 0px;
29+
padding: 0px;
30+
/* Allows content to fill the viewport and go beyond the bottom */
31+
min-height: 100%;
32+
}
33+
#root {
34+
flex-shrink: 0;
35+
flex-basis: auto;
36+
flex-grow: 1;
37+
display: flex;
38+
flex: 1;
39+
}
40+
41+
html {
42+
scroll-behavior: smooth;
43+
/* Prevent text size change on orientation change https://gist.github.com/tfausak/2222823#file-ios-8-web-app-html-L138 */
44+
-webkit-text-size-adjust: 100%;
45+
height: calc(100% + env(safe-area-inset-top));
46+
}
47+
48+
body {
49+
display: flex;
50+
/* Allows you to scroll below the viewport; default value is visible */
51+
overflow-y: auto;
52+
overscroll-behavior-y: none;
53+
text-rendering: optimizeLegibility;
54+
-webkit-font-smoothing: antialiased;
55+
-moz-osx-font-smoothing: grayscale;
56+
-ms-overflow-style: scrollbar;
57+
}
58+
/* Enable for apps that support dark-theme */
59+
/*@media (prefers-color-scheme: dark) {
60+
body {
61+
background-color: black;
62+
}
63+
}*/
64+
</style>
65+
</head>
66+
67+
<body>
68+
<!--
69+
A generic no script element with a reload button and a message.
70+
Feel free to customize this however you'd like.
71+
-->
72+
<noscript>
73+
<form
74+
action=""
75+
style="
76+
background-color: #fff;
77+
position: fixed;
78+
top: 0;
79+
left: 0;
80+
right: 0;
81+
bottom: 0;
82+
z-index: 9999;
83+
"
84+
>
85+
<div
86+
style="
87+
font-size: 18px;
88+
font-family: Helvetica, sans-serif;
89+
line-height: 24px;
90+
margin: 10%;
91+
width: 80%;
92+
"
93+
>
94+
<p>Oh no! It looks like JavaScript is not enabled in your browser.</p>
95+
<p style="margin: 20px 0;">
96+
<button
97+
type="submit"
98+
style="
99+
background-color: #4630eb;
100+
border-radius: 100px;
101+
border: none;
102+
box-shadow: none;
103+
color: #fff;
104+
cursor: pointer;
105+
font-weight: bold;
106+
line-height: 20px;
107+
padding: 6px 16px;
108+
"
109+
>
110+
Reload
111+
</button>
112+
</p>
113+
</div>
114+
</form>
115+
</noscript>
116+
<!-- The root element for your Expo app. -->
117+
<div id="root"></div>
118+
</body>
119+
</html>

0 commit comments

Comments
 (0)