commit
341fc61116
Binary file not shown.
After Width: | Height: | Size: 9.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
|
@ -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",
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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");
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -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" },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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 }
|
||||||
|
</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;
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 = [];
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue