Skip to content

Commit 493fbf0

Browse files
authored
chore: make sample user friendly (#90)
🎫 Ticket: https://linear.app/stream/issue/XYZ-123 πŸ“‘ Docs: https://github.com/GetStream/docs-content/pull/<id> ### πŸ’‘ Overview ### πŸ“ Implementation notes
1 parent 95b62d4 commit 493fbf0

File tree

9 files changed

+147
-29
lines changed

9 files changed

+147
-29
lines changed
Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
1-
EXPO_PUBLIC_TOKEN_CREATION_URL=
2-
EXPO_PUBLIC_BASE_URL=
31
EXPO_PUBLIC_PLACES_API_KEY=
42
EXPO_PUBLIC_MAPS_API_KEY=
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# Expo TikTok Sample App
2+
3+
This is a sample application displaying some of the capabilities of our `feeds-react-native-sdk`, build using `Expo`.
4+
5+
## Running the app
6+
7+
### Install the `expo` toolset
8+
9+
- Install the global `expo` package by running `npm install -g expo`
10+
11+
### Clone the Project
12+
13+
```bash
14+
git clone https://github.com/GetStream/stream-feeds-js.git
15+
```
16+
17+
### Installation
18+
19+
1. At the root of the project, install dependencies
20+
21+
```bash
22+
yarn install
23+
```
24+
25+
2. Build all of the libraries
26+
27+
```bash
28+
yarn build:libs
29+
```
30+
31+
3. Move to the `packages/feeds-client` directory and run it in `--watch` mode:
32+
33+
```bash
34+
cd packages/feeds-client && yarn start
35+
```
36+
37+
4. Open a new terminal window and move to the `sample-apps/react-native/ExpoTikTokApp` directory and install the dependencies:
38+
39+
```bash
40+
cd sample-apps/react-native/ExpoTikTokApp && yarn install
41+
```
42+
43+
5. (optional) Generate a Google Maps API key
44+
45+
In order for viewing a designated location on a map to work as a feature, you will need to create a Google Maps API key.
46+
47+
For this purpose, you can follow [their official documentation](https://developers.google.com/maps/documentation/android-sdk/get-api-key).
48+
49+
To include it in the app, you will need to set it to the `EXPO_PUBLIC_MAPS_API_KEY` environment variable.
50+
51+
Omitting this step will simply disable the feature.
52+
53+
> **WARNING**: Before you can start using the Google Maps Platform APIs and SDKs, you must sign up and create a [billing account](https://developers.google.com/maps/gmp-get-started#create-billing-account)!
54+
55+
6. (optional) Generate a `Geoapify` API key
56+
57+
In order for the location search feature to be available, you're going to need to generate a `Geoapify` API key.
58+
59+
To do that, you may follow [their documentation](https://www.geoapify.com/get-started-with-maps-api/).
60+
61+
To include it in the app, you will need to set it to the `EXPO_PUBLIC_PLACES_API_KEY` environment variable.
62+
63+
Omitting this step will simply disable the feature.
64+
65+
7. (optional) Create a `.env` file
66+
67+
If you did any of steps `5.` or `6.`, you will need to add them to a `.env` file so that they can be consumed by the app.
68+
69+
To do this, create the file in `sample-apps/react-native/ExpoTikTokApp` and fill in the respective environment variables.
70+
71+
It should look something like this:
72+
73+
```
74+
EXPO_PUBLIC_PLACES_API_KEY=<geapify-api-key>
75+
EXPO_PUBLIC_MAPS_API_KEY=<google-maps-api-key>
76+
```
77+
78+
### Run
79+
80+
To run the application for different platforms, use the following commands:
81+
82+
- For iOS
83+
84+
```bash
85+
yarn run ios -d
86+
```
87+
88+
- For android
89+
90+
```bash
91+
yarn run android -d
92+
```
93+
94+
## Using user tokens directly
95+
96+
If you want to use user tokens instead of the default token provider setup you can do the following:
97+
98+
1. Generate a user token using a user ID and API secret [here](https://getstream.io/chat/docs/react/token_generator/).
99+
2. Open `sample-apps/react-native/ExpoTikTokApp/users.json` and add a `token` field to any user
100+
101+
The `token` field will be preferred over the token provider, if it exists.
102+
103+
> **NOTE**: Since users are cached when logged in, if you change the `token` of a user from `users.json` it's best to uninstall and then reinstall the app so that the cache is cleared.
104+
105+
## Using your own API key
106+
107+
To use your own API key with the sample app, you may do the following steps.
108+
109+
1. Open the `sample-apps/react-native/ExpoTikTokApp/constants/stream.ts` file and change the `apiKey` variable to your own API key
110+
2. Populate the app with the respective API key with users, their feeds and their follow relationships
111+
3. The easiest way to do this is by running the `sample-apps/react-sample-app/setup-env.js` script either directly from our repository or from your own (you can temporarily replace the environment variables in place with your own credentials, you can simply omit `NEXT_PUBLIC_API_URL`)
112+
4. Create user tokens manually for the users you'd like to use like it's explained [here](#using-user-tokens-directly), since the token provider is not going to work out of the box

β€Žsample-apps/react-native/ExpoTikTokApp/app/_layout.tsxβ€Ž

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@ import React, { useEffect } from 'react';
1111
import { Text } from 'react-native';
1212
import 'react-native-reanimated';
1313
import { StreamFeeds } from '@stream-io/feeds-react-native-sdk';
14-
import type { UserRequest } from '@stream-io/feeds-react-native-sdk';
1514
import LoginScreen from '@/components/LoginScreen';
1615

1716
import { useColorScheme } from '@/components/useColorScheme';
18-
import { UserContextProvider, useUserContext } from '@/contexts/UserContext';
17+
import {
18+
LocalUser,
19+
UserContextProvider,
20+
useUserContext,
21+
} from '@/contexts/UserContext';
1922
import { useCreateClient } from '@/hooks/useCreateClient';
2023
import { ErrorBoundary as InternalErrorBoundary } from '@/components/ErrorBoundary';
2124
import { View } from 'react-native';
@@ -67,7 +70,7 @@ const RootLayout = () => {
6770
return <RootLayoutNav user={user} />;
6871
};
6972

70-
const RootLayoutNav = ({ user }: { user: UserRequest }) => {
73+
const RootLayoutNav = ({ user }: { user: LocalUser }) => {
7174
const colorScheme = useColorScheme();
7275

7376
const client = useCreateClient(user);

β€Žsample-apps/react-native/ExpoTikTokApp/components/LocationPreview.tsxβ€Ž

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Text, StyleSheet, Pressable } from 'react-native';
33
import { Ionicons } from '@expo/vector-icons';
44
import { Place } from '@/components/PlaceSearchDropdown';
55
import { useRouter } from 'expo-router';
6+
import { mapApiKey } from '@/constants/stream';
67

78
type LocationPreviewProps = {
89
location: Omit<Place, 'id' | 'address'>;
@@ -12,9 +13,11 @@ export const LocationPreview = ({ location }: LocationPreviewProps) => {
1213
const router = useRouter();
1314
return (
1415
<Pressable
15-
onPress={() =>
16-
router.push({ pathname: '/location-map-screen', params: location })
17-
}
16+
onPress={() => {
17+
if (mapApiKey) {
18+
router.push({ pathname: '/location-map-screen', params: location });
19+
}
20+
}}
1821
style={styles.container}
1922
>
2023
<Ionicons

β€Žsample-apps/react-native/ExpoTikTokApp/components/LoginScreen.tsxβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ const PredefinedUserItem = ({ item }: { item: LocalUser}) => {
2121
const { logIn } = useUserContext();
2222

2323
const handleUserSelect = useCallback((user: LocalUser) => {
24-
logIn({ id: user.id });
24+
logIn(user);
2525
}, [logIn]);
2626

2727
return (
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
// export const apiKey = 'fa5xpkvxrdw4';
21
export const apiKey = 'ccqysy8u2tm6';
32
export const tokenCreationUrl = 'https://pronto.getstream.io/api/auth/create-token?environment=feeds-react-native-sample-app';
43
export const placesApiKey = process.env.EXPO_PUBLIC_PLACES_API_KEY;
4+
export const mapApiKey = process.env.EXPO_PUBLIC_MAPS_API_KEY;
55

66
export const COMMENTS_LOADING_CONFIG = { sort: 'last', limit: 5 };
77
export const ACTIVITY_TEXT_MAX_CHARACTERS = 250;

β€Žsample-apps/react-native/ExpoTikTokApp/contexts/UserContext.tsxβ€Ž

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ import {
88
import { UserRequest } from '@stream-io/feeds-react-native-sdk';
99
import AsyncStorage from '@react-native-async-storage/async-storage';
1010

11+
export type LocalUser = Pick<UserRequest, 'id' | 'name' | 'image'> & { token?: string };
12+
1113
type UserContextValue = {
12-
user: UserRequest | null;
14+
user: LocalUser | null;
1315
userLoaded: boolean;
14-
logIn: (user: UserRequest) => Promise<void>;
16+
logIn: (user: LocalUser) => Promise<void>;
1517
logOut: () => Promise<void>;
1618
};
1719

@@ -23,7 +25,7 @@ const UserContext = createContext<UserContextValue>({
2325
});
2426

2527
export const UserContextProvider = ({ children }: PropsWithChildren) => {
26-
const [cachedUser, setCachedUser] = useState<UserRequest | null>(null);
28+
const [cachedUser, setCachedUser] = useState<LocalUser | null>(null);
2729
const [userLoaded, setUserLoaded] = useState(false);
2830

2931
useEffect(() => {
@@ -37,7 +39,7 @@ export const UserContextProvider = ({ children }: PropsWithChildren) => {
3739
fetchUserFromStorage();
3840
}, []);
3941

40-
const logIn = async (user: UserRequest) => {
42+
const logIn = async (user: LocalUser) => {
4143
await AsyncStorage.setItem('@stream-io/login-config', JSON.stringify(user));
4244
setCachedUser(user);
4345
};

β€Žsample-apps/react-native/ExpoTikTokApp/hooks/useCreateClient.tsβ€Ž

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import { useCallback } from 'react';
2-
import {
3-
useCreateFeedsClient
4-
} from '@stream-io/feeds-react-native-sdk';
5-
import type { UserRequest } from '@stream-io/feeds-react-native-sdk';
2+
import { useCreateFeedsClient } from '@stream-io/feeds-react-native-sdk';
63
import { apiKey, tokenCreationUrl } from '@/constants/stream';
4+
import { LocalUser } from '@/contexts/UserContext';
75

86
const tokenProviderFactory = (userId: string) => async () => {
97
if (!tokenCreationUrl) {
@@ -20,17 +18,19 @@ const tokenProviderFactory = (userId: string) => async () => {
2018
return data.token;
2119
};
2220

23-
const CLIENT_OPTIONS = { base_url: process.env.EXPO_PUBLIC_BASE_URL };
21+
const CLIENT_OPTIONS = {};
2422

25-
export const useCreateClient = (user: UserRequest) => {
23+
export const useCreateClient = (user: LocalUser) => {
2624
const tokenProvider = useCallback(() => {
2725
const provider = tokenProviderFactory(user.id);
2826
return provider();
2927
}, [user.id]);
3028

29+
const userData = { id: user.id, image: user.image, name: user.name };
30+
3131
const client = useCreateFeedsClient({
32-
userData: user,
33-
tokenOrProvider: tokenProvider,
32+
userData,
33+
tokenOrProvider: user.token ?? tokenProvider,
3434
options: CLIENT_OPTIONS,
3535
apiKey,
3636
});
@@ -39,4 +39,4 @@ export const useCreateClient = (user: UserRequest) => {
3939
globalThis.client = client;
4040

4141
return client;
42-
}
42+
};

β€Žsample-apps/react-native/ExpoTikTokApp/users.jsonβ€Ž

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,31 @@
22
{
33
"id": "susan",
44
"name": "Susan",
5-
"image": "https://randomuser.me/api/portraits/women/47.jpg",
5+
"image": "https://randomuser.me/api/portraits/women/47.jpg"
66
},
77
{
88
"id": "adam",
99
"name": "Adam",
10-
"image": "https://randomuser.me/api/portraits/men/38.jpg",
10+
"image": "https://randomuser.me/api/portraits/men/38.jpg"
1111
},
1212
{
1313
"id": "thomas",
1414
"name": "Thomas",
15-
"image": "https://randomuser.me/api/portraits/men/42.jpg",
15+
"image": "https://randomuser.me/api/portraits/men/42.jpg"
1616
},
1717
{
1818
"id": "sloan",
1919
"name": "Sloan",
20-
"image": "https://randomuser.me/api/portraits/women/60.jpg",
20+
"image": "https://randomuser.me/api/portraits/women/60.jpg"
2121
},
2222
{
2323
"id": "tiffany",
2424
"name": "Tiffany",
25-
"image": "https://randomuser.me/api/portraits/women/40.jpg",
25+
"image": "https://randomuser.me/api/portraits/women/40.jpg"
2626
},
2727
{
2828
"id": "jack",
2929
"name": "Jack",
30-
"image": "https://randomuser.me/api/portraits/men/54.jpg",
30+
"image": "https://randomuser.me/api/portraits/men/54.jpg"
3131
}
3232
]

0 commit comments

Comments
Β (0)