Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android Deeplinking: Inviting/joining other packs #77

Open
wants to merge 28 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e9143e4
Add simple '/pack/:stickerPackId' deeplink
MKuijpers Mar 20, 2021
c361836
Add join screen and deeplink connection to the join screen
MKuijpers Mar 29, 2021
f0829f2
Merge branch 'master' into deeplinking
MKuijpers Apr 2, 2021
4f494a1
Use new invite API for invites/joining
MKuijpers Apr 3, 2021
e0071a5
Small cleanup
MKuijpers Apr 3, 2021
189d08d
Rewrite StickerPackScreen to FC
MKuijpers Apr 3, 2021
f477146
Generate invite URL on client
MKuijpers Apr 3, 2021
7445498
Convert toolbar to FC
MKuijpers Apr 3, 2021
806a394
Revert sticker pack header change to avoid conflicts
MKuijpers Apr 3, 2021
a58c119
Build apk
MKuijpers Apr 12, 2021
9988115
Merge branch 'master' into deeplinking
MKuijpers Apr 12, 2021
90865a0
Add branches wildcard for pull_request in APK build
MKuijpers Apr 12, 2021
f26bbf5
Fix syntax in .yml
MKuijpers Apr 12, 2021
cb86c2d
Temporarily remove path requirement for build-apk.yml
MKuijpers Apr 12, 2021
7874eda
Add (hopefully) correct app path requirement for apk-build.yml
MKuijpers Apr 12, 2021
cbc8886
Extract pack stickers view to component
MKuijpers Apr 17, 2021
f9c4723
Simplify ci change
MKuijpers Apr 17, 2021
eaa9240
Merge branch 'master' into deeplinking
MKuijpers Jan 19, 2023
44dd456
Change deeplink domain to vercel preview domain
MKuijpers Jan 19, 2023
e9120ea
Merge branch 'mvp-screen-changes' into deeplinking
MKuijpers Jan 19, 2023
a0d3b57
Merge branch 'mvp-screen-changes' into deeplinking
MKuijpers Jan 20, 2023
8ab970e
Change join sticker pack screen design by reusing sticker pack screen…
MKuijpers Jan 20, 2023
b0e4a12
Merge branch 'mvp-screen-changes' into deeplinking
MKuijpers Jan 21, 2023
f887b11
Merge branch 'mvp-screen-changes' into deeplinking
MKuijpers Jan 22, 2023
6c732ec
Merge branch 'mvp-screen-changes' into deeplinking
MKuijpers Jan 22, 2023
87b75f2
Implement kicking sticker pack members
MKuijpers Jan 22, 2023
2ef1f27
Merge branch 'master' into deeplinking
MKuijpers Jan 23, 2023
6b93e15
Merge branch 'master' into deeplinking
MKuijpers Feb 1, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build-apk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:
- master
pull_request:
paths:
- app/*
- 'app/*'

jobs:
build-apk:
Expand Down
14 changes: 14 additions & 0 deletions app/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,20 @@
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="kangaroo" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data
android:scheme="https"
android:host="kangaroo-brian2509.vercel.app" />
</intent-filter>
</activity>

<!-- <custom-config> -->
Expand Down
33 changes: 33 additions & 0 deletions app/src/api/hooks/mutations/invites.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { QueryClient, useMutation } from "react-query";
import { QUERY_KEYS } from "../../../constants/ReactQueryKeys";
import {
CreateInviteDto,
InviteRoDto,
StickerPackRo,
} from "../../generated-typescript-api-client/src";
import { api } from "../../generatedApiWrapper";

const useInvite = async (inviteId: string) => {
const { data } = await api.invites.useInvite(inviteId);
return data;
};

export const useInviteMutation = (queryClient: QueryClient) =>
useMutation<StickerPackRo, any, string, unknown>(useInvite, {
onSuccess: () => {
queryClient.invalidateQueries(QUERY_KEYS.ownAndJoinedStickerPacks);
},
});

const createInvite = async (
stickerPackId: string,
createInviteDto: CreateInviteDto,
): Promise<InviteRoDto> => {
const { data } = await api.stickerPacks.createInvite(stickerPackId, createInviteDto || {});
return data;
};

export const useCreateInviteMutation = (stickerPackId: string) =>
useMutation<InviteRoDto, any, CreateInviteDto, unknown>((createInviteDto: CreateInviteDto) =>
createInvite(stickerPackId, createInviteDto),
);
25 changes: 21 additions & 4 deletions app/src/api/hooks/mutations/stickerPack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const createStickerPack = async (createStickerPackDto: CreateStickerPackDto) =>
};
export const useCreateStickerPackMutation = (queryClient: QueryClient) =>
useMutation<StickerPackRo, any, CreateStickerPackDto, unknown>(createStickerPack, {
onSuccess: () => queryClient.invalidateQueries(QUERY_KEYS.myStickerPacks),
onSuccess: () => queryClient.invalidateQueries(QUERY_KEYS.ownAndJoinedStickerPacks),
});

// Remove Sticker Pack Mutation
Expand All @@ -25,15 +25,15 @@ const removeStickerPack = async (stickerPackId: string) => {
};
export const useRemoveStickerPackMutation = (queryClient: QueryClient) =>
useMutation<StickerPackRo, any, string, unknown>(removeStickerPack, {
onSuccess: () => queryClient.invalidateQueries(QUERY_KEYS.myStickerPacks),
onSuccess: () => queryClient.invalidateQueries(QUERY_KEYS.ownAndJoinedStickerPacks),
});

// Upload Sticker Mutation
export const useUploadStickerMutation = (queryClient: QueryClient) =>
useMutation<StickerRo, any, UploadStickerRo, unknown>(uploadSticker, {
onSuccess: (data, variables) => {
queryClient.invalidateQueries([QUERY_KEYS.stickerPack, variables.stickerPackId]);
queryClient.invalidateQueries(QUERY_KEYS.myStickerPacks);
queryClient.invalidateQueries(QUERY_KEYS.ownAndJoinedStickerPacks);
},
});

Expand All @@ -51,6 +51,23 @@ export const useDeleteStickerMutation = (queryClient: QueryClient) =>
useMutation<StickerRo, any, DeleteStickerRo, unknown>(deleteSticker, {
onSuccess: (data, variables) => {
queryClient.invalidateQueries([QUERY_KEYS.stickerPack, variables.stickerPackId]);
queryClient.invalidateQueries(QUERY_KEYS.myStickerPacks);
queryClient.invalidateQueries(QUERY_KEYS.ownAndJoinedStickerPacks);
},
});

// Kick user Mutation
interface KickMemberDto {
stickerPackId: string,
userToBeKickedId: string
}
const kickMember = async (kickMemberDto: KickMemberDto) => {
const { stickerPackId, userToBeKickedId } = kickMemberDto;
const { data } = await api.stickerPacks.kickMember(stickerPackId, userToBeKickedId);
return data;
};
export const useKickMemberMutation = (queryClient: QueryClient) =>
useMutation<StickerPackRo, any, KickMemberDto, unknown>(kickMember, {
onSuccess: (data, variables) => {
queryClient.invalidateQueries([QUERY_KEYS.stickerPack, variables.stickerPackId]);
},
});
21 changes: 21 additions & 0 deletions app/src/api/hooks/query/invites.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { QueryClient, useQuery } from "react-query";
import { QUERY_KEYS } from "../../../constants/ReactQueryKeys";
import { StickerPackRo } from "../../generated-typescript-api-client/src";
import { api } from "../../generatedApiWrapper";

const getInvitePreview = async (inviteId: string) => {
const { data } = await api.invites.previewInvite(inviteId);
return data;
};

export const useInvitePreview = (queryClient: QueryClient, inviteId: string) =>
useQuery<StickerPackRo, any, StickerPackRo>(
[QUERY_KEYS.invitePreview, inviteId],
() => getInvitePreview(inviteId),
{
onSuccess: (data) => {
queryClient.invalidateQueries(QUERY_KEYS.ownAndJoinedStickerPacks);
queryClient.invalidateQueries([QUERY_KEYS.stickerPack, data.id]);
},
},
);
10 changes: 7 additions & 3 deletions app/src/api/hooks/query/stickerPack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,17 @@ export const useStickerPack = (id: string) =>
);

const getStickerPacks = async () => {
const { data } = await api.users.getOwnStickerPacks();
// TODO: After merge, use get "getOwnAndJoinedStickerPacks" method, which is not working at the time of merging
const { data } = await api.users.getOwnAndJoinedStickerPacks();
// Backend returns stickers in reverse order, so we need to sort them first.
for (let i = 0; i < data.length; i++) {
data[i].stickers = sortStickersByCreatedAt(data[i].stickers);
}
return data;
};

export const useStickerPacks = () =>
useQuery<StickerPackRo[], any, StickerPackRo[]>(QUERY_KEYS.myStickerPacks, getStickerPacks);
export const useOwnAndJoinedStickerPacks = () =>
useQuery<StickerPackRo[], any, StickerPackRo[]>(
QUERY_KEYS.ownAndJoinedStickerPacks,
getStickerPacks,
);
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ interface Props {
selectedMember: UserRo;
modalVisible: boolean;
closeModal: () => void;
onPressKickMember: () => void;
}

export const MemberClickedModal = ({
selectedMember,
modalVisible,
closeModal,
onPressKickMember
}: Props): JSX.Element => {
return (
<Modal
Expand All @@ -32,10 +34,7 @@ export const MemberClickedModal = ({
Close
</Button>
)}>
<Button size="medium" appearance="ghost" status="basic">
Remove as Admin
</Button>
<Button status="danger" size="medium" appearance="ghost">
<Button status="danger" size="medium" appearance="ghost" onPress={onPressKickMember}>
Remove from Pack
</Button>
</Card>
Expand Down
27 changes: 4 additions & 23 deletions app/src/components/sticker-pack-manage-screen/MemberList.tsx
Original file line number Diff line number Diff line change
@@ -1,33 +1,21 @@
import React, { useEffect, useState } from "react";
import React from "react";
import { Divider, Icon, List, ListItem } from "@ui-kitten/components";
import { StickerPackRo, UserRo } from "../../api/generated-typescript-api-client/src";
import { isAuthor } from "../../util/stickerpack_utils";
import { Text } from "react-native";
import { MemberClickedModal } from "./MemberClickedModal";
import tw from "tailwind-react-native-classnames";

interface Props {
stickerPack: StickerPackRo;
onPressMember: (user: UserRo | undefined) => void;
}

export const MemberList = ({ stickerPack }: Props): JSX.Element => {
const [modalVisible, setModalVisible] = useState<boolean>(false);
const [clickedMember, setClickedMember] = useState<UserRo | undefined>();

useEffect(() => {
const shouldOpenModal = clickedMember != undefined;
setModalVisible(shouldOpenModal);
}, [clickedMember]);

const closeModal = () => {
setModalVisible(false);
setClickedMember(undefined);
};
export const MemberList = ({ stickerPack, onPressMember }: Props): JSX.Element => {

const renderItem = ({ item: user }: { item: UserRo }) => (
<ListItem
onPress={() => {
setClickedMember(user);
onPressMember(user);
}}
title={`${user.username}`}
accessoryLeft={(props) => <Icon name="person" {...props} />}
Expand All @@ -47,13 +35,6 @@ export const MemberList = ({ stickerPack }: Props): JSX.Element => {
ItemSeparatorComponent={Divider}
renderItem={renderItem}
/>
{clickedMember && (
<MemberClickedModal
selectedMember={clickedMember}
modalVisible={modalVisible}
closeModal={closeModal}
/>
)}
</>
);
};
55 changes: 55 additions & 0 deletions app/src/components/stickerpack/PackStickersView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React from "react";
import { Layout, Text } from "@ui-kitten/components";
import { Image, TouchableOpacity } from "react-native";
import { StickerPackRo, StickerRo } from "../../api/generated-typescript-api-client/src";
import tw from "tailwind-react-native-classnames";

interface Props {
stickerPack: StickerPackRo;
onStickerPress?: (sticker: StickerRo) => void;
}

export const PackStickersView = ({ stickerPack, onStickerPress }: Props): JSX.Element => {
const renderSticker = (sticker: StickerRo): JSX.Element => {
return (
<TouchableOpacity
key={sticker.id}
style={{
width: "21%",
height: "auto",
marginHorizontal: "2%",
marginBottom: "3.5%",
}}
disabled={onStickerPress == undefined}
onPress={() => {
onStickerPress?.(sticker);
}}>
<Image
style={tw.style("rounded-lg", {
width: "100%",
paddingBottom: "100%",
borderRadius: 3,
})}
source={{
uri: sticker.fileUrl,
}}
/>
</TouchableOpacity>
);
};

return (
<Layout style={tw`flex-col p-2 pt-1 pb-8`}>
<Layout style={tw`flex-row flex-grow justify-between items-baseline`}>
<Text style={tw`font-semibold mr-4`}>
Willem Alexander
<Text style={tw`text-xs text-gray-500`}> ({stickerPack.stickers.length})</Text>
</Text>
<Text style={tw`text-gray-500 pt-3 text-xs`}>Wed 4:20</Text>
</Layout>
<Layout style={tw`flex-row flex-wrap pt-3`}>
{stickerPack.stickers.map(renderSticker)}
</Layout>
</Layout>
);
};
15 changes: 9 additions & 6 deletions app/src/components/stickerpack/StickerPackHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { CHEVRON_ICON_COLOR } from "../../constants/colors";

interface Props {
stickerPack: StickerPackRo;
onHeaderPress: () => void;
onHeaderPress?: () => void;
}
const StickerPackHeader = ({ stickerPack, onHeaderPress }: Props): JSX.Element => {
const numMembers = stickerPack.members.length;
Expand All @@ -18,6 +18,7 @@ const StickerPackHeader = ({ stickerPack, onHeaderPress }: Props): JSX.Element =
<TouchableOpacity
style={tailwind("flex flex-row justify-between items-center p-4 border-b-2 border-gray-200")}
onPress={onHeaderPress}
disabled={onHeaderPress === undefined}
>
<Layout style={tailwind("flex flex-row items-center")}>
<CoverStickerImage
Expand All @@ -36,11 +37,13 @@ const StickerPackHeader = ({ stickerPack, onHeaderPress }: Props): JSX.Element =
</Text>
</Layout>
</Layout>
<Icon
style={tailwind("w-8 h-8")}
fill={CHEVRON_ICON_COLOR}
name='chevron-right-outline'
/>
{onHeaderPress ? (
<Icon
style={tailwind("w-8 h-8")}
fill={CHEVRON_ICON_COLOR}
name='chevron-right-outline'
/>
) : null}
</TouchableOpacity >
)
}
Expand Down
8 changes: 4 additions & 4 deletions app/src/components/stickerpack/StickerPackStickersBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,9 @@ export const StickerGrid = ({ stickers, onStickerPress, stickersPerRow = 4 }: St

interface StickerPackBodyProps {
stickerPack: StickerPackRo;
onStickerPress: (sticker: StickerRo) => void;
refreshing: boolean;
onRefresh: () => void;
onStickerPress?: (sticker: StickerRo) => void;
refreshing?: boolean;
onRefresh?: () => void;
}
const StickerPackBody = ({ stickerPack, onStickerPress, refreshing, onRefresh }: StickerPackBodyProps): JSX.Element => {

Expand All @@ -74,7 +74,7 @@ const StickerPackBody = ({ stickerPack, onStickerPress, refreshing, onRefresh }:
return (
<ScrollView
style={tailwind("p-6")}
refreshControl={<RefreshControl refreshing={refreshing} onRefresh={onRefresh} />}
refreshControl={<RefreshControl refreshing={refreshing || false} onRefresh={onRefresh} />}
>
<Layout style={tailwind("flex-row justify-between items-baseline pb-4 pt-2")}>
<Layout style={tailwind("flex-row items-baseline")}>
Expand Down
1 change: 1 addition & 0 deletions app/src/constants/Deeplinking.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const DEEPLINK_SITE_DOMAIN = "https://kangaroo-brian2509.vercel.app";
3 changes: 2 additions & 1 deletion app/src/constants/ReactQueryKeys.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export const QUERY_KEYS = {
myStickerPacks: "myStickerPacks",
ownAndJoinedStickerPacks: "ownAndJoinedStickerPacks",
stickerPack: "stickerPack",
invitePreview: "invitePreview",
me: "myProfile",
like: "like",
};
1 change: 1 addition & 0 deletions app/src/constants/StickerPack.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export const ACCOUNT_MAX_PREVIEW_STICKERS = 8;
export const MAX_STICKERS_PER_PACK = 30;
3 changes: 2 additions & 1 deletion app/src/navigation/RootNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Layout, Spinner } from "@ui-kitten/components";
import { AuthStackNavigator } from "./auth/AuthStackNavigator";
import { AppStackNavigator } from "./app/AppStackNavigator";
import tailwind from "tailwind-rn";
import { deepLinkingOptions } from "./deeplinking/deeplinkingOptions";

type RootStackNavigatorProps = {
isAuthenticated: boolean
Expand Down Expand Up @@ -45,7 +46,7 @@ export const RootNavigator = (): React.ReactElement => {
}

return (
<NavigationContainer>
<NavigationContainer linking={deepLinkingOptions}>
<RootStackNavigator isAuthenticated={isAuthenticated} />
</NavigationContainer>
);
Expand Down
Loading