From 314de081ded3c3c7127fa78ee619e03350b7ca0d Mon Sep 17 00:00:00 2001 From: natjms Date: Thu, 15 Apr 2021 14:43:45 -0300 Subject: [PATCH] Add new page direct.js and conversation.js --- src/App.js | 4 + src/components/navigation/back-bar.js | 35 ++- src/components/navigation/navigators.js | 14 +- src/components/pages/direct.js | 195 +++++++++++++ src/components/pages/direct/conversation.js | 294 ++++++++++++++++++++ 5 files changed, 528 insertions(+), 14 deletions(-) create mode 100644 src/components/pages/direct.js create mode 100644 src/components/pages/direct/conversation.js diff --git a/src/App.js b/src/App.js index 035e89e..80ccf0e 100644 --- a/src/App.js +++ b/src/App.js @@ -15,6 +15,8 @@ import ProfileJsx, { ViewProfileJsx } from "src/components/pages/profile"; import DiscoverJsx from 'src/components/pages/discover'; import SearchJsx from 'src/components/pages/discover/search'; import ViewHashtagJsx from 'src/components/pages/discover/view-hashtag'; +import DirectJsx from "src/components/pages/direct"; +import ConversationJsx from "src/components/pages/direct/conversation"; import NotificationsJsx from 'src/components/pages/profile/notifications'; import UserListJsx from "src/components/pages/user-list.js"; import SettingsJsx from "src/components/pages/profile/settings.js"; @@ -23,6 +25,8 @@ const Stack = createStackNavigator({ Authenticate: { screen: AuthenticateJsx }, Feed: { screen: FeedJsx, }, Discover: { screen: DiscoverJsx }, + Direct: { screen: DirectJsx }, + Conversation: { screen: ConversationJsx }, Notifications: { screen: NotificationsJsx }, Profile: { screen: ProfileJsx, }, Settings: { screen: SettingsJsx }, diff --git a/src/components/navigation/back-bar.js b/src/components/navigation/back-bar.js index 3b83cbb..556ebd6 100644 --- a/src/components/navigation/back-bar.js +++ b/src/components/navigation/back-bar.js @@ -1,33 +1,44 @@ import React from "react"; import { Image } from "react-native"; -import { TouchableWithoutFeedback, View } from "react-native"; +import { TouchableOpacity, View } from "react-native"; const BackBarJsx = (props) => { const backIcon = require("assets/eva-icons/back.png"); return ( - props.navigation.goBack() }> + props.navigation.goBack() } + style = { styles.button }> - + + + { props.children } + ); }; const styles = { nav: { - padding: 15, - borderBottom: "2px solid #CCC", - backgroundColor: "white" + backgroundColor: "white", + + flexDirection: "row", + alignItems: "center", + }, + rest: { + flexGrow: 1, + }, + chevron: { + width: 30, + height: 30, }, button: { - width: 30, - height: 30 - } + padding: 10, + }, } -export default BackBarJsx; \ No newline at end of file +export default BackBarJsx; diff --git a/src/components/navigation/navigators.js b/src/components/navigation/navigators.js index d3776c1..6e43850 100644 --- a/src/components/navigation/navigators.js +++ b/src/components/navigation/navigators.js @@ -36,7 +36,12 @@ export const ScreenWithBackBarJsx = (props) => { return ( - + + { props.renderBackBar != undefined + ? props.renderBackBar() + : <> + } + { props.children } @@ -49,7 +54,12 @@ export const ScreenWithFullNavigationJsx = (props) => { return ( - + + { props.renderBackBar != undefined + ? props.renderBackBar() + : <> + } + { props.children } diff --git a/src/components/pages/direct.js b/src/components/pages/direct.js new file mode 100644 index 0000000..60a5488 --- /dev/null +++ b/src/components/pages/direct.js @@ -0,0 +1,195 @@ +import React, { useState, useEffect } from "react"; +import { + View, + Text, + TouchableOpacity, + Image, + FlatList, + TextInput, + Dimensions, +} from "react-native"; + +import { Ionicons } from "@expo/vector-icons"; + +import { ScreenWithTrayJsx } from "src/components/navigation/navigators"; +import ModerateMenuJsx from "src/components/moderate-menu.js"; + +const TEST_IMAGE_1 = "https://cache.desktopnexus.com/thumbseg/2255/2255124-bigthumbnail.jpg"; +const TEST_IMAGE_2 = "https://natureproducts.net/Forest_Products/Cutflowers/Musella_cut.jpg"; +const TEST_ACCOUNT_1 = { acct: "njms", display_name: "Nat🔆", avatar: TEST_IMAGE_1 }; +const TEST_ACCOUNT_2 = { acct: "someone", display_name: "Some person", avatar: TEST_IMAGE_2 }; + +const TEST_STATUS = { + id: 1, + account: TEST_ACCOUNT_1, + content: "This is a direct message", +}; + +function filterConversations(convs, query) { + return convs.filter(conv => { + const accts = conv.accounts.map(account => account.acct).join(); + const names = conv.accounts.map(account => account.display_name).join(); + + return accts.includes(query) || names.includes(query) + }); +} + +const DirectJsx = ({ navigation }) => { + const [state, setState] = useState({ + loaded: false, + query: "" + }); + + useEffect(() => { + setState({...state, + loaded: true, + conversations: [ + { + id: 1, + unread: true, + accounts: [TEST_ACCOUNT_1], + last_status: TEST_STATUS, + }, + { + id: 2, + unread: false, + accounts: [TEST_ACCOUNT_1, TEST_ACCOUNT_2], + last_status: TEST_STATUS, + } + ], + }); + }, []); + + const onPressConversationFactory = (conv) => { + return () => { + navigation.navigate("Conversation", { + conversation: conv, + }); + } + }; + + const renderConversation = ({ item }) => { + const boldIfUnread = item.unread ? styles.bold : {}; + + return + + + + + + + { item.accounts.map(account => account.acct).join(", ") } + + + { + // Prefix message with acct + [ + item.accounts.length > 1 ? + item.last_status.account.acct + ": " + : "", + item.last_status.content, + ].join("") + } + + + + + + + + }; + + return ( + + + { + setState({...state, + query: value, + }); + } + }/> + + + + + { state.loaded ? + conv.id }/> + : <> + } + + ); +}; + +const SCREEN_WIDTH = Dimensions.get("window").width; +const styles = { + row: { + flexDirection: "row", + alignItems: "center", + }, + form: { + container: { + marginLeft: 20, + marginTop: 20, + marginBottom: 20, + }, + searchBar: { + padding: 10, + width: SCREEN_WIDTH * 3 / 4, + borderWidth: 1, + borderRadius: 5, + borderColor: "#888", + }, + compose: { + marginLeft: "auto", + marginRight: "auto", + }, + }, + conv: { + container: { + paddingBottom: 20, + paddingLeft: 10, + paddingRight: 20, + }, + containerButton: { flexGrow: 1 }, + avatar: { + image: { + width: 40, + height: 40, + borderRadius: 20, + } + }, + body: { + marginLeft: 10, + }, + context: { + marginLeft: "auto", + } + }, + menu: { + trigger: { + width: 20, + height: 20, + }, + }, + bold: { fontWeight: "bold" }, +}; + +export { DirectJsx as default }; diff --git a/src/components/pages/direct/conversation.js b/src/components/pages/direct/conversation.js new file mode 100644 index 0000000..909931e --- /dev/null +++ b/src/components/pages/direct/conversation.js @@ -0,0 +1,294 @@ +import React, { useState, useEffect } from "react"; +import { + View, + Text, + Image, + TextInput, + FlatList, + ScrollView, + Dimensions, + TouchableOpacity, +} from "react-native"; + +import AsyncStorage from "@react-native-async-storage/async-storage"; + +import { Ionicons } from "@expo/vector-icons"; + +import { + Menu, + MenuOptions, + MenuOption, + MenuTrigger, + renderers +} from "react-native-popup-menu"; + +const { SlideInMenu } = renderers; + +import BackBarJsx from "src/components/navigation/back-bar"; +import { ContextJsx } from "src/components/navigation/navigators"; + +import { timeToAge } from "src/interface/rendering"; + +const TEST_IMAGE_1 = "https://cache.desktopnexus.com/thumbseg/2255/2255124-bigthumbnail.jpg"; +const TEST_IMAGE_2 = "https://natureproducts.net/Forest_Products/Cutflowers/Musella_cut.jpg"; +const TEST_ACCOUNT_1 = { acct: "someone", display_name: "Someone", avatar: TEST_IMAGE_1 }; +const TEST_ACCOUNT_2 = { acct: "someone_else", display_name: "Another person", avatar: TEST_IMAGE_2 }; + +const TEST_STATUS = { + account: TEST_ACCOUNT_1, + content: "This is a direct message", + created_at: 1596745156000, +}; + +const TEST_MESSAGES = [ + { ...TEST_STATUS, id: 1 }, + { ...TEST_STATUS, id: 2, account: TEST_ACCOUNT_2 }, + { ...TEST_STATUS, id: 3 }, + { ...TEST_STATUS, id: 4, account: { acct: "njms" } }, + { ...TEST_STATUS, id: 5 }, +]; + +const ConversationJsx = ({ navigation }) => { + const conversation = navigation.getParam("conversation", {}); + const [state, setState] = useState({ + loaded: false, + newMessage: "", + }); + + useEffect(() => { + // Get the context of last_status, then profile from AsyncStorage + AsyncStorage.getItem("@user_profile").then((profile) => { + setState({...state, + loaded: true, + profile: JSON.parse(profile), + messages: TEST_MESSAGES, + }); + }); + }, []); + + const accountListOptionsStyles = { + optionWrapper: { // The wrapper around a single option + flexDirection: "row", + alignItems: "center", + + paddingLeft: SCREEN_WIDTH / 15, + paddingTop: SCREEN_WIDTH / 30, + paddingBottom: SCREEN_WIDTH / 30 + }, + optionsWrapper: { // The wrapper around all options + marginTop: SCREEN_WIDTH / 20, + marginBottom: SCREEN_WIDTH / 20, + }, + optionsContainer: { // The Animated.View + borderTopLeftRadius: 10, + borderTopRightRadius: 10 + } + }; + + const renderBackBar = () => ( + + + + + + + { + conversation.accounts + .slice(0, 3) // Take first 3 accounts only + .map(account => account.acct) + .join(", ") + } + + + + + { + conversation.accounts.map(account => + + + + + @{ account.acct } + + + { account.display_name } + + + + ) + } + + + + ); + + const renderMessage = ({ item }) => { + const yours = state.profile.acct == item.account.acct; + return <> + { !yours + ? + { item.account.acct } + + : <> + } + + { !yours + ? + : <> + } + + + + { item.content + "\n" } + + + { timeToAge(item.created_at) } + + + + + ; + }; + + return ( + + + + { renderBackBar() } + + + { state.loaded + ? item.id }/> + : <> + } + + + { + setState({...state, + newMessage: value, + }); + } + }/> + + + + + + + ); +}; + +const SCREEN_WIDTH = Dimensions.get("window").width; +const styles = { + row: { + flexDirection: "row", + alignItems: "center", + }, + backBar: { + accountList: { + avatar: { + width: 40, + height: 40, + borderRadius: 20, + marginRight: 10, + }, + }, + container: { + marginLeft: 20, + paddingTop: 10, + paddingBottom: 10, + }, + avatar: { + width: 40, + height: 40, + borderRadius: 20, + marginRight: 10, + }, + }, + message: { + container: { + paddingTop: 5, + paddingBottom: 10, + paddingLeft: 10, + paddingRight: 10, + flexDirection: "row", + }, + acct: { + paddingLeft: 60, + fontSize: 12, + color: "#888", + }, + avatar: { + width: 40, + height: 40, + borderRadius: 20, + marginRight: 10, + }, + bubble: { + width: SCREEN_WIDTH * 3/4, + borderWidth: 1, + borderColor: "#888", + borderRadius: 10, + padding: 10, + }, + yourBubble: { + backgroundColor: "#CCC", + marginLeft: "auto", + }, + yourText: { + //color: "white", + textAlign: "right", + }, + age: { + fontSize: 10, + color: "#888", + }, + }, + send: { + container: { + marginTop: 10, + marginBottom: 10, + marginLeft: 10, + }, + input: { + padding: 10, + borderWidth: 1, + borderColor: "#888", + borderRadius: 5, + flexGrow: 1, + }, + button: { + marginLeft: 10, + marginRight: 10, + } + }, + bold: { fontWeight: "bold", }, +}; + +export { ConversationJsx as default };