Skip to content

Commit

Permalink
chore: add group chat demo (#69)
Browse files Browse the repository at this point in the history
Co-authored-by: DominicGBauer <[email protected]>
Co-authored-by: benitav <[email protected]>
  • Loading branch information
3 people authored Feb 13, 2024
1 parent 9846f3c commit b4cd43f
Show file tree
Hide file tree
Showing 61 changed files with 11,827 additions and 8,422 deletions.
4 changes: 4 additions & 0 deletions demos/react-native-supabase-group-chat/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
EXPO_PUBLIC_SUPABASE_URL=https://durbqntqcbthnzeyncft.supabase.co
EXPO_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImR1cmJxbnRxY2J0aG56ZXluY2Z0Iiwicm9sZSI6ImFub24iLCJpYXQiOjE2OTYzOTk0MDksImV4cCI6MjAxMTk3NTQwOX0.mbYtqYHt6vX1K5p9KjjLgiCmveWkHdSUH3dgdVTHBNs
EXPO_PUBLIC_POWERSYNC_URL=https://652c8d6e54e498b08255ab81.powersync.journeyapps.com
EXPO_PUBLIC_EAS_PROJECT_ID=c08eefc9-7b5b-487e-85c7-22e14b7287c0
2 changes: 2 additions & 0 deletions demos/react-native-supabase-group-chat/.eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/.expo
node_modules
16 changes: 16 additions & 0 deletions demos/react-native-supabase-group-chat/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
module.exports = {
extends: ["universe", "universe/shared/typescript-analysis"],
overrides: [
{
files: ["*.ts", "*.tsx", "*.d.ts"],
parserOptions: {
project: "./tsconfig.json",
tsconfigRootDir: __dirname,
},
},
],
ignorePatterns: ["*.typegen.ts", "database.types.ts"],
env: {
node: true,
},
};
23 changes: 23 additions & 0 deletions demos/react-native-supabase-group-chat/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
node_modules/
.expo/
dist/
npm-debug.*
*.jks
*.p8
*.p12
*.key
*.mobileprovision
*.orig.*
web-build/

# macOS
.DS_Store

# Temporary files created by Metro to check the health of the file watcher
.metro-health-check*

# .env
*.ipa
*.tar.gz
.tamagui
ios/
23 changes: 23 additions & 0 deletions demos/react-native-supabase-group-chat/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# PowerChat - Demo app for the PowerSync React Native Client SDK

This is a demo app built to showcase how to use PowerSync to built an offline-first React Native app. The app is built with Expo/React Native, and uses Supabase as the backend. The following video gives an overview of the implemented functionality:

<https://github.com/journeyapps/powersync-supabase-react-native-group-chat-demo/assets/91166910/f93c484a-437a-44b3-95ab-f5864a99ca1f>

Here are some steps to keep in mind when building/deploying your own version of this app:

1. Deploy a Supabase backend based on the configuration and migrations contained in the [supabase](./supabase) folder. The API URL and public API Key from your Supabase project need to be replaced in the [.env](./.env) file.

2. Create a PowerSync instance using the [PowerSync dashboard](https://powersync.journeyapps.com/) and connect the instance to your Supabase backend. Copy the Sync Rules from the [sync-rules.yml](./sync-rules.yml) of this repository into the sync-rules.yaml within the PowerSync dashboard. Copy the PowerSync instance URL from the dashboard and replace it in the [.env](./.env) file.

3. Create an Expo project and replace the EAS project id in the [.env](./.env) file.

> Please note: If you leave the values within the [.env](./.env) file as they are (none of them are sensitive secret's btw), you can try the app with the demo backend without spinning up your own Supabase backend and PowerSync instance (as long at the demo backend is around, at least).
Here are some helpful links:

- [PowerSync Website](https://www.powersync.com/)
- [PowerSync Docs](https://docs.powersync.com/)
- [PowerSync React Native Client SDK](https://github.com/journeyapps/powersync-js/tree/main/packages/powersync-sdk-react-native)
- [Supabase Docs](https://supabase.com/docs)
- [Expo Docs](https://docs.expo.dev/)
56 changes: 56 additions & 0 deletions demos/react-native-supabase-group-chat/app.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { type ExpoConfig } from "expo/config";

const projectId = process.env.EXPO_PUBLIC_EAS_PROJECT_ID;

const config: ExpoConfig = {
name: "PowerChat",
slug: "powerchat",
scheme: "powerchat",
version: "1.0.0",
orientation: "portrait",
icon: "./assets/icon.png",
userInterfaceStyle: "automatic",
splash: {
image: "./assets/splash.png",
resizeMode: "contain",
backgroundColor: "#cb62ff",
},
updates: {
url: `https://u.expo.dev/${projectId}`,
},
assetBundlePatterns: ["**/*"],
ios: {
supportsTablet: true,
bundleIdentifier: "com.powerchat",
config: {
usesNonExemptEncryption: false,
},
jsEngine: "jsc",
},
experiments: {
tsconfigPaths: true,
},
android: {
adaptiveIcon: {
foregroundImage: "./assets/adaptive-icon.png",
backgroundColor: "#ffffff",
},
},
web: {
favicon: "./assets/favicon.png",
bundler: "metro",
},
extra: {
eas: {
projectId,
},
},
runtimeVersion: {
policy: "sdkVersion",
},
plugins: [
"expo-router"
]
};

export default config;
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions demos/react-native-supabase-group-chat/babel.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module.exports = function (api) {
api.cache(true);
return {
presets: ["babel-preset-expo"],
plugins: [
[
"@tamagui/babel-plugin",
{
components: ["tamagui"],
config: "./src/tamagui.config.ts",
},
],
"@babel/plugin-transform-async-generator-functions",
"react-native-reanimated/plugin",
],
};
};
26 changes: 26 additions & 0 deletions demos/react-native-supabase-group-chat/eas.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"cli": {
"version": ">= 3.13.3",
"promptToConfigurePushNotifications": false
},
"build": {
"development": {
"developmentClient": true,
"distribution": "internal",
"channel": "preview"
},
"simulator": {
"extends": "development",
"ios": {
"simulator": true
}
},
"preview": {
"channel": "preview",
"distribution": "internal"
},
"production": {
"channel": "production"
}
}
}
1 change: 1 addition & 0 deletions demos/react-native-supabase-group-chat/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
import 'expo-router/entry';
22 changes: 22 additions & 0 deletions demos/react-native-supabase-group-chat/metro.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Learn more https://docs.expo.dev/guides/monorepos
const { getDefaultConfig } = require('expo/metro-config');
const path = require('node:path');

// Find the project and workspace directories
const projectRoot = __dirname;
const workspaceRoot = path.resolve(projectRoot, '../..');

const config = getDefaultConfig(projectRoot);

// 1. Watch all files within the monorepo
config.watchFolders = [workspaceRoot];
// 2. Let Metro know where to resolve packages and in what order
config.resolver.nodeModulesPaths = [
path.resolve(projectRoot, 'node_modules'),
path.resolve(workspaceRoot, 'node_modules')
];
// #3 - Force resolving nested modules to the folders below
config.resolver.disableHierarchicalLookup = true;
config.resolver.unstable_enableSymlinks = true;

module.exports = config;
77 changes: 77 additions & 0 deletions demos/react-native-supabase-group-chat/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
{
"name": "powerchat",
"version": "1.0.0",
"main": "expo-router/entry",
"scripts": {
"clear": "find ./ -type d -and \\( -name node_modules -or -name build -or -name dist \\) -exec rm -rf '{}' +",
"ncu": "pnpx npm-check-updates",
"dev": "expo start",
"android": "expo run:android",
"ios": "expo run:ios",
"web": "expo start --web --clear",
"doc": "pnpx expo-doctor@latest",
"prebuild": "expo prebuild --platform ios --clean --no-install",
"build:simulator": "pnpx eas-cli build --profile simulator --platform ios --local",
"build:development": "pnpx eas-cli build --profile development --platform ios --local",
"build:production": "pnpx eas-cli build --profile production --platform ios --local",
"update:production": "pnpx eas-cli update --non-interactive -p ios --branch=production --auto",
"types": "supabase gen types typescript --local > src/lib/database.types.ts",
"lint": "eslint src"
},
"dependencies": {
"@azure/core-asynciterator-polyfill": "^1.0.2",
"@faker-js/faker": "8.3.1",
"@journeyapps/powersync-sdk-react-native": "workspace:*",
"@journeyapps/powersync-sdk-common": "workspace:*",
"@journeyapps/powersync-react": "workspace:*",
"@journeyapps/react-native-quick-sqlite": "1.1.1",
"@react-native-async-storage/async-storage": "1.21.0",
"@shopify/flash-list": "1.6.3",
"@supabase/supabase-js": "2.39.0",
"@tamagui/animations-react-native": "1.79.6",
"@tamagui/babel-plugin": "1.79.6",
"@tamagui/config": "1.79.6",
"@tamagui/font-inter": "1.79.6",
"@tamagui/lucide-icons": "1.79.6",
"@tamagui/theme-base": "1.79.6",
"base-64": "^1.0.0",
"date-fns": "^2.30.0",
"expo": "~50.0.6",
"expo-crypto": "~12.8.0",
"expo-dev-client": "~3.3.8",
"expo-linking": "~6.2.2",
"expo-router": "^3.4.7",
"expo-splash-screen": "~0.26.4",
"expo-status-bar": "~1.11.1",
"metro": "~0.80.5",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-native": "0.73.4",
"react-native-fetch-api": "^3.0.0",
"react-native-gesture-handler": "~2.14.1",
"react-native-get-random-values": "~1.8.0",
"react-native-pager-view": "6.2.3",
"react-native-polyfill-globals": "^3.1.0",
"react-native-reanimated": "~3.6.2",
"react-native-safe-area-context": "4.8.2",
"react-native-screens": "~3.29.0",
"react-native-svg": "14.1.0",
"react-native-url-polyfill": "^2.0.0",
"react-native-web": "0.19.9",
"tamagui": "1.79.6",
"text-encoding": "^0.7.0",
"web-streams-polyfill": "^3.2.1"
},
"devDependencies": {
"@babel/core": "7.23.5",
"@babel/plugin-transform-async-generator-functions": "^7.23.4",
"@types/react": "^18.2.42",
"eas-cli": "^7.2.0",
"eslint": "8.55.0",
"eslint-config-universe": "12.0.0",
"prettier": "^3.1.0",
"typescript": "5.3.2"
},
"license": "UNLICENSED",
"private": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { usePowerSync } from "@journeyapps/powersync-sdk-react-native";
import { UserCog } from "@tamagui/lucide-icons";
import { Link, Stack, useLocalSearchParams } from "expo-router";
import { useEffect, useState } from "react";

import { Loading } from "@/components/loading/Loading";

export default function ChatsLayout() {
const { group: groupId } = useLocalSearchParams<{ group: string }>();
const powerSync = usePowerSync();
const [isInitialSyncCompleted, setIsInitialSyncCompleted] = useState(false);

async function checkForInitialSync() {
const initialSync = await powerSync.execute(
"SELECT name FROM ps_buckets WHERE last_applied_op > 0 LIMIT 1"
);
if (initialSync.rows?._array?.length) {
setIsInitialSyncCompleted(true);
} else {
setIsInitialSyncCompleted(false);

setTimeout(() => checkForInitialSync(), 100);
}
}

useEffect(() => {
checkForInitialSync();
}, []);

if (!isInitialSyncCompleted) {
return <Loading message="Syncing data" />;
}

return (
<Stack>
<Stack.Screen name="index" options={{ title: "Chats" }} />
<Stack.Screen name="c" options={{ title: "Contact" }} />
<Stack.Screen
name="g"
options={{
title: "Group",
headerRight: (props) => (
<Link href={`/(app)/(chats)/g/${groupId}/settings`}>
<UserCog size="$1.5" color={props.tintColor} />
</Link>
),
}}
/>
</Stack>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Stack } from "expo-router";

export default function ChatsContactLayout() {
return (
<>
<Stack>
<Stack.Screen name="index" options={{ headerShown: false }} />
</Stack>
</>
);
}
Loading

0 comments on commit b4cd43f

Please sign in to comment.