Merge pull request #18 from natjms/discover

Implementing discover
This commit is contained in:
Nat 2021-04-10 13:51:37 -03:00 committed by GitHub
commit 341fc61116
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 666 additions and 64 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

10
package-lock.json generated
View File

@ -6137,6 +6137,11 @@
"resolved": "https://registry.npmjs.org/react-native-iphone-x-helper/-/react-native-iphone-x-helper-1.2.1.tgz", "resolved": "https://registry.npmjs.org/react-native-iphone-x-helper/-/react-native-iphone-x-helper-1.2.1.tgz",
"integrity": "sha512-/VbpIEp8tSNNHIvstuA3Swx610whci1Zpc9mqNkqn14DkMbw+ORviln2u0XyHG1kPvvwTNGZY6QpeFwxYaSdbQ==" "integrity": "sha512-/VbpIEp8tSNNHIvstuA3Swx610whci1Zpc9mqNkqn14DkMbw+ORviln2u0XyHG1kPvvwTNGZY6QpeFwxYaSdbQ=="
}, },
"react-native-pager-view": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/react-native-pager-view/-/react-native-pager-view-5.1.2.tgz",
"integrity": "sha512-UvPvjtuIkiI9Ti8NoMH+fiFj0ehfFv4WkNUGM46dOJfOxmE6Z/hoyJjymOHU//iLkQSMO+YNherZs0HcijdA2A=="
},
"react-native-popup-menu": { "react-native-popup-menu": {
"version": "0.15.10", "version": "0.15.10",
"resolved": "https://registry.npmjs.org/react-native-popup-menu/-/react-native-popup-menu-0.15.10.tgz", "resolved": "https://registry.npmjs.org/react-native-popup-menu/-/react-native-popup-menu-0.15.10.tgz",
@ -6168,6 +6173,11 @@
"resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-2.9.0.tgz", "resolved": "https://registry.npmjs.org/react-native-screens/-/react-native-screens-2.9.0.tgz",
"integrity": "sha512-5MaiUD6HA3nzY3JbVI8l3V7pKedtxQF3d8qktTVI0WmWXTI4QzqOU8r8fPVvfKo3MhOXwhWBjr+kQ7DZaIQQeg==" "integrity": "sha512-5MaiUD6HA3nzY3JbVI8l3V7pKedtxQF3d8qktTVI0WmWXTI4QzqOU8r8fPVvfKo3MhOXwhWBjr+kQ7DZaIQQeg=="
}, },
"react-native-tab-view": {
"version": "2.16.0",
"resolved": "https://registry.npmjs.org/react-native-tab-view/-/react-native-tab-view-2.16.0.tgz",
"integrity": "sha512-ac2DmT7+l13wzIFqtbfXn4wwfgtPoKzWjjZyrK1t+T8sdemuUvD4zIt+UImg03fu3s3VD8Wh/fBrIdcqQyZJWg=="
},
"react-native-web": { "react-native-web": {
"version": "0.11.7", "version": "0.11.7",
"resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.11.7.tgz", "resolved": "https://registry.npmjs.org/react-native-web/-/react-native-web-0.11.7.tgz",

View File

@ -19,10 +19,12 @@
"react-dom": "~16.11.0", "react-dom": "~16.11.0",
"react-native": "https://github.com/expo/react-native/archive/sdk-38.0.2.tar.gz", "react-native": "https://github.com/expo/react-native/archive/sdk-38.0.2.tar.gz",
"react-native-gesture-handler": "~1.6.0", "react-native-gesture-handler": "~1.6.0",
"react-native-pager-view": "^5.1.2",
"react-native-popup-menu": "^0.15.10", "react-native-popup-menu": "^0.15.10",
"react-native-reanimated": "~1.9.0", "react-native-reanimated": "~1.9.0",
"react-native-safe-area-context": "~3.0.7", "react-native-safe-area-context": "~3.0.7",
"react-native-screens": "~2.9.0", "react-native-screens": "~2.9.0",
"react-native-tab-view": "^2.16.0",
"react-native-web": "~0.11.7", "react-native-web": "~0.11.7",
"react-navigation": "^4.4.0", "react-navigation": "^4.4.0",
"react-navigation-stack": "^2.8.2" "react-navigation-stack": "^2.8.2"

View File

@ -1,5 +1,8 @@
import React from "react"; import React, { useState, useEffect } from "react";
import { Image } from "react-native"; import { Image } from "react-native";
import { checkUnreadNotifications } from "src/requests";
import { activeOrNot } from "src/interface/interactions" import { activeOrNot } from "src/interface/interactions"
import { TouchableWithoutFeedback, View } from "react-native"; import { TouchableWithoutFeedback, View } from "react-native";
@ -18,6 +21,19 @@ const TrayButtonJsx = (props) => {
const TrayJsx = (props) => { const TrayJsx = (props) => {
const nav = props.navigation; const nav = props.navigation;
const [state, setState] = useState({
unreadNotifications: false
});
useEffect(() => {
checkUnreadNotifications()
.then(isUnread => {
setState({...state,
unreadNotifications: isUnread,
});
});
}, []);
const icons = { const icons = {
feed: { feed: {
@ -40,6 +56,10 @@ const TrayJsx = (props) => {
active: require("assets/eva-icons/person-black.png"), active: require("assets/eva-icons/person-black.png"),
inactive: require("assets/eva-icons/person-grey.png") inactive: require("assets/eva-icons/person-grey.png")
}, },
profileNotif: {
active: require("assets/eva-icons/person-black-notif.png"),
inactive: require("assets/eva-icons/person-grey-notif.png")
},
} }
return ( return (
@ -67,7 +87,11 @@ const TrayJsx = (props) => {
nav = { nav } /> nav = { nav } />
<TrayButtonJsx <TrayButtonJsx
where = "Profile" where = "Profile"
pack = { icons.profile } pack = {
state.unreadNotifications ?
icons.profileNotif
: icons.profile
}
active = { props.active } active = { props.active }
nav = { nav } /> nav = { nav } />
</View> </View>

View File

@ -44,18 +44,28 @@ const AuthenticateJsx = ({navigation}) => {
}); });
useEffect(() => { useEffect(() => {
const profile = AsyncStorage.getItem("@user_profile").then((profile) => { AsyncStorage.getItem("@user_profile").then((profile) => {
if (profile != null) { if (profile) {
navigation.navigate("feed"); navigation.navigate("Feed");
} }
setState({...state, authChecked: true}); setState({...state, authChecked: true});
}); });
}, []); }, []);
const loginCallback = async () => { const loginCallback = () => {
const profileJSON = JSON.stringify(TEST_PROFILE); const initialization = [
AsyncStorage.setItem("@user_profile", profileJSON).then(() => { [ "@user_profile", JSON.stringify(TEST_PROFILE) ],
[
"@user_notifications",
JSON.stringify({
unread: false,
memory: [{ id: 1 }, { id: 2 }],
})
]
];
AsyncStorage.multiSet(initialization).then(() => {
navigation.navigate("Feed"); navigation.navigate("Feed");
}); });
}; };

View File

@ -1,11 +1,61 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { View, TextInput, Text, Dimensions } from "react-native"; import { View, TextInput, Text, Dimensions } from "react-native";
import { TabView, TabBar, SceneMap } from "react-native-tab-view";
import { Ionicons } from "@expo/vector-icons";
import PagedGridJsx from "src/components/posts/paged-grid"; import PagedGridJsx from "src/components/posts/paged-grid";
import { ScreenWithTrayJsx } from "src/components/navigation/navigators"; import { ScreenWithTrayJsx } from "src/components/navigation/navigators";
import { TouchableWithoutFeedback } from "react-native-gesture-handler"; import { TouchableWithoutFeedback } from "react-native-gesture-handler";
const DiscoverJsx = (props) => { const DiscoverJsx = (props) => {
const [index, setIndex] = useState(0);
const [routes] = useState([
{
key: "home",
icon: "md-home",
},
{
key: "federated",
icon: "md-planet",
},
]);
const HomeTimeline = () => (
<PagedGridJsx
navigation = { props.navigation }
originTab = "Discover" />
);
const FederatedTimeline = () => (
<PagedGridJsx
navigation = { props.navigation }
originTab = "Discover" />
);
const renderScene = SceneMap({
home: HomeTimeline,
federated: FederatedTimeline,
});
const renderTabBar = (props) => (
<TabBar
{...props}
indicatorStyle = { styles.tabBar.indicator }
activeColor = "#000"
inactiveColor = "#888"
renderIcon = { renderIcon }
style = { styles.tabBar.tab } />
);
const renderIcon = ({ route, color }) => (
<Ionicons
name = { route.icon }
size = { 24 }
color = { color } />
);
return ( return (
<ScreenWithTrayJsx <ScreenWithTrayJsx
active = "Discover" active = "Discover"
@ -20,13 +70,17 @@ const DiscoverJsx = (props) => {
</View> </View>
</View> </View>
</TouchableWithoutFeedback> </TouchableWithoutFeedback>
<PagedGridJsx <TabView
navigation = { props.navigation } navigationState = { { index, routes } }
originTab = "Discover" /> renderScene = { renderScene }
renderTabBar = { renderTabBar }
onIndexChange = { setIndex }
initialLayout = { { width: SCREEN_WIDTH } } />
</ScreenWithTrayJsx> </ScreenWithTrayJsx>
); );
}; };
const SCREEN_WIDTH = Dimensions.get("window").width;
const styles = { const styles = {
form: { form: {
display: "flex", display: "flex",
@ -37,7 +91,14 @@ const styles = {
searchBar: { searchBar: {
padding: 10, padding: 10,
fontSize: 17, fontSize: 17,
color: "#888" color: "#888",
borderBottomWidth: 1,
borderBottomColor: "#CCC",
},
tabBar: {
indicator: { backgroundColor: "black" },
tab: { backgroundColor: "white" },
}, },
}; };

View File

@ -67,11 +67,11 @@ const SearchJsx = ({navigation}) => {
{ state.query == "" ? { state.query == "" ?
<View></View> <View></View>
: <View> : <View>
<Text>Accounts</Text> <Text style = { styles.label }>Accounts</Text>
<AccountsListJsx <AccountsListJsx
data = { TEST_ACCOUNTS } data = { TEST_ACCOUNTS }
callback = { accountCallback } /> callback = { accountCallback } />
<Text>Hashtags</Text> <Text style = { styles.label }>Hashtags</Text>
<HashtagListJsx <HashtagListJsx
data = { TEST_HASHTAGS } data = { TEST_HASHTAGS }
callback = { hashtagCallback } /> callback = { hashtagCallback } />
@ -156,6 +156,10 @@ const styles = {
fontSize: 17, fontSize: 17,
color: "#888" color: "#888"
}, },
label: {
padding: 10,
fontSize: 15,
},
searchList: { padding: 0 }, searchList: { padding: 0 },
searchResultContainer: { searchResultContainer: {
display: "flex", display: "flex",

View File

@ -2,15 +2,15 @@ import React, { useState } from "react";
import { View, Image, Dimensions, Text } from "react-native"; import { View, Image, Dimensions, Text } from "react-native";
import { ScreenWithFullNavigationJsx } from "src/components/navigation/navigators"; import { ScreenWithFullNavigationJsx } from "src/components/navigation/navigators";
import PagedGridJsx from "src/components/posts/paged-grid"; import PagedGridJsx from "src/components/posts/paged-grid";
import { TouchableWithoutFeedback } from "react-native-gesture-handler"; import { TouchableOpacity } from "react-native-gesture-handler";
const FollowHashtagButtonJsx = ({followed, onPress}) => { const FollowHashtagButtonJsx = ({followed, onPress}) => {
return ( return (
<TouchableWithoutFeedback <TouchableOpacity
style = { style = {
[ [
styles.button, styles.button,
followed ? { backgroundColor: "black" } : {} followed ? { backgroundColor: "#888" } : {}
] ]
} }
onPress = { onPress }> onPress = { onPress }>
@ -18,7 +18,7 @@ const FollowHashtagButtonJsx = ({followed, onPress}) => {
style = { followed ? { color: "white" } : {} }> style = { followed ? { color: "white" } : {} }>
{ followed ? "Followed" : "Follow" } { followed ? "Followed" : "Follow" }
</Text> </Text>
</TouchableWithoutFeedback> </TouchableOpacity>
); );
}; };
@ -69,33 +69,33 @@ const ViewHashtagJsx = ({navigation}) => {
const screen_width = Dimensions.get("window").width; const screen_width = Dimensions.get("window").width;
const styles = { const styles = {
headerContainer: { headerContainer: {
display: "flex",
flexDirection: "row", flexDirection: "row",
alignItems: "center", alignItems: "center",
padding: 15, padding: 15,
borderBottom: "2px solid black"
}, },
image: { image: {
width: screen_width / 3, width: screen_width / 3,
height: screen_width / 3, height: screen_width / 3,
border: "2px solid black", borderWidth: 1,
borderColor: "#888",
borderRadius: "100%", borderRadius: "100%",
marginRight: 20 marginRight: 20,
}, },
hashtag: { hashtag: {
fontWeight: "bold", fontWeight: "bold",
fontSize: 20 fontSize: 20
}, },
button: { button: {
border: "2px solid black", borderWidth: 1,
borderColor: "#888",
borderRadius: 5, borderRadius: 5,
padding: 10, padding: 10,
paddingLeft: 30, paddingLeft: 30,
paddingRight: 30, paddingRight: 30,
marginTop: 10 marginTop: 10,
}, },
strong: { strong: {
fontWeight: "bold" fontWeight: "bold",
}, },
} }

View File

@ -150,9 +150,16 @@ const ProfileDisplayJsx = ({navigation}) => {
} }
useEffect(() => { useEffect(() => {
AsyncStorage.getItem("@user_profile").then((profileJSON) => { AsyncStorage.multiGet(["@user_profile", "@user_notifications"])
.then(values => {
const [profileJSON, notificationsJSON] = values;
const profile = JSON.parse(profileJSON[1]);
const notifications = JSON.parse(notificationsJSON[1]);
console.log(notifications);
setState({ setState({
profile: JSON.parse(profileJSON), profile: profile,
unreadNotifications: notifications.unread,
mutuals: getMutuals(TEST_YOUR_FOLLOWERS, TEST_THEIR_FOLLOWERS), mutuals: getMutuals(TEST_YOUR_FOLLOWERS, TEST_THEIR_FOLLOWERS),
own: true, own: true,
loaded: true, loaded: true,
@ -205,9 +212,19 @@ const ProfileDisplayJsx = ({navigation}) => {
{ {
state.own ? state.own ?
<View style = { styles.profileContextContainer }> <View style = { styles.profileContextContainer }>
<TouchableOpacity> <TouchableOpacity
onPress = {
() => {
navigation.navigate("Notifications");
}
}>
<Image <Image
source = { activeOrNot(state.unread_notifs, notif_pack) } source = {
activeOrNot(
state.unreadNotifications,
notif_pack
)
}
style = { styles.profileHeaderIcon } /> style = { styles.profileHeaderIcon } />
</TouchableOpacity> </TouchableOpacity>
</View> </View>

View File

@ -1,14 +1,439 @@
import React, { useState } from "react"; import React, { useState, useEffect } from "react";
import { ScreenWithTrayJsx } from "src/components/navigation/navigators";
const NotificationsJsx = ({navigation}) => { import {
Dimensions,
View,
TouchableOpacity,
Image,
Text,
} from "react-native";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { ScreenWithBackBarJsx } from "src/components/navigation/navigators";
const TEST_IMAGE = "https://cache.desktopnexus.com/thumbseg/2255/2255124-bigthumbnail.jpg";
const TEST_NOTIFICATIONS = [
{
id: 1,
type: "follow",
account: {
acct: "njms",
avatar: TEST_IMAGE,
},
},
{
id: 2,
type: "follow_request",
account: {
acct: "njms",
avatar: TEST_IMAGE,
},
},
{
id: 3,
type: "mention",
account: {
acct: "njms",
avatar: TEST_IMAGE,
},
status: {
id: 1,
media_attachments: [],
content: "This is a message",
}
},
{
id: 4,
type: "mention",
account: {
acct: "njms",
avatar: TEST_IMAGE,
},
status: {
id: 1,
media_attachments: [
{ url: TEST_IMAGE }
],
content: "This is a message",
}
},
{
id: 5,
type: "mention",
account: {
acct: "njms",
avatar: TEST_IMAGE,
},
status: {
id: 1,
media_attachments: [
{ url: TEST_IMAGE }
],
content: "This is a really really really really really really"
+ " really really really really really really long message",
}
},
{
id: 6,
type: "reblog",
account: {
acct: "njms",
avatar: TEST_IMAGE,
},
status: {
id: 1,
media_attachments: [
{ url: TEST_IMAGE }
],
}
},
{
id: 7,
type: "favourite",
account: {
acct: "njms",
avatar: TEST_IMAGE,
},
status: {
id: 1,
media_attachments: [
{ url: TEST_IMAGE }
],
}
},
{
id: 8,
type: "status",
account: {
acct: "njms",
avatar: TEST_IMAGE,
},
status: {
id: 1,
media_attachments: [
{ url: TEST_IMAGE }
],
}
},
]
function navigateProfileFactory(nav, acct) {
return () => {
nav.navigate("ViewProfile", {
acct: acct,
});
};
}
function navigatePostFactory(nav, id) {
return () => {
nav.navigate("ViewPost", {
originTab: "Profile",
id: id,
});
}
}
function renderNotification(notif, navigation) {
switch(notif.type) {
case "follow":
return <FollowJsx
data = { notif }
key = { notif.id }
navigation = { navigation } />
case "follow_request":
return <FollowRequestJsx
data = { notif }
key = { notif.id }
navigation = { navigation } />
case "mention":
return <MentionJsx
data = { notif }
key = { notif.id }
navigation = { navigation } />
case "reblog":
return <ReblogJsx
data = { notif }
key = { notif.id }
navigation = { navigation } />
case "favourite":
return <FavouriteJsx
data = { notif }
key = { notif.id }
navigation = { navigation } />
case "status":
return <StatusJsx
data = { notif }
key = { notif.id }
navigation = { navigation } />
default:
// We're not expecting polls to be super popular on Pixelfed
return <></>
}
}
const UserTextJsx = (props) => {
return ( return (
<ScreenWithTrayJsx <Text
active = "Notifications" style = { styles.bold }
navigation = { navigation }> onPress = {
() => {
props.navigation.navigate("ViewProfile", {
acct: props.acct
});
}
}>
{ props.acct }&nbsp;
</Text>
);
};
</ScreenWithTrayJsx> const NotificationJsx = (props) => {
return (
<View style = { styles.notif.container }>
<View style = { styles.notif.thumbnailContainer }>
<TouchableOpacity
onPress = { props.thumbnailPressCallback }>
<Image
style = {
[
styles.notif.thumbnail,
props.thumbnailStyles
]
}
source = { { uri: props.thumbnail } } />
</TouchableOpacity>
</View>
<View style = { styles.notif.contentContainer }>
{ props.children }
</View>
{ props.button ?
<View style = { styles.notif.buttonContainer }>
<TouchableOpacity
style = { styles.notif.button }
onPress = { props.buttonCallback }>
<Text>{ props.buttonLabel }</Text>
</TouchableOpacity>
</View>
: <></>
}
</View>
);
};
const FollowJsx = (props) => {
return (
<NotificationJsx
thumbnail = { props.data.account.avatar }
thumbnailStyles = { styles.notif.circularThumbnail }
thumbnailPressCallback = {
navigateProfileFactory(props.navigation, props.data.account.acct)
}>
<Text style = { styles.notif.content }>
<UserTextJsx acct = { props.data.account.acct } />
has followed you.
</Text>
</NotificationJsx>
);
};
const FollowRequestJsx = (props) => {
return (
<NotificationJsx
thumbnail = { props.data.account.avatar }
thumbnailStyles = { styles.notif.circularThumbnail }
thumbnailPressCallback = {
navigateProfileFactory(props.navigation, props.data.account.acct)
}
button = { true }
buttonLabel = { "Accept" }
buttonCallback = { () => console.log("Request accepted") }>
<Text style = { styles.notif.content }>
<UserTextJsx acct = { props.data.account.acct } />
has requested to follow you.
</Text>
</NotificationJsx>
);
};
const MentionJsx = (props) => {
let uri;
let imageStyle;
let thumbnailCallback;
if (props.data.status.media_attachments.length > 0) {
// If it's a comment...
uri = props.data.status.media_attachments[0].url;
imageStyle = {};
thumbnailCallback = navigatePostFactory(
props.navigation,
props.data.status.id
);
} else {
// If it's a reply to your comment...
uri = props.data.account.avatar;
imageStyle = styles.notif.circularThumbnail;
thumbnailCallback = navigateProfileFactory(
props.navigation,
props.data.account.acct
); );
} }
return (
<NotificationJsx
thumbnail = { uri }
thumbnailStyles = { imageStyle }i
thumbnailPressCallback = { thumbnailCallback }>
<Text style = { styles.notif.content }>
<UserTextJsx acct = { props.data.account.acct } />
mentioned you:
<Text style = { styles.notif.status }>
"{ props.data.status.content }"
</Text>
</Text>
</NotificationJsx>
);
};
const ReblogJsx = (props) => {
return (
<NotificationJsx
thumbnail = { props.data.status.media_attachments[0].url }
thumbnailPressCallback = {
navigatePostFactory(props.navigation, props.data.status.id)
}>
<Image
style = { styles.notif.inlineIcon }
source = { require("assets/eva-icons/post-actions/boost-full.png") } />
<Text style = { styles.notif.content }>
<UserTextJsx acct = { props.data.account.acct } />
shared your post.
</Text>
</NotificationJsx>
);
};
const FavouriteJsx = (props) => {
return (
<NotificationJsx
thumbnail = { props.data.status.media_attachments[0].url }
thumbnailPressCallback = {
navigatePostFactory(props.navigation, props.data.status.id)
}>
<Image
style = { styles.notif.inlineIcon }
source = { require("assets/eva-icons/post-actions/heart-active.png") } />
<Text style = { styles.notif.content }>
<UserTextJsx acct = { props.data.account.acct } />
liked your post.
</Text>
</NotificationJsx>
);
};
const StatusJsx = (props) => {
return (
<NotificationJsx
thumbnail = { props.data.status.media_attachments[0].url }
thumbnailPressCallback = {
navigatePostFactory(props.navigation, props.data.status.id)
}>
<Text style = { styles.notif.content }>
<UserTextJsx acct = { props.data.account.acct } />
just posted.
</Text>
</NotificationJsx>
);
};
const NotificationsJsx = ({navigation}) => {
const [state, setState] = useState({
loaded: false,
});
useEffect(() => {
const read = JSON.stringify({
unread: false,
memory: [
{ id: 1 },
{ id: 2 },
{ id: 3 },
]
});
AsyncStorage.mergeItem("@user_notifications", read)
.then(() => {
setState({...state,
notifications: TEST_NOTIFICATIONS,
loaded: true
})
});
}, []);
return (
<ScreenWithBackBarJsx
navigation = { navigation }>
{ state.loaded ?
<View>
{
state.notifications.map(notif =>
renderNotification(notif, navigation)
)
}
</View>
: <></>
}
</ScreenWithBackBarJsx>
);
}
const SCREEN_WIDTH = Dimensions.get("window").width;
const styles = {
notif: {
container: {
flexDirection: "row",
alignItems: "center",
paddingLeft: 20,
marginTop: 10,
marginBottom: 10,
},
circularThumbnail: { borderRadius: SCREEN_WIDTH / 16 },
thumbnailContainer: {
marginRight: 10,
},
thumbnail: {
width: SCREEN_WIDTH / 8,
height: SCREEN_WIDTH / 8,
},
contentContainer: {
flexShrink: 1,
flexDirection: "row",
alignItems: "center",
},
inlineIcon: {
width: 20,
height: 20,
marginRight: 10,
},
status: { fontStyle: "italic" },
buttonContainer: {
marginLeft: "auto",
marginRight: 10,
},
button: {
borderWidth: 1,
borderColor: "#888",
borderRadius: 10,
padding: 10,
},
},
bold: { fontWeight: "bold" },
};
export default NotificationsJsx; export default NotificationsJsx;

View File

@ -10,6 +10,8 @@ import {
Dimensions, Dimensions,
} from "react-native"; } from "react-native";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { withoutHTML } from "src/interface/rendering"; import { withoutHTML } from "src/interface/rendering";
import { ScreenWithBackBarJsx } from "src/components/navigation/navigators"; import { ScreenWithBackBarJsx } from "src/components/navigation/navigators";
@ -203,7 +205,17 @@ const SettingsJsx = (props) => {
<TouchableOpacity style = { styles.largeButton }> <TouchableOpacity style = { styles.largeButton }>
<Text> Save Profile </Text> <Text> Save Profile </Text>
</TouchableOpacity> </TouchableOpacity>
<TouchableOpacity style = { styles.largeButton }> <TouchableOpacity
style = { styles.largeButton }
onPress = {
() => {
AsyncStorage.multiRemove(
["@user_profile", "@user_notifications"]
).then(() => {
props.navigation.navigate("Authenticate");
});
}
}>
<Text style = { styles.textWarning }> Log out </Text> <Text style = { styles.textWarning }> Log out </Text>
</TouchableOpacity> </TouchableOpacity>
</View> </View>

View File

@ -3,14 +3,20 @@ import React from "react";
import { ScreenWithFullNavigationJsx } from "src/components/navigation/navigators"; import { ScreenWithFullNavigationJsx } from "src/components/navigation/navigators";
import { PostByIdJsx } from "src/components/posts/post"; import { PostByIdJsx } from "src/components/posts/post";
const ViewPostJsx = (props) => { const ViewPostJsx = ({navigation}) => {
const id = navigation.getParam("id", undefined);
if (id == undefined) {
throw Error("ID not specified when navigating to ViewPost!");
}
return ( return (
<ScreenWithFullNavigationJsx <ScreenWithFullNavigationJsx
active = { props.navigation.getParam("originTab", "Timeline") } active = { navigation.getParam("originTab", "Timeline") }
navigation = { props.navigation }> navigation = { navigation }>
<PostByIdJsx <PostByIdJsx
navigation = { props.navigation } navigation = { navigation }
id = { props.id } /> id = { id } />
</ScreenWithFullNavigationJsx> </ScreenWithFullNavigationJsx>
); );
} }

View File

@ -1,7 +1,7 @@
import React from "react"; import React from "react";
import { View, Dimensions, Image } from "react-native"; import { View, Dimensions, Image } from "react-native";
import GridPostJsx from "src/components/posts/grid-post" import GridPostJsx from "src/components/posts/grid-post";
function partition(arr, size) { function partition(arr, size) {
let newArray = []; let newArray = [];

View File

@ -1,5 +1,5 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect } from "react";
import { View, TouchableWithoutFeedback, Text } from "react-native"; import { View, TouchableOpacity, Text } from "react-native";
import GridViewJsx from "src/components/posts/grid-view"; import GridViewJsx from "src/components/posts/grid-view";
@ -60,16 +60,16 @@ const PagedGridJSX = (props) => {
} }
} /> } />
<View style = { styles.buttonContainer }> <View style = { styles.buttonContainer }>
<TouchableWithoutFeedback <TouchableOpacity
onPress = { () => { onPress = { () => {
// TODO: actually get more posts :) // TODO: actually get more posts :)
let morePosts = state.posts.concat(TEST_POSTS); let morePosts = state.posts.concat(TEST_POSTS);
setState({ posts: morePosts, loaded: true }); setState({...state, posts: morePosts});
} }> } }>
<View style = { styles.buttonMore }> <View style = { styles.buttonMore }>
<Text>Show more?</Text> <Text>Show more?</Text>
</View> </View>
</TouchableWithoutFeedback> </TouchableOpacity>
</View> </View>
</View> </View>
); );
@ -82,7 +82,8 @@ const styles = {
alignItems: "center" alignItems: "center"
}, },
buttonMore: { buttonMore: {
border: "2px solid black", borderWidth: 1,
borderColor: "#888",
borderRadius: 5, borderRadius: 5,
padding: 10, padding: 10,
margin: 20 margin: 20

30
src/requests.js Normal file
View File

@ -0,0 +1,30 @@
import AsyncStorage from "@react-native-async-storage/async-storage";
const TEST_NOTIFICATIONS = [{ id: 1 }, { id: 2 }];
const TEST_NEW_NOTIFICATIONS_1 = [{ id: 1 }, { id: 2 }];
const TEST_NEW_NOTIFICATIONS_2 = [{ id: 1 }, { id: 2 }, { id: 3 }];
export async function checkUnreadNotifications() {
// If the check has already been made since the last time notifications.js
// has been opened
const notifications = JSON.parse(await AsyncStorage.getItem("@user_notifications"));
if (notifications.unread) {
return true;
} else {
// Some promise to get new notifications
const newNotifs = await Promise.resolve(TEST_NEW_NOTIFICATIONS_2);
const isUnread = JSON.stringify(newNotifs) != JSON.stringify(notifications.memory);
// Update stored notifications
await AsyncStorage.setItem(
"@user_notifications",
JSON.stringify({...notifications,
unread: isUnread,
})
);
return isUnread;
}
}