Rewrap pages in ScrollViews
This commit is contained in:
parent
52e8f8f59b
commit
985cbe6ca1
|
@ -1,5 +1,12 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import { View, TextInput, Text, Dimensions } from "react-native";
|
||||
import {
|
||||
ScrollView,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
TextInput,
|
||||
Text,
|
||||
Dimensions
|
||||
} from "react-native";
|
||||
|
||||
import { TabView, TabBar, SceneMap } from "react-native-tab-view";
|
||||
|
||||
|
@ -142,24 +149,26 @@ const Discover = (props) => {
|
|||
return (
|
||||
<>
|
||||
{ state.loaded
|
||||
? <>
|
||||
<TouchableWithoutFeedback
|
||||
onPress = { () => props.navigation.navigate("Search") }>
|
||||
<View style = { styles.form }>
|
||||
<View style = { styles.searchBarContainer }>
|
||||
<Text style = { styles.searchBar }>
|
||||
Search...
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</TouchableWithoutFeedback>
|
||||
? <ScrollView>
|
||||
<View style = { styles.form.container }>
|
||||
<TextInput
|
||||
style = { styles.form.input }
|
||||
placeholder = "Search..."
|
||||
onPressIn = {
|
||||
() => props.navigation.navigate("Search")
|
||||
}/>
|
||||
<TouchableOpacity
|
||||
style = { styles.form.submit }>
|
||||
<Ionicons name="search" size={24} color="black" />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<TabView
|
||||
navigationState = { { index, routes } }
|
||||
renderScene = { renderScene }
|
||||
renderTabBar = { renderTabBar }
|
||||
onIndexChange = { setIndex }
|
||||
initialLayout = { { width: SCREEN_WIDTH } } />
|
||||
</>
|
||||
</ScrollView>
|
||||
: <></>
|
||||
}
|
||||
</>
|
||||
|
@ -169,10 +178,25 @@ const Discover = (props) => {
|
|||
const SCREEN_WIDTH = Dimensions.get("window").width;
|
||||
const styles = {
|
||||
form: {
|
||||
justifyContent: "center",
|
||||
backgroundColor: "white",
|
||||
padding: 20
|
||||
container: {
|
||||
flexDirection: "row",
|
||||
justifyContent: "center",
|
||||
backgroundColor: "white",
|
||||
padding: 20,
|
||||
},
|
||||
|
||||
input: {
|
||||
flexGrow: 1,
|
||||
padding: 10,
|
||||
fontSize: 17,
|
||||
color: "#888"
|
||||
},
|
||||
|
||||
submit: {
|
||||
padding: 20,
|
||||
}
|
||||
},
|
||||
|
||||
searchBar: {
|
||||
padding: 10,
|
||||
fontSize: 17,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import {
|
||||
ScrollView,
|
||||
View,
|
||||
TextInput,
|
||||
Text,
|
||||
|
@ -7,7 +8,7 @@ import {
|
|||
Image,
|
||||
} from "react-native";
|
||||
import { TabView, TabBar, SceneMap } from "react-native-tab-view";
|
||||
import { FontAwesome } from '@expo/vector-icons';
|
||||
import { Ionicons, FontAwesome5 } from '@expo/vector-icons';
|
||||
import AsyncStorage from "@react-native-async-storage/async-storage";
|
||||
|
||||
import * as requests from "src/requests";
|
||||
|
@ -112,7 +113,7 @@ const Search = ({navigation}) => {
|
|||
const [ routes ] = useState([
|
||||
{
|
||||
key: "accounts",
|
||||
icon: "user",
|
||||
icon: "user-alt",
|
||||
},
|
||||
{
|
||||
key: "hashtags",
|
||||
|
@ -152,7 +153,7 @@ const Search = ({navigation}) => {
|
|||
);
|
||||
|
||||
const renderIcon = ({ route, color }) => (
|
||||
<FontAwesome
|
||||
<FontAwesome5
|
||||
name = { route.icon }
|
||||
size = { 24 }
|
||||
color = { color } />
|
||||
|
@ -161,7 +162,7 @@ const Search = ({navigation}) => {
|
|||
return (
|
||||
<>
|
||||
{ state.loaded
|
||||
? <>
|
||||
? <ScrollView>
|
||||
<View style = { styles.form.container }>
|
||||
<TextInput
|
||||
style = { styles.form.input }
|
||||
|
@ -182,7 +183,7 @@ const Search = ({navigation}) => {
|
|||
<TouchableOpacity
|
||||
onPress = { _handleSearch }
|
||||
style = { styles.form.submit }>
|
||||
<FontAwesome name="search" size={24} color="black" />
|
||||
<Ionicons name="search" size={24} color="black" />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
{ state.results
|
||||
|
@ -194,7 +195,7 @@ const Search = ({navigation}) => {
|
|||
initialLayout = { { width: SCREEN_WIDTH } } />
|
||||
: <></>
|
||||
}
|
||||
</>
|
||||
</ScrollView>
|
||||
: <></>
|
||||
}
|
||||
</>
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
import { View, Image, Dimensions, Text } from "react-native";
|
||||
import { ScrollView, View, Image, Dimensions, Text } from "react-native";
|
||||
import PagedGrid from "src/components/posts/paged-grid";
|
||||
|
||||
import * as requests from "src/requests";
|
||||
import AsyncStorage from "@react-native-async-storage/async-storage";
|
||||
|
||||
const ViewHashtag = ({navigation}) => {
|
||||
const ViewHashtag = ({ navigation, route }) => {
|
||||
const FETCH_LIMIT = 18;
|
||||
let [state, setState] = useState({
|
||||
tag: navigation.getParam("tag", null),
|
||||
tag: route.params.tag,
|
||||
posts: [],
|
||||
offset: 0,
|
||||
followed: false,
|
||||
|
@ -66,10 +66,16 @@ const ViewHashtag = ({navigation}) => {
|
|||
});
|
||||
};
|
||||
|
||||
const latest = state.tag.history[0];
|
||||
// A hashtag's history describes how actively it's being used. There's
|
||||
// one element in the history array for every set interval of time.
|
||||
// state.tag.history may be undefined, and its length might be 0.
|
||||
let latest = null;
|
||||
if (state.tag.history && state.tag.history.length > 0) {
|
||||
latest = state.tag.history[0];
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<ScrollView>
|
||||
<View>
|
||||
<View style = { styles.headerContainer }>
|
||||
<View>
|
||||
|
@ -105,17 +111,19 @@ const ViewHashtag = ({navigation}) => {
|
|||
</View>
|
||||
<>
|
||||
{ state.loaded && state.posts.length > 0
|
||||
? <PagedGrid
|
||||
navigation = { navigation }
|
||||
posts = { state.posts }
|
||||
onShowMore = { _handleShowMore } />
|
||||
: <Text style = { styles.nothing }>
|
||||
Nothing to show
|
||||
</Text>
|
||||
? state.posts.length > 0
|
||||
? <PagedGrid
|
||||
navigation = { navigation }
|
||||
posts = { state.posts }
|
||||
onShowMore = { _handleShowMore } />
|
||||
: <Text style = { styles.nothing }>
|
||||
Nothing to show
|
||||
</Text>
|
||||
: <></>
|
||||
}
|
||||
</>
|
||||
</View>
|
||||
</>
|
||||
</ScrollView>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import {
|
|||
Text,
|
||||
TouchableOpacity,
|
||||
FlatList,
|
||||
ScrollView,
|
||||
} from "react-native";
|
||||
|
||||
import * as Linking from "expo-linking";
|
||||
|
@ -13,7 +14,12 @@ import AsyncStorage from "@react-native-async-storage/async-storage";
|
|||
|
||||
import { activeOrNot } from "src/interface/interactions";
|
||||
import HTML from "react-native-render-html";
|
||||
import { withLeadingAcct, withoutHTML, pluralize } from "src/interface/rendering";
|
||||
import {
|
||||
withLeadingAcct,
|
||||
withoutHTML,
|
||||
pluralize,
|
||||
StatusBarSpace,
|
||||
} from "src/interface/rendering";
|
||||
import * as requests from "src/requests";
|
||||
|
||||
import GridView from "src/components/posts/grid-view";
|
||||
|
@ -56,11 +62,11 @@ const HTMLLink = ({link}) => {
|
|||
}
|
||||
}
|
||||
|
||||
const ViewProfile = ({navigation}) => {
|
||||
const ViewProfile = ({ navigation, route }) => {
|
||||
// As rendered when opened from somewhere other than the tab bar
|
||||
const [state, setState] = useState({
|
||||
loaded: false,
|
||||
profile: navigation.getParam("profile"),
|
||||
profile: route.params.profile,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -159,9 +165,7 @@ const ViewProfile = ({navigation}) => {
|
|||
return (
|
||||
<>
|
||||
{ state.loaded
|
||||
? <>
|
||||
active = { navigation.getParam("originTab") }
|
||||
navigation = { navigation }>
|
||||
? <ScrollView>
|
||||
<RawProfile
|
||||
navigation = { navigation }
|
||||
onFollow = { _handleFollow }
|
||||
|
@ -172,7 +176,7 @@ const ViewProfile = ({navigation}) => {
|
|||
listedUsers = { state.listedUsers }
|
||||
followed = { state.followed }
|
||||
posts = { state.posts }/>
|
||||
</>
|
||||
</ScrollView>
|
||||
: <></>
|
||||
}
|
||||
</>
|
||||
|
@ -184,57 +188,65 @@ const Profile = ({ navigation }) => {
|
|||
loaded: false,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
let profile;
|
||||
let notifs;
|
||||
let domain;
|
||||
let accessToken;
|
||||
const init = async () => {
|
||||
const [
|
||||
profilePair,
|
||||
notifPair,
|
||||
instancePair,
|
||||
tokenPair
|
||||
] = await AsyncStorage.multiGet([
|
||||
"@user_profile",
|
||||
"@user_notifications",
|
||||
"@user_instance",
|
||||
"@user_token",
|
||||
]);
|
||||
|
||||
AsyncStorage
|
||||
.multiGet([
|
||||
const profile = JSON.parse(profilePair[1]);
|
||||
const notifs = JSON.parse(notifPair[1]);
|
||||
const instance = instancePair[1];
|
||||
const accessToken = JSON.parse(tokenPair[1]).access_token;
|
||||
|
||||
const latestProfile =
|
||||
await requests.fetchProfile(instance, profile.id, accessToken);
|
||||
const posts =
|
||||
await requests.fetchAccountStatuses(instance, profile.id, accessToken);
|
||||
const followers =
|
||||
await requests.fetchFollowers(instance, profile.id, accessToken);
|
||||
|
||||
const latestProfileString = JSON.stringify(latestProfile);
|
||||
|
||||
// Update the profile in AsyncStorage if it's changed
|
||||
if(latestProfileString != JSON.stringify(profile)) {
|
||||
await AsyncStorage.setItem(
|
||||
"@user_profile",
|
||||
"@user_notifications",
|
||||
"@user_instance",
|
||||
"@user_token",
|
||||
])
|
||||
.then(([profilePair, notifPair, domainPair, tokenPair]) => {
|
||||
profile = JSON.parse(profilePair[1]);
|
||||
notifs = JSON.parse(notifPair[1]);
|
||||
domain = domainPair[1];
|
||||
accessToken = JSON.parse(tokenPair[1]).access_token;
|
||||
latestProfileString
|
||||
);
|
||||
}
|
||||
|
||||
return Promise.all([
|
||||
requests.fetchProfile(domain, profile.id),
|
||||
requests.fetchAccountStatuses(domain, profile.id, accessToken),
|
||||
requests.fetchFollowers(domain, profile.id, accessToken),
|
||||
]);
|
||||
})
|
||||
.then(([latestProfile, posts, followers]) => {
|
||||
if(JSON.stringify(latestProfile) != JSON.stringify(profile)) {
|
||||
profile = latestProfile
|
||||
}
|
||||
|
||||
setState({...state,
|
||||
profile: profile,
|
||||
notifs: notifs,
|
||||
posts: posts,
|
||||
setState({...state,
|
||||
profile: latestProfile,
|
||||
notifs: notifs,
|
||||
posts: posts,
|
||||
listedUsers: followers,
|
||||
loaded: true,
|
||||
});
|
||||
});
|
||||
}, []);
|
||||
loaded: true,
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => { init(); }, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
<StatusBarSpace/>
|
||||
{ state.loaded
|
||||
? <>
|
||||
? <ScrollView>
|
||||
<RawProfile
|
||||
navigation = { navigation }
|
||||
own = { true }
|
||||
profile = { state.profile }
|
||||
posts = { state.posts }
|
||||
listedUsers = { state.listedUsers }
|
||||
listedUsers = { state.listedUsers }
|
||||
notifs = { state.notifs }/>
|
||||
</>
|
||||
</ScrollView>
|
||||
: <></>
|
||||
}
|
||||
</>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import React, { useState, useEffect } from "react";
|
||||
|
||||
import {
|
||||
ScrollView,
|
||||
SafeAreaView,
|
||||
View,
|
||||
TextInput,
|
||||
|
@ -134,7 +135,7 @@ const Settings = (props) => {
|
|||
return (
|
||||
<>
|
||||
{ state.loaded
|
||||
? <>
|
||||
? <ScrollView>
|
||||
<View style = { styles.avatar.container }>
|
||||
<Image
|
||||
source = { { uri: state.newAvatar.uri } }
|
||||
|
@ -215,7 +216,7 @@ const Settings = (props) => {
|
|||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</>
|
||||
</ScrollView>
|
||||
: <></>
|
||||
}
|
||||
</>
|
||||
|
|
|
@ -40,7 +40,7 @@ const GridView = (props) => {
|
|||
&& p.media_attachments.length > 0
|
||||
);
|
||||
|
||||
let rows = partition(props.posts, 3);
|
||||
let rows = partition(postsWithMedia, 3);
|
||||
return (
|
||||
<View>
|
||||
{
|
||||
|
|
|
@ -80,6 +80,12 @@ export const RawPost = (props) => {
|
|||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (props.onRendered != null) {
|
||||
props.onRendered();
|
||||
}
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<View>
|
||||
<View style = { styles.postHeader }>
|
||||
|
@ -349,6 +355,7 @@ export const PostByData = (props) => {
|
|||
<RawPost
|
||||
data = { state.data }
|
||||
dimensions = { state.dimensions }
|
||||
onRendered = { props.onRendered }
|
||||
onFavourite = { _handleFavourite }
|
||||
onReblog = { _handleReblog }
|
||||
onBookmark = { _handleDelete }
|
||||
|
|
|
@ -104,8 +104,8 @@ export async function verifyCredentials(domain, token) {
|
|||
return resp.json();
|
||||
}
|
||||
|
||||
export async function fetchProfile(domain, id) {
|
||||
const resp = await get(`https://${domain}/api/v1/accounts/${id}`);
|
||||
export async function fetchProfile(domain, id, token) {
|
||||
const resp = await get(`https://${domain}/api/v1/accounts/${id}`, token);
|
||||
return resp.json();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue