Add entrypoint to ViewProfile from a post's header

This commit is contained in:
Nat 2021-05-21 09:09:58 -03:00
parent 5c42133e53
commit f133458df6
2 changed files with 55 additions and 92 deletions

View File

@ -12,93 +12,30 @@ import * as Linking from "expo-linking";
import AsyncStorage from "@react-native-async-storage/async-storage"; import AsyncStorage from "@react-native-async-storage/async-storage";
import { activeOrNot } from "src/interface/interactions"; import { activeOrNot } from "src/interface/interactions";
import { withoutHTML } from "src/interface/rendering"; import { withoutHTML, pluralize } from "src/interface/rendering";
import * as requests from "src/requests"; import * as requests from "src/requests";
import GridViewJsx from "src/components/posts/grid-view"; import GridViewJsx from "src/components/posts/grid-view";
import { import {
ScreenWithTrayJsx, ScreenWithTrayJsx,
ScreenWithFullNavigationJsx ScreenWithBackBarJsx,
} from "src/components/navigation/navigators"; } from "src/components/navigation/navigators";
import ModerateMenuJsx from "src/components/moderate-menu.js"; import ModerateMenuJsx from "src/components/moderate-menu.js";
const TEST_IMAGE = "https://cache.desktopnexus.com/thumbseg/2255/2255124-bigthumbnail.jpg";
const TEST_POSTS = [
{
id: 1,
media_attachments: [
{preview_url: TEST_IMAGE}
]
},
{
id: 2,
media_attachments: [
{preview_url: TEST_IMAGE}
]
},
{
id: 3,
media_attachments: [
{preview_url: TEST_IMAGE}
]
},
{
id: 4,
media_attachments: [
{preview_url: TEST_IMAGE}
]
}
];
const TEST_PROFILE = {
username: "njms",
acct: "njms",
display_name: "Nat🔆",
locked: false,
bot: false,
note: "Yeah heart emoji.",
avatar: TEST_IMAGE,
followers_count: "1 jillion",
statuses_count: 334,
fields: [
{
name: "Blog",
value: "<a href=\"https://njms.ca\">https://njms.ca</a>",
verified_at: "some time"
},
{
name: "Github",
value: "<a href=\"https://github.com/natjms\">https://github.com/natjms</a>",
verified_at: null
}
]
};
const TEST_YOUR_FOLLOWERS = [
{ id: 1 },
{ id: 2 },
{ id: 3 },
{ id: 4 },
{ id: 5 },
];
const TEST_THEIR_FOLLOWERS = [
{ id: 2 },
{ id: 3 },
{ id: 4 },
{ id: 6 },
];
function getMutuals(yourFollowing, theirFollowers) { function getMutuals(yourFollowing, theirFollowers) {
// Where yours and theirs are arrays of followers, as returned by the API // Where yours and theirs are arrays of followers, as returned by the API
// Returns a list of people you are following that are following some other // Returns a list of people you are following that are following some other
// account // account
const acctsArray = ({acct}) => acct; const getAcct = ({acct}) => acct;
const asIDs = new Set(theirFollowers.map(acctArray)); const theirsAsAccts = new Set(
theirFollowers.map(({acct}) => acct)
);
return yourFollowing.filter(x => asIDs.has(idify(x))); return yourFollowing.filter(x =>
theirsAsAccts.has(x.acct)
);
} }
const HTMLLink = ({link}) => { const HTMLLink = ({link}) => {
@ -129,18 +66,16 @@ const ViewProfileJsx = ({navigation}) => {
}); });
useEffect(() => { useEffect(() => {
let ownProfile, ownDomain, accessToken, domain;
AsyncStorage AsyncStorage
.multiGet(["@user_profile", "@user_instance", "@user_token"]) .multiGet(["@user_profile", "@user_instance", "@user_token"])
.then(([ownProfilePair, ownDomainPair, tokenPair]) => .then(([ ownProfilePair, ownDomainPair, tokenPair ]) => {
[ ownProfile = JSON.parse(ownProfilePair[1]);
JSON.parse(ownProfilePair[1]), ownDomain = ownDomainPair[1];
ownDomainPair[1], accessToken = JSON.parse(tokenPair[1]).access_token;
JSON.parse(tokenPair[1]).access_token,
]
)
.then(([ ownProfile, ownDomain, accessToken ]) => {
const parsedAcct = state.profile.acct.split("@"); const parsedAcct = state.profile.acct.split("@");
const domain = parsedAcct.length == 1 domain = parsedAcct.length == 1
? ownDomain // There's no @ in the acct, thus it's a local user ? ownDomain // There's no @ in the acct, thus it's a local user
: parsedAcct [1] // The part of profile.acct after the @ : parsedAcct [1] // The part of profile.acct after the @
@ -155,26 +90,35 @@ const ViewProfileJsx = ({navigation}) => {
state.profile.id, state.profile.id,
accessToken accessToken
), ),
requests.fetchAccountStatuses(
// NOTE: Should be fetched from remote instance if
// necessary Thus, we use domain and not ownDomain
domain,
state.profile.id,
accessToken
)
]); ]);
}) })
.then(([ ownFollowing, theirFollowers ]) => .then(([ ownFollowing, theirFollowers, posts ]) => {
setState({...state, setState({...state,
mutuals: getMutuals(ownFollowing, theirFollowers), mutuals: getMutuals(ownFollowing, theirFollowers),
posts: posts,
loaded: true, loaded: true,
}) });
); });
}, []); }, []);
return ( return (
<> <>
{ state.loaded { state.loaded
? <ScreenWithFullNavigationJsx ? <ScreenWithBackBarJsx
active = { navigation.getParam("originTab") } active = { navigation.getParam("originTab") }
navigation = { navigation }> navigation = { navigation }>
<RawProfileJsx <RawProfileJsx
profile = { state.profile } profile = { state.profile }
mutuals = { state.mutuals }
notifs = { state.notifs } notifs = { state.notifs }
posts = { TEST_POSTS }/> posts = { state.posts }/>
</ScreenWithFullNavigationJsx> </ScreenWithBackBarJsx>
: <></> : <></>
} }
</> </>
@ -330,7 +274,16 @@ const RawProfileJsx = (props) => {
{ {
props.own ? props.own ?
<>View followers</> <>View followers</>
: <>{ props.mutuals + " mutuals" }</> : <>
{
props.mutuals.length
+ pluralize(
props.mutuals.length,
" mutual",
" mutuals"
)
}
</>
} }
</Text> </Text>

View File

@ -4,8 +4,8 @@ import {
View, View,
Text, Text,
Dimensions, Dimensions,
TouchableWithoutFeedback, TouchableOpacity,
ScrollView ScrollView,
} from "react-native"; } from "react-native";
import { pluralize, timeToAge} from "src/interface/rendering" import { pluralize, timeToAge} from "src/interface/rendering"
@ -71,15 +71,25 @@ export const RawPostJsx = (props) => {
+ pluralize(repliesCount, " comment", " comments"); + pluralize(repliesCount, " comment", " comments");
} }
const _handleProfileButton = () => {
props.navigation.navigate("ViewProfile", {
profile: props.data.account,
});
};
return ( return (
<View> <View>
<View style = { styles.postHeader }> <View style = { styles.postHeader }>
<TouchableOpacity onPress = { _handleProfileButton }>
<Image <Image
style = { styles.pfp } style = { styles.pfp }
source = { { uri: props.data.account.avatar } } /> source = { { uri: props.data.account.avatar } } />
</TouchableOpacity>
<TouchableOpacity onPress = { _handleProfileButton }>
<Text style = { styles.postHeaderName }> <Text style = { styles.postHeaderName }>
{ props.data.account.acct } { props.data.account.acct }
</Text> </Text>
</TouchableOpacity>
<ModerateMenuJsx <ModerateMenuJsx
containerStyle = { styles.menu } containerStyle = { styles.menu }
triggerStyle = { styles.ellipsis } /> triggerStyle = { styles.ellipsis } />
@ -118,7 +128,7 @@ export const RawPostJsx = (props) => {
</Text> </Text>
&nbsp;{ props.data.content } &nbsp;{ props.data.content }
</Text> </Text>
<TouchableWithoutFeedback <TouchableOpacity
onPress = { onPress = {
() => props.navigation.navigate("ViewComments", { () => props.navigation.navigate("ViewComments", {
originTab: props.navigation.getParam("originTab"), originTab: props.navigation.getParam("originTab"),
@ -128,7 +138,7 @@ export const RawPostJsx = (props) => {
<View> <View>
<Text style = { styles.comments }>{ commentsText }</Text> <Text style = { styles.comments }>{ commentsText }</Text>
</View> </View>
</TouchableWithoutFeedback> </TouchableOpacity>
<Text style = { styles.captionDate }> <Text style = { styles.captionDate }>
{ timeToAge(Date.now(), (new Date(props.data.created_at)).getTime()) } { timeToAge(Date.now(), (new Date(props.data.created_at)).getTime()) }