Skip to content

Commit

Permalink
feat: repost (#90)
Browse files Browse the repository at this point in the history
* chore: change tweet time display
* feat: navigate from tweet to profile
* feat: repost
* feat: display repost
* chore: common configurations of vscode
* chore: styling the feed
* feat: adding a delay to wait for the tx to be mined

---------

Signed-off-by: Iuri Pereira <[email protected]>
  • Loading branch information
iuricmp authored Jun 13, 2024
1 parent 806a520 commit 3d5faab
Show file tree
Hide file tree
Showing 17 changed files with 381 additions and 80 deletions.
12 changes: 12 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Editor configuration, see http://editorconfig.org
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
max_line_length = off
6 changes: 3 additions & 3 deletions mobile/app/home/feed.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ActivityIndicator, FlatList, Platform, StyleSheet, View, Alert as RNAlert } from "react-native";
import { ActivityIndicator, FlatList, Platform, StyleSheet, View, Alert as RNAlert, SafeAreaView } from "react-native";
import React, { useEffect, useRef, useState } from "react";
import { useNavigation, useRouter } from "expo-router";
import { useFeed } from "@gno/hooks/use-feed";
Expand Down Expand Up @@ -82,12 +82,12 @@ export default function Page() {
}

return (
<Layout.Container>
<SafeAreaView style={{ flex: 1, paddingTop: Platform.select({ ios: 0, default: 20 }) }}>
<View style={styles.container}>
<FeedView totalPosts={totalPosts} onPress={onPress} address={user.address} type="userFeed" />
<Button.TouchableOpacity title="Post" onPress={onPressPost} style={styles.post} variant="primary" />
</View>
</Layout.Container>
</SafeAreaView>
);
}

Expand Down
2 changes: 1 addition & 1 deletion mobile/app/post/[post_id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ function Page() {
<Layout.Container>
<Layout.Header title="Post" iconType="back" />
<Layout.Body>
<Tweet post={post} highlighted />
<Tweet post={post} showFooter={false} />

<View style={{ flex: 1 }}>
{loading ? (
Expand Down
15 changes: 5 additions & 10 deletions mobile/app/post/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { KeyInfo } from "@buf/gnolang_gnonative.bufbuild_es/gnonativetypes_pb";
import Alert from "@gno/components/alert";
import Button from "@gno/components/button";
import Layout from "@gno/components/layout";
import Spacer from "@gno/components/spacer";
Expand Down Expand Up @@ -43,6 +41,11 @@ export default function Search() {
console.log("response ono post screen: ", response);
}
setPostContent("");

// delay 3s to wait for the transaction to be mined
// TODO: replace with a better way to wait for the transaction to be mined
await new Promise((resolve) => setTimeout(resolve, 3000));

router.push("home");
} catch (error) {
console.error("on post screen", error);
Expand Down Expand Up @@ -82,11 +85,3 @@ export default function Search() {
</>
);
}

const styles = StyleSheet.create({
centerScreen: {
height: "100%",
justifyContent: "center",
alignItems: "center",
},
});
74 changes: 74 additions & 0 deletions mobile/app/repost/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import Button from "@gno/components/button";
import { Tweet } from "@gno/components/feed/tweet";
import Layout from "@gno/components/layout";
import TextInput from "@gno/components/textinput";
import { selectPostToReply, useAppSelector } from "@gno/redux";
import { useGnoNativeContext } from "@gnolang/gnonative";
import { useRouter } from "expo-router";
import { useState } from "react";
import { Alert, View } from "react-native";

export default function Page() {
const post = useAppSelector(selectPostToReply);
const gno = useGnoNativeContext();
const router = useRouter();

const [replyContent, setReplyContent] = useState("");
const [loading, setLoading] = useState<boolean>(false);

const onPressRepost = async () => {
if (!post) return;

setLoading(true);
try {
const gasFee = "1000000ugnot";
const gasWanted = 10000000;

const args: Array<string> = [post.user.address, String(post.id), replyContent];
for await (const response of await gno.call("gno.land/r/berty/social", "RepostThread", args, gasFee, gasWanted)) {
console.log("response ono post screen: ", response);
}

// delay 3s to wait for the transaction to be mined
// TODO: replace with a better way to wait for the transaction to be mined
await new Promise((resolve) => setTimeout(resolve, 6000));

router.push("home");
} catch (error) {
console.error("on post screen", error);
Alert.alert("Failed to repost", "" + error);
} finally {
setLoading(false);
}
};

return (
<Layout.Container>
<Layout.Header title="Repost" />
<View style={{ flex: 1, flexDirection: "row", alignItems: "center", padding: 16 }}>
<View style={{ flex: 4 }} />
<Button.TouchableOpacity
loading={loading}
style={{ flex: 1 }}
variant="primary"
title="Repost"
onPress={onPressRepost}
></Button.TouchableOpacity>
</View>
<Layout.Body>
<TextInput
placeholder="Add a comment"
onChangeText={setReplyContent}
value={replyContent}
autoCapitalize={"none"}
textAlign="left"
multiline
numberOfLines={3}
style={{ height: 80 }}
/>

<Tweet post={post} showFooter={false} />
</Layout.Body>
</Layout.Container>
);
}
8 changes: 4 additions & 4 deletions mobile/components/change-network/network-list/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { NetworkMetainfo } from '@gno/native_modules/types';
import NetworkListItem from '../network-list-item';
import styled from 'styled-components/native';
import Text from 'components/text';
import NetworkListItem from "../network-list-item";
import styled from "styled-components/native";
import Text from "components/text";
import { NetworkMetainfo } from "@gnolang/gnonative/build/hooks/types";

interface Props {
currentChainId: string | undefined;
Expand Down
23 changes: 23 additions & 0 deletions mobile/components/feed/like-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { StyleProp, TextStyle, TouchableOpacity } from "react-native";
import { colors } from "@gno/styles/colors";
import { MaterialCommunityIcons } from "@expo/vector-icons";
import Text from "../text";

interface Props {
style?: StyleProp<TextStyle> | undefined;
onPressRepost?: () => void;
}

function LikeButton({ style, onPressRepost }: Props) {
return (
<TouchableOpacity
onPress={onPressRepost}
style={[style, { flexDirection: "row", paddingHorizontal: 12, alignItems: "center" }]}
>
<MaterialCommunityIcons name="heart-outline" size={16} color={colors.text.secondary} />
<Text.Caption1 style={{ color: colors.text.secondary }}> Enjoy</Text.Caption1>
</TouchableOpacity>
);
}

export default LikeButton;
23 changes: 23 additions & 0 deletions mobile/components/feed/repost-button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { StyleProp, TextStyle, TouchableOpacity } from "react-native";
import { colors } from "@gno/styles/colors";
import { MaterialCommunityIcons } from "@expo/vector-icons";
import Text from "../text";

interface Props {
style?: StyleProp<TextStyle> | undefined;
onPressRepost?: () => void;
}

function RepostButton({ style, onPressRepost }: Props) {
return (
<TouchableOpacity
onPress={onPressRepost}
style={[style, { flexDirection: "row", paddingHorizontal: 12, alignItems: "center" }]}
>
<MaterialCommunityIcons name="arrow-u-left-top" size={16} color={colors.text.secondary} />
<Text.Caption1 style={{ color: colors.text.secondary }}>Repost</Text.Caption1>
</TouchableOpacity>
);
}

export default RepostButton;
21 changes: 21 additions & 0 deletions mobile/components/feed/repost-label.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { colors } from "@gno/styles/colors";
import Text from "../text";
import { Post } from "@gno/types";

function RepostLabel({ post }: { post: Post }) {
if (!post.parent_id || post.parent_id === 0) return null;

return (
<Text.Caption1
style={{
color: colors.text.secondary,
textAlign: "left",
paddingBottom: 8,
}}
>
reposted from @{post.parent_post?.user.name}
</Text.Caption1>
);
}

export default RepostLabel;
13 changes: 13 additions & 0 deletions mobile/components/feed/timestamp-label.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { formatDistanceToNow } from "date-fns";
import { colors } from "@gno/styles/colors";
import Text from "../text";

function TimeStampLabel({ timestamp }: { timestamp: string }) {
return (
<Text.Caption1 style={{ color: colors.text.secondary }}>
{formatDistanceToNow(new Date(timestamp), { addSuffix: false })}
</Text.Caption1>
);
}

export default TimeStampLabel;
23 changes: 0 additions & 23 deletions mobile/components/feed/timestamp.label.tsx

This file was deleted.

96 changes: 96 additions & 0 deletions mobile/components/feed/tweet-repost.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React from "react";
import { Image, Pressable, StyleSheet, View } from "react-native";
import { Post } from "../../types";
import Text from "@gno/components/text";
import RepliesLabel from "./replies-label";
import TimeStampLabel from "./timestamp-label";
import RepostButton from "./repost-button";
import { setPostToReply, useAppDispatch } from "@gno/redux";
import { useRouter } from "expo-router";
import RepostLabel from "./repost-label";

interface FeedProps {
post?: Post;
onPress?: (post: Post) => void;
showFooter?: boolean;
}

const func = () => {};

export function TweetRepost({ post, onPress = func, showFooter = true }: FeedProps) {
const router = useRouter();
const dispatch = useAppDispatch();
const isRepost = Boolean(post && post.parent_id > 0);

const onPressRepost = async (item: Post) => {
await dispatch(setPostToReply({ post: item }));
router.navigate({ pathname: "/repost" });
};

const onPressName = async () => {
router.navigate({ pathname: "account", params: { accountName: post?.user.name } });
};

if (!post) {
return null;
}

return (
<Pressable onPress={() => onPress(post)} style={styles.container}>
<RepostLabel post={post} />
<View style={styles.body}>
<View style={styles.content}>
<View style={{ flexDirection: "row", alignItems: "center" }}>
<Image source={{ uri: post.user.image }} style={styles.image} />
<Pressable style={{ flexDirection: "row", alignItems: "center", paddingLeft: 8 }} onPress={onPressName}>
<Text.Body style={[{ fontWeight: "bold", fontSize: 16, paddingRight: 8 }]}>@{post.user.name}</Text.Body>
<TimeStampLabel timestamp={post.date} />
</Pressable>
</View>

<Text.Body selectable>{post.post}</Text.Body>
</View>
</View>
{showFooter ? (
<View style={[styles.footer]}>
{/* <LikeButton style={styles.reply} onPressRepost={() => onPressRepost(post)} /> */}
<RepostButton style={styles.reply} onPressRepost={() => onPressRepost(post)} />
<RepliesLabel replyCount={post.n_replies} style={styles.reply} />
</View>
) : null}
</Pressable>
);
}

const styles = StyleSheet.create({
container: {
paddingTop: 8,
borderBottomColor: "#ccc",
borderBottomWidth: 1,
},
body: {
flexDirection: "row",
gap: 4,
},
image: {
width: 24,
height: 24,
borderRadius: 24,
},
content: {
gap: 4,
flex: 1,
},
footer: {
flexDirection: "row",
paddingTop: 12,
paddingLeft: 64,
gap: 16,
},
footerHighlighted: {
marginTop: 16,
borderTopColor: "#ccc",
borderTopWidth: 1,
},
reply: { paddingLeft: 16 },
});
Loading

0 comments on commit 3d5faab

Please sign in to comment.