Skip to content

Commit

Permalink
Merge pull request #26 from Unshut-Labs/feat/xmtp-groups-dash
Browse files Browse the repository at this point in the history
feat: Groups, UX, Frames
  • Loading branch information
alexrisch authored Jul 25, 2024
2 parents 8647b29 + d72bd25 commit 923ca0e
Show file tree
Hide file tree
Showing 489 changed files with 21,368 additions and 11,556 deletions.
17 changes: 16 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,27 @@
{
"extends": "universe/native",
"ignorePatterns": ["dist/", "node_modules/", "vendor/"],
"plugins": ["react", "import", "unused-imports", "react-hooks"],
"plugins": ["react", "import", "unused-imports", "react-hooks", "react-native"],
"rules": {
"no-unused-vars": "off",
"unused-imports/no-unused-imports": "error",
"react-hooks/rules-of-hooks": "error",
"react-hooks/exhaustive-deps": "error",
"react-native/no-inline-styles": "warn",
"react-native/no-raw-text": "warn",
"react-native/no-single-element-style-arrays": "warn",
"react/jsx-no-bind": [
"warn",
{
"ignoreRefs": true,
"allowArrowFunctions": false,
"allowFunctions": false,
"allowBind": false,
"ignoreDOMComponents": true
}
],
"react/jsx-key": "error",

"prettier/prettier": "off" // We use prettier manually on the side
},
"root": true
Expand Down
25 changes: 25 additions & 0 deletions .github/workflows/typescript.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Typescript CI
on:
pull_request:
branches:
- main
- feat/xmtp-groups-dash
jobs:
tsc:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: actions/setup-node@v3
- run: yarn
- run: yarn typecheck
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 0
- uses: actions/setup-node@v3
- run: yarn
- run: yarn lint
3 changes: 0 additions & 3 deletions .gitmodules

This file was deleted.

80 changes: 39 additions & 41 deletions App.tsx
Original file line number Diff line number Diff line change
@@ -1,37 +1,39 @@
import "reflect-metadata";
import "./polyfills";

import { configure as configureCoinbase } from "@coinbase/wallet-mobile-sdk";
import { ActionSheetProvider } from "@expo/react-native-action-sheet";
import { PrivyProvider } from "@privy-io/expo";
import { Ethereum } from "@thirdweb-dev/chains";
import { coinbaseWallet, ThirdwebProvider } from "@thirdweb-dev/react-native";
import {
backgroundColor,
MaterialDarkTheme,
MaterialLightTheme,
} from "@styles/colors";
import { useCoinbaseWalletListener } from "@utils/coinbaseWallet";
import React, { useEffect } from "react";
import {
LogBox,
Platform,
StyleSheet,
useColorScheme,
View,
LogBox,
} from "react-native";
import "./utils/splash/splash";
import { KeyboardProvider } from "react-native-keyboard-controller";
import { Provider as PaperProvider } from "react-native-paper";
import { ThirdwebProvider } from "thirdweb/react";
import "./utils/splash/splash";

import XmtpEngine from "./components/XmtpEngine";
import config from "./config";
import { useAppStore } from "./data/store/appStore";
import { useSelect } from "./data/store/storeHelpers";
import {
updateLastVersionOpen,
runAsyncUpdates,
updateLastVersionOpen,
} from "./data/updates/asyncUpdates";
import { QueryClientProvider } from "./queries/QueryProvider";
import Main from "./screens/Main";
import { registerBackgroundFetchTask } from "./utils/background";
import {
backgroundColor,
MaterialDarkTheme,
MaterialLightTheme,
} from "./utils/colors";
import { privySecureStorage } from "./utils/keychain/helpers";
import mmkv from "./utils/mmkv";
import { DEFAULT_EMOJIS, RECENT_EMOJI_STORAGE_KEY } from "./utils/reactions";
Expand All @@ -55,6 +57,11 @@ export default function App() {
const colorScheme = useColorScheme();
const styles = useStyles();

useCoinbaseWalletListener(
true,
new URL(`https://${config.websiteDomain}/coinbase`)
);

useEffect(() => {
registerBackgroundFetchTask();
}, []);
Expand Down Expand Up @@ -86,37 +93,28 @@ export default function App() {
Platform.OS === "ios" ? KeyboardProvider : React.Fragment;

return (
<PrivyProvider appId={config.privy.appId} storage={privySecureStorage}>
<ThirdwebProvider
activeChain={Ethereum}
dAppMeta={{
...config.walletConnectConfig.dappMetadata,
isDarkMode: colorScheme === "dark",
}}
autoConnect={false}
clientId={config.thirdwebClientId}
supportedWallets={[
coinbaseWallet({
callbackURL: new URL(`https://${config.websiteDomain}/coinbase`),
}),
]}
>
<AppKeyboardProvider>
<ActionSheetProvider>
<PaperProvider
theme={
colorScheme === "light" ? MaterialLightTheme : MaterialDarkTheme
}
>
<View style={styles.safe}>
<XmtpEngine />
<Main />
</View>
</PaperProvider>
</ActionSheetProvider>
</AppKeyboardProvider>
</ThirdwebProvider>
</PrivyProvider>
<QueryClientProvider>
<PrivyProvider appId={config.privy.appId} storage={privySecureStorage}>
<ThirdwebProvider>
<AppKeyboardProvider>
<ActionSheetProvider>
<PaperProvider
theme={
colorScheme === "light"
? MaterialLightTheme
: MaterialDarkTheme
}
>
<View style={styles.safe}>
<XmtpEngine />
<Main />
</View>
</PaperProvider>
</ActionSheetProvider>
</AppKeyboardProvider>
</ThirdwebProvider>
</PrivyProvider>
</QueryClientProvider>
);
}

Expand Down
9 changes: 5 additions & 4 deletions App.web.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import "@expo/metro-runtime";
import "./polyfills";
import "./assets/web.css";
import { ActionSheetProvider } from "@expo/react-native-action-sheet";
import { PrivyProvider } from "@privy-io/react-auth";
import { createWeb3Modal, defaultConfig } from "@web3modal/ethers5/react";
import { useColorScheme } from "react-native";
import { PaperProvider } from "react-native-paper";
import { SafeAreaProvider } from "react-native-safe-area-context";
import "./assets/web.css";
import "./polyfills";

import { MaterialDarkTheme, MaterialLightTheme } from "@styles/colors";

import XmtpEngine from "./components/XmtpEngine";
import config from "./config";
import Main from "./screens/Main";
import { MaterialDarkTheme, MaterialLightTheme } from "./utils/colors";
import mmkv from "./utils/mmkv";
import { DEFAULT_EMOJIS, RECENT_EMOJI_STORAGE_KEY } from "./utils/reactions";
import { useRecentPicksPersistence } from "./vendor/rn-emoji-keyboard";
Expand All @@ -26,7 +27,7 @@ const mainnet = {

createWeb3Modal({
ethersConfig: defaultConfig({
metadata: config.walletConnectConfig.dappMetadata,
metadata: config.walletConnectConfig.appMetadata,
}),
chains: [mainnet],
projectId: config.walletConnectConfig.projectId,
Expand Down
80 changes: 80 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# Building the App - iOS

### Install JS/React Native Dependencies

```
yarn
```

### Install iOS Dependencies

```
npx pod-install
```

### Build the iOS App

Open ios/Converse.xcworkspace in Xcode and Build

# Building the App - Android

### Install JS/React Native Dependencies

```
yarn
```

### Install submodules for Android patched fork

```
git submodule update
```

### Build the Android App

Open Android Studio
press the top right gradle icon to sync gradle
Click the play/build button to build and install the app

### Forward backend port

if running the backend locally

```
adb reverse tcp:9875 tcp:9875
```

# Running the App

Once the app builds it will open the Expo App
this will ask what server port you are targetting, if none are found, you probably need to start the expo server

### Start Expo Server

```
yarn start
```

# Linting

```
yarn lint
```

# Testing

Before running the tests make sure that you have a `.env` file setup with the `DEV_API_URI` variable set

```sh
# In the `converse-backend` repo
yarn dev
# Back in this repo
yarn test
```


# Key Cases Needed for App Release

1. Old conversations are persisted
2. Can send a message without duplicates
3. Can create a group
1 change: 1 addition & 0 deletions android/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ build/
local.properties
*.iml
*.hprof
.cxx/

# Bundle artifacts
*.jsbundle
16 changes: 8 additions & 8 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,6 @@ android {
details.useTarget group: details.requested.group, name: 'lifecycle-viewmodel-ktx', version: '2.5.0'
}
}
resolutionStrategy.dependencySubstitution {
substitute(module("org.xmtp:android")).using(project(":libs:xmtp-android:library"))
}
}

}
Expand Down Expand Up @@ -159,11 +156,12 @@ android {
lint {
abortOnError false
}

packagingOptions {
// Should prevent clashes with other libraries that use OpenSSL
pickFirst '**/libcrypto.so'
jniLibs {
pickFirsts += ['**/libcrypto.so']
}
}

}

// Apply static values from `gradle.properties` to the `android.packagingOptions`
Expand Down Expand Up @@ -193,13 +191,16 @@ dependencies {
implementation 'com.google.firebase:firebase-messaging-ktx:23.0.3'
implementation 'com.beust:klaxon:5.5'
implementation 'androidx.security:security-crypto:1.1.0-alpha05'
// No need to precise a version as we're substituting for local version anyway
implementation "org.xmtp:android"
implementation 'org.web3j:crypto'
implementation 'com.google.crypto.tink:tink-android:1.7.0'
implementation 'com.android.volley:volley:1.2.1'
implementation 'com.tencent:mmkv:1.3.1'
implementation 'me.leolin:ShortcutBadger:1.1.22'
implementation "org.jetbrains.kotlin:kotlin-reflect:1.9.22"
implementation 'com.github.bumptech.glide:glide:4.13.2'
annotationProcessor 'com.github.bumptech.glide:compiler:4.13.2'



def isGifEnabled = (findProperty('expo.gif.enabled') ?: "") == "true";
Expand All @@ -223,7 +224,6 @@ dependencies {
implementation("androidx.core:core-splashscreen:1.0.0")
// implementation 'org.web3j:core:4.8.8-android'

implementation("com.facebook.react:flipper-integration")
if (hermesEnabled.toBoolean()) {
implementation("com.facebook.react:hermes-android")
} else {
Expand Down
8 changes: 7 additions & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
Expand All @@ -10,6 +10,12 @@
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
<uses-permission android:name="android.permission.USE_BIOMETRIC"/>
<!-- This forces minSdkVersion 23 for module reactnativeaesgcmcrypto even if the lib
has minSdkVersion 26. It could technically lead to failures but we don't care as it's
a dependency in thirdweb used only for inapp wallets which we don't care about -->
<uses-sdk
android:minSdkVersion="23"
tools:overrideLibrary="com.reactnativeaesgcmcrypto" />
<queries>
<package android:name="org.toshi"/>
<intent>
Expand Down
Binary file modified android/app/src/main/ic_launcher-playstore.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified android/app/src/main/ic_launcher_preview-playstore.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 8 additions & 2 deletions android/app/src/main/java/com/converse/dev/Datatypes.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,18 @@ package com.converse.dev

import kotlin.math.roundToInt

class NotificationData(val message: String, val timestampNs: String, val contentTopic: String, val sentViaConverse: Boolean? = false, val account: String)
class NotificationData(val message: String, val timestampNs: String, val contentTopic: String, val account: String)
class ConversationDictData(val shortAddress: String? = null, val title: String? = null)
class SavedNotificationMessage(val topic: String, val content: String, val senderAddress: String, val sent: Long, val id: String, val sentViaConverse: Boolean, val contentType: String, val account: String? = null, val referencedMessageId: String? = null)
class SavedNotificationMessage(val topic: String, val content: String, val senderAddress: String, val sent: Long, val id: String, val contentType: String, val account: String? = null, val referencedMessageId: String? = null)
class ConversationContext(val conversationId: String, val metadata: Map<String, Any>)
class Accounts(val currentAccount: String, val accounts: Array<String>, val databaseId: Map<String, String>? = null)
class AccountsStore(val state: Accounts, val version: Int)
class EnsName(val name: String, val displayName: String? = null, val isPrimary: Boolean? = false, val avatar: String? = null)
class ConverseUserName(val name: String, val displayName: String? = null, val isPrimary: Boolean? = false, val avatar: String? = null)
class ProfileSocials(val ensNames: Array<EnsName>? = null, val userNames: Array<ConverseUserName>? = null)
class Profile(val updatedAt: Long, val socials: ProfileSocials)
class Profiles(val profiles: Map<String, Profile>? = null)
class ProfilesStore(val state: Profiles, val version: Int)
class SavedNotificationConversation(val topic: String, val peerAddress: String, val createdAt: Long, val context: ConversationContext?, val account: String? = null, spamScore: Double?) {
// Whenever spamScore is set, round it to two decimal to ensure it fits as a 2-digit float in the database
var spamScore: Double? = spamScore
Expand Down
Loading

0 comments on commit 923ca0e

Please sign in to comment.