Ensure timeline interruption only gets rendered after the posts. Fixes #38

This commit is contained in:
Nat 2022-03-30 08:55:45 -07:00
parent 78eaf0efe6
commit 1aebc9f770
3 changed files with 65 additions and 38 deletions

View File

@ -13,6 +13,7 @@ import * as requests from "src/requests";
const FeedJsx = (props) => {
const [state, setState] = useState({
loaded: false,
postsRendered: false,
});
useEffect(() => {
@ -63,6 +64,43 @@ const FeedJsx = (props) => {
);
}, []);
const _handleTimelineLoaded = () => setState({...state,
postsRendered: true,
});
let endOfTimelineMessage = <></>;
if (state.postsRendered) {
// Only render the timeline interruption if all of the posts have been
// rendered in the feed.
endOfTimelineMessage = <>
<View style = {
state.posts.length == 0
? {}
: styles.interruption.topBorder
}>
<View style = { styles.interruption.inner }>
<Ionicons
name="ios-checkmark-circle-outline"
size= { 150 }
color="black" />
<Text style = { styles.interruption.header }>
You're all caught up.
</Text>
<Text> Wow, it sure is a lovely day outside 🌳 </Text>
<TouchableWithoutFeedback
style = { styles.interruption.button }
onPress = {
() => props.navigation.navigate("OlderPosts")
}>
<Text> See older posts </Text>
</TouchableWithoutFeedback>
</View>
</View>
</>;
}
return (
<>
{ state.loaded
@ -77,33 +115,9 @@ const FeedJsx = (props) => {
<TimelineViewJsx
navigation = { props.navigation }
posts = { state.posts } />
<View style = {
state.posts.length == 0
? {}
: styles.interruption.topBorder
}>
<View style = { styles.interruption.inner }>
<Ionicons
name="ios-checkmark-circle-outline"
size= { 150 }
color="black" />
<Text style = { styles.interruption.header }>
You're all caught up.
</Text>
<Text> Wow, it sure is a lovely day outside 🌳 </Text>
<TouchableWithoutFeedback
style = { styles.interruption.button }
onPress = {
() => props.navigation.navigate("OlderPosts")
}>
<Text> See older posts </Text>
</TouchableWithoutFeedback>
</View>
</View>
posts = { state.posts }
onTimelineLoaded = { _handleTimelineLoaded }/>
{ endOfTimelineMessage }
</ScreenWithTrayJsx>
: <></>
}

View File

@ -180,8 +180,8 @@ export const RawPostJsx = (props) => {
export const PostByDataJsx = (props) => {
/*
Renders a post where the data is supplied directly to the element through
its properties, as it is in a timeline.
* Renders a post where the data is supplied directly to the element through
* its properties, as it is in a timeline.
*/
let [state, setState] = useState({
@ -217,6 +217,10 @@ export const PostByDataJsx = (props) => {
own,
loaded: true
});
if (props.onPostLoaded != null) {
props.onPostLoaded();
}
});
}, []);
@ -417,13 +421,6 @@ const styles = {
}
};
// customStyles for react-native-popup-menu should be defined in particular
// objects to be interpreted correctly.
//const menuStyles = {
// menuProviderWrapper
//}
const optionsStyles = {
optionWrapper: { // The wrapper around a single option
paddingLeft: SCREEN_WIDTH / 15,

View File

@ -1,15 +1,30 @@
import React from "react";
import React, { useState, useEffect } from "react";
import { View } from "react-native";
import { PostByDataJsx } from "src/components/posts/post";
const TimelineViewJsx = (props) => {
// Count the number of posts that have already loaded
const [postsLoaded, setPostsLoaded] = useState(0);
// Ensure only posts with media get in the timeline
const posts = props.posts.filter(
p => p.media_attachments != null
&& p.media_attachments.length > 0
);
useEffect(() => {
// When all the posts have been loaded, call onTimelineLoaded
// if it's been defined
if (postsLoaded == posts.length) {
if (props.onTimelineLoaded != null) {
props.onTimelineLoaded();
}
}
}, [postsLoaded]);
_handlePostLoaded = () => setPostsLoaded(postsLoaded + 1);
return (
<View>
{ props.posts.map((post, i) => {
@ -17,7 +32,8 @@ const TimelineViewJsx = (props) => {
<View key = { i } >
<PostByDataJsx
navigation = { props.navigation }
data = { post } />
data = { post }
onPostLoaded = { _handlePostLoaded }/>
</View>
);
}) }