Skip to content

Commit

Permalink
Feat/react-to-post (#98)
Browse files Browse the repository at this point in the history
* feat: add reaction
* chore: bump version

---------

Signed-off-by: Iuri Pereira <[email protected]>
  • Loading branch information
iuricmp authored Jun 19, 2024
1 parent 1ce7cc1 commit 5c6b8b1
Show file tree
Hide file tree
Showing 16 changed files with 234 additions and 21 deletions.
4 changes: 2 additions & 2 deletions mobile/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"name": "dsocial",
"slug": "dsocial",
"platforms": ["ios", "android"],
"version": "1.0.4",
"version": "1.0.5",
"orientation": "portrait",
"scheme": "tech.berty.dsocial",
"icon": "./assets/images/icon.png",
Expand Down Expand Up @@ -35,7 +35,7 @@
"backgroundColor": "#ffffff"
},
"package": "tech.berty.dsocial.android",
"versionCode": 7
"versionCode": 8
},
"web": {
"favicon": "./assets/images/favicon.png"
Expand Down
14 changes: 14 additions & 0 deletions mobile/app/[account]/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,19 @@ export default function Page() {
fetchData();
};

const onGnod = async (post: Post) => {
console.log("gnodding post: ", post);
setLoading("Gnoding...");
try {
await feed.onGnod(post);
await fetchData();
} catch (error) {
console.error("Error while adding reaction: " + error);
} finally {
setLoading(undefined);
}
};

const onPressPost = async (item: Post) => {
await dispatch(setPostToReply({ post: item }));
router.navigate({ pathname: "/post/[post_id]", params: { post_id: item.id, address: item.user.address } });
Expand All @@ -105,6 +118,7 @@ export default function Page() {
currentUser={currentUser}
following={following}
followers={followers}
onGnod={onGnod}
onPressPost={onPressPost}
onPressFollowing={onPressFollowing}
onPressFollowers={onPressFollowers}
Expand Down
25 changes: 21 additions & 4 deletions mobile/app/home/feed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { Post } from "@gno/types";
import { selectAccount, setPostToReply, useAppDispatch, useAppSelector } from "@gno/redux";
import Alert from "@gno/components/alert";
import { FeedView } from "@gno/components/view";
import { useGnoNativeContext } from "@gnolang/gnonative";
import base64 from "base-64";

export default function Page() {
const [totalPosts, setTotalPosts] = useState(0);
Expand All @@ -17,6 +19,7 @@ export default function Page() {

const router = useRouter();
const feed = useFeed();
const gno = useGnoNativeContext();
const navigation = useNavigation();
const ref = useRef<FlatList>(null);
const dispatch = useAppDispatch();
Expand Down Expand Up @@ -55,11 +58,25 @@ export default function Page() {
router.navigate({ pathname: "/post/[post_id]", params: { post_id: item.id, address: item.user.address } });
};

const onGnod = async (post: Post) => {
setIsLoading(true);

try {
await feed.onGnod(post);
} catch (error) {
RNAlert.alert("Error", "Error while adding reaction: " + error);
} finally {
setIsLoading(false);
}
};

if (isLoading)
return (
<View style={styles.footer}>
<ActivityIndicator size="large" color="#0000ff" />
</View>
<Layout.Container>
<Layout.Body>
<ActivityIndicator size="large" color="#0000ff" />
</Layout.Body>
</Layout.Container>
);

if (error)
Expand All @@ -84,7 +101,7 @@ export default function Page() {
return (
<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" />
<FeedView totalPosts={totalPosts} onPress={onPress} onGnod={onGnod} address={user.address} type="userFeed" />
<Button.TouchableOpacity title="Post" onPress={onPressPost} style={styles.post} variant="primary" />
</View>
</SafeAreaView>
Expand Down
17 changes: 15 additions & 2 deletions mobile/app/post/[post_id].tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Spacer from "@gno/components/spacer";
import Alert from "@gno/components/alert";
import { useGnoNativeContext } from "@gnolang/gnonative";
import { Tweet } from "@gno/components/feed/tweet";
import { FlatList, KeyboardAvoidingView, View } from "react-native";
import { FlatList, KeyboardAvoidingView, View, Alert as RNAlert } from "react-native";
import { Post } from "@gno/types";
import { useFeed } from "@gno/hooks/use-feed";

Expand Down Expand Up @@ -77,6 +77,19 @@ function Page() {
// TODO: on press a tweet inside the reply thread
};

const onGnod = async (post: Post) => {
console.log("gnodding post: ", post);
setLoading("Gnoding...");
try {
await feed.onGnod(post);
await fetchData();
} catch (error) {
RNAlert.alert("Error", "Error while adding reaction: " + error);
} finally {
setLoading(undefined);
}
};

if (!post) {
return (
<Layout.Container>
Expand All @@ -103,7 +116,7 @@ function Page() {
data={thread}
keyExtractor={(item) => `${item.id}`}
contentContainerStyle={{ width: "100%", paddingBottom: 20 }}
renderItem={({ item }) => <Tweet post={item} onPress={onPressTweet} />}
renderItem={({ item }) => <Tweet post={item} onPress={onPressTweet} onGnod={onGnod} />}
onEndReachedThreshold={0.1}
/>
)}
Expand Down
23 changes: 23 additions & 0 deletions mobile/components/feed/gnod-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 Text from "../text";
import Icons from "../icons";

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

function GnodButton({ style, onPressRepost }: Props) {
return (
<TouchableOpacity
onPress={onPressRepost}
style={[style, { flexDirection: "row", paddingHorizontal: 12, alignItems: "center" }]}
>
<Icons.Gnod color={colors.text.secondary} style={{ marginRight: 4 }} />
<Text.Caption1 style={{ color: colors.text.secondary }}>Gnod</Text.Caption1>
</TouchableOpacity>
);
}

export default GnodButton;
21 changes: 21 additions & 0 deletions mobile/components/feed/gnod-label.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
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 {
gnodsCount: number;
onPress?: () => void;
style?: StyleProp<TextStyle> | undefined;
}

function GnodLabel({ gnodsCount, style, onPress }: Props) {
return (
<TouchableOpacity onPress={onPress} style={[style, { flexDirection: "row", gap: 8 }]}>
<MaterialCommunityIcons name="message-reply-outline" size={16} color={colors.text.secondary} />
<Text.Caption1 style={{ color: colors.text.secondary }}>{gnodsCount} Gnods</Text.Caption1>
</TouchableOpacity>
);
}

export default GnodLabel;
8 changes: 5 additions & 3 deletions mobile/components/feed/tweet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,18 @@ import { setPostToReply, useAppDispatch } from "@gno/redux";
import { useRouter } from "expo-router";
import RepostLabel from "./repost-label";
import { TweetRepost } from "./tweet-repost";
import GnodLabel from "./gnod-label";

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

const func = () => {};

export function Tweet({ post, onPress = func, showFooter = true }: FeedProps) {
export function Tweet({ post, onPress = func, onGnod = func, showFooter = true }: FeedProps) {
const router = useRouter();
const dispatch = useAppDispatch();
const isRepost = Boolean(post && post.parent_id > 0);
Expand Down Expand Up @@ -55,7 +57,7 @@ export function Tweet({ post, onPress = func, showFooter = true }: FeedProps) {
</View>
{showFooter ? (
<View style={[styles.footer]}>
{/* <LikeButton style={styles.reply} onPressRepost={() => onPressRepost(post)} /> */}
<GnodLabel style={styles.reply} gnodsCount={post.n_gnods} onPress={() => onGnod(post)} />
<RepostButton style={styles.reply} onPressRepost={() => onPressRepost(post)} />
<RepliesLabel replyCount={post.n_replies} style={styles.reply} />
</View>
Expand Down Expand Up @@ -86,7 +88,7 @@ const styles = StyleSheet.create({
footer: {
flexDirection: "row",
paddingTop: 12,
paddingLeft: 64,
paddingLeft: 44,
gap: 16,
},
footerHighlighted: {
Expand Down
35 changes: 35 additions & 0 deletions mobile/components/icons/Gnod.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import * as React from "react";
import Svg, { Path, SvgProps } from "react-native-svg";

function Gnod(props: SvgProps) {
return (
<Svg width={props.width || 16} height={props.height || 18} viewBox="0 0 35.973949 45.630001" {...props}>
<Path
d="M46.935 319.041c-.86-1.062-1.3-6.509-.892-11.039.324-3.59 1.522-9.358 2.176-10.47.41-.699.78-.891 4.564-2.372 3.675-1.439 4.18-1.58 4.7-1.32 1.173.583 1.215 1.553.174 3.958l-.97 2.241 2.838 2.576c3.133 2.842 5.556 5.792 6.442 7.842.474 1.057.477 1.456-.2 1.73-.556.282-1.051.301-1.745.066-2.33-.789-6.84-.007-10.063 1.745-2.137 1.161-4.026 2.775-4.7 4.016-.601 1.103-1.825 1.644-2.324 1.027zm3.724-3.783c1.232-1.05 1.809-1.619 4.9-2.83 4.036-1.579 5.843-1.619 8.45-1.038.814.182 1.516.243 1.563.138.42-.963-4.22-6.518-7.989-9.564-1.029-.832-1.88-1.535-1.89-1.562-.01-.027.485-1.222 1.1-2.656.976-2.27 1.062-2.657.665-2.996-.427-.364-.71-.29-4.362 1.14-3.362 1.316-3.954 1.617-4.248 2.16-.589 1.088-1.832 7.446-2.079 10.633-.314 4.049.108 9.297.787 9.807.159.12.534-.234.97-.912.39-.61 1.35-1.653 2.133-2.32z"
transform="translate(-33.937 -293.734)"
fill="#000"
/>
<Path
d="M59.732 331.183c-3.816-.866-6.94-1.711-7.665-2.073-1.915-.955-3.535-3.55-3.659-5.862-.063-1.187 1.112-3.796 1.838-4.08.434-.17.56-.036.984 1.044.677 1.73 1.078 1.645 2.993-.632 1.398-1.663 1.744-1.934 3.17-2.493 1.426-.558 1.874-.594 4.075-.33 2.937.354 3.363.094 2.685-1.637-.604-1.543-.027-1.789 2.057-.876 2.268.994 3.408 2.56 3.661 5.03.205 1.993-.327 3.36-2.728 7.005-3.848 5.84-3.705 5.746-7.411 4.904zm6.231-4.59c1.415-2.149 2.684-4.212 2.82-4.584.722-1.964.212-4.67-1.138-6.039-.357-.362-1.201-.884-1.874-1.16l-1.224-.5.398 1.017c.448 1.146.218 1.98-.64 2.315-.31.122-1.546.072-2.744-.112-3.524-.538-4.865.058-7.3 3.248-.476.624-1.141 1.243-1.478 1.374-.903.354-1.814-.2-2.096-1.276-.203-.772-.279-.841-.562-.509-.936 1.097-1.17 3.469-.506 5.155.474 1.206 2.305 2.744 3.856 3.24 3.312 1.057 8.677 2.199 9.28 1.975.419-.155 1.514-1.569 3.208-4.143z"
transform="translate(-33.937 -293.734)"
fill="gray"
fillOpacity={1}
stroke="none"
/>
<Path
d="M41.909 317.83c-.637 0-1.149.648-1.149 1.453v6.684h-5.14a1.18 1.18 0 00-1.183 1.182v10.533a1.18 1.18 0 001.182 1.182h6.341a1.18 1.18 0 001.182-1.182v-18.4c0-.804-.597-1.452-1.233-1.452z"
transform="translate(-33.937 -293.734)"
fill="none"
fillOpacity={1}
stroke="gray"
strokeWidth={1}
strokeLinecap="round"
strokeLinejoin="round"
strokeDasharray="none"
strokeOpacity={1}
/>
</Svg>
);
}

export default Gnod;
61 changes: 61 additions & 0 deletions mobile/components/icons/Gnoded.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import * as React from "react";
import Svg, { G, Path, Rect, SvgProps } from "react-native-svg";

function Gnod(props: SvgProps) {
return (
<Svg width={props.width || 16} height={props.height || 18} viewBox="0 0 37.17128 43.839218" {...props}>
<G transform="translate(-21.696 -47.89)">
<Path
d="M35.37 64.797c-.08-1.364 2.738-6.046 5.71-9.489 2.355-2.729 6.691-6.717 7.872-7.24.74-.328 1.153-.269 5.09.733 3.825.974 4.317 1.152 4.59 1.667.611 1.158.08 1.97-2.168 3.318l-2.094 1.256.805 3.747c.889 4.135 1.138 7.945.663 10.127-.23 1.135-.461 1.46-1.17 1.29-.617-.096-1.03-.37-1.457-.964-1.434-2-5.555-3.993-9.193-4.448-2.414-.302-4.89-.092-6.161.523-1.131.546-2.441.273-2.487-.52zm5.232-.903c1.613-.135 2.413-.261 5.63.558 4.2 1.068 5.692 2.09 7.472 4.082.555.62 1.09 1.08 1.189 1.022.903-.537.37-7.755-.916-12.428-.352-1.276-.633-2.343-.626-2.37.007-.029 1.106-.711 2.442-1.517 2.117-1.277 2.412-1.54 2.286-2.048-.134-.544-.407-.649-4.209-1.616-3.498-.89-4.155-.99-4.71-.721-1.112.54-5.829 4.983-7.887 7.428-2.615 3.107-5.332 7.617-5.077 8.428.06.189.57.12 1.32-.177.672-.267 2.06-.555 3.086-.641z"
fill="#000"
/>
<Path
d="M38.69 82.123c-2.595-2.929-4.64-5.436-5.019-6.153-1-1.892-.803-4.945.444-6.895.64-1.002 3.116-2.437 3.872-2.245.452.115.476.298.19 1.422-.458 1.8-.083 1.966 2.801 1.231 2.105-.536 2.544-.555 4.03-.177 1.483.377 1.868.609 3.502 2.107 2.18 1.999 2.678 2.036 3.136.234.409-1.605 1.02-1.469 2.182.488 1.264 2.13 1.277 4.066.044 6.22-.996 1.74-2.226 2.54-6.3 4.102-6.532 2.503-6.361 2.51-8.881-.334zm7.739-.098c2.402-.921 4.636-1.858 4.964-2.08 1.731-1.177 2.894-3.673 2.595-5.57-.08-.504-.46-1.42-.847-2.036l-.703-1.12-.27 1.058c-.303 1.193-.975 1.736-1.868 1.509-.324-.083-1.298-.844-2.165-1.691-2.55-2.492-3.987-2.789-7.825-1.616-.75.23-1.651.344-2.002.255-.94-.239-1.356-1.22-.959-2.258.285-.746.264-.847-.16-.742-1.4.346-2.972 2.137-3.416 3.894-.318 1.256.274 3.573 1.245 4.88 2.075 2.789 5.768 6.844 6.389 7.014.43.118 2.144-.392 5.022-1.497z"
fill="gray"
fillOpacity={1}
stroke="none"
/>
<Path
d="M41.156 83.339c-1.344-1-5.896-6.248-6.56-7.564-.507-1.004-.812-2.076-.87-3.058-.037-.613.014-.992.202-1.51.464-1.275 1.425-2.482 2.466-3.097.368-.217.92-.424 1.046-.392.103.026.081.223-.073.645-.32.881-.209 1.608.318 2.057.518.443 1.226.47 2.541.102 1.9-.534 2.552-.66 3.499-.681.526-.012 1.438.182 1.927.41.703.327 1.333.796 2.334 1.737 1.616 1.52 2.175 1.893 2.782 1.86.413-.024.762-.246 1.052-.673.125-.182.179-.33.387-1.061l.241-.85.525.875c.89 1.485 1.127 2.266 1.013 3.348-.052.497-.367 1.561-.6 2.031-.474.95-1.197 1.836-1.909 2.335-.252.176-.873.46-2.287 1.044-3.558 1.47-6.474 2.49-7.409 2.595-.35.039-.374.033-.624-.154z"
fill="gray"
fillOpacity={1}
stroke="gray"
strokeWidth={0.123433}
strokeLinecap="round"
strokeLinejoin="round"
strokeOpacity={1}
/>
<Rect
width={8.7040815}
height={12.897045}
x={22.310823}
y={78.216766}
ry={1.1818035}
fill="gray"
fillOpacity={1}
stroke="gray"
strokeWidth={1.22998}
strokeLinecap="round"
strokeLinejoin="round"
strokeOpacity={1}
/>
<Rect
width={2.2979565}
height={10.095428}
x={28.63328}
y={70.079712}
ry={1.4526443}
fill="gray"
fillOpacity={1}
stroke="gray"
strokeWidth={1.39732}
strokeLinecap="round"
strokeLinejoin="round"
strokeOpacity={1}
/>
</G>
</Svg>
);
}

export default Gnod;
4 changes: 4 additions & 0 deletions mobile/components/icons/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import CheckMark from "./CheckMark";
import Home from "./Home";
import Search from "./Search";
import Profile from "./Profile";
import Gnod from "./Gnod";
import Gnoded from "./Gnoded";

const Icons = {
ArrowLeft,
Expand All @@ -14,6 +16,8 @@ const Icons = {
Home,
Search,
Profile,
Gnod,
Gnoded
};

export default Icons;
4 changes: 3 additions & 1 deletion mobile/components/view/account/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ interface Props {
onPressFollow: (address: string) => void;
onPressUnfollow: (address: string) => void;
onPressPost: (post: Post) => void;
onGnod: (post: Post) => void;
user: User;
currentUser: User;
followers: Following[];
Expand All @@ -27,6 +28,7 @@ function AccountView(props: Props) {
onPressFollow,
onPressUnfollow,
onPressPost,
onGnod,
user,
following,
followers,
Expand Down Expand Up @@ -79,7 +81,7 @@ function AccountView(props: Props) {
<View style={{ flex: 1, width: "100%", paddingHorizontal: 16, paddingTop: 8 }}>
<Text.Body>Posts</Text.Body>
<View style={{ height: 1, backgroundColor: colors.grayscale[200] }} />
<FeedView totalPosts={totalPosts} onPress={onPressPost} address={user.address} type="userPosts" />
<FeedView totalPosts={totalPosts} onPress={onPressPost} onGnod={onGnod} address={user.address} type="userPosts" />
</View>
</View>
</Layout.Container>
Expand Down
5 changes: 3 additions & 2 deletions mobile/components/view/feed/feed-view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ import { Tweet } from "@gno/components/feed/tweet";
type Props = {
totalPosts: number;
onPress: (item: Post) => void;
onGnod: (item: Post) => void;
address: string;
type: "userPosts" | "userFeed";
};

const subtractOrZero = (a: number, b: number) => Math.max(0, a - b);

export default function FeedView({ totalPosts, onPress, address, type }: Props) {
export default function FeedView({ totalPosts, onPress, onGnod, address, type }: Props) {
const pageSize = 9;
const [startIndex, setStartIndex] = useState(subtractOrZero(totalPosts, pageSize));
const [endIndex, setEndIndex] = useState(totalPosts);
Expand Down Expand Up @@ -117,7 +118,7 @@ export default function FeedView({ totalPosts, onPress, address, type }: Props)
ListEmptyComponent={<EmptyFeedList />}
keyExtractor={(item) => `${item.id}`}
contentContainerStyle={styles.flatListContent}
renderItem={({ item }) => <Tweet post={item} onPress={onPress} />}
renderItem={({ item }) => <Tweet post={item} onPress={onPress} onGnod={onGnod} />}
onEndReached={handleEndReached}
onEndReachedThreshold={0.1}
/>
Expand Down
3 changes: 1 addition & 2 deletions mobile/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 5c6b8b1

Please sign in to comment.