├── .watchmanconfig ├── .gitattributes ├── app.json ├── android ├── .settings │ └── org.eclipse.buildship.core.prefs ├── app │ ├── .settings │ │ └── org.eclipse.buildship.core.prefs │ ├── debug.keystore │ ├── src │ │ ├── main │ │ │ ├── assets │ │ │ │ └── fonts │ │ │ │ │ ├── Entypo.ttf │ │ │ │ │ ├── Feather.ttf │ │ │ │ │ ├── Zocial.ttf │ │ │ │ │ ├── AntDesign.ttf │ │ │ │ │ ├── EvilIcons.ttf │ │ │ │ │ ├── Fontisto.ttf │ │ │ │ │ ├── Foundation.ttf │ │ │ │ │ ├── Ionicons.ttf │ │ │ │ │ ├── Octicons.ttf │ │ │ │ │ ├── FontAwesome.ttf │ │ │ │ │ ├── MaterialIcons.ttf │ │ │ │ │ ├── SimpleLineIcons.ttf │ │ │ │ │ ├── SFProDisplay-Bold.ttf │ │ │ │ │ ├── FontAwesome5_Brands.ttf │ │ │ │ │ ├── FontAwesome5_Regular.ttf │ │ │ │ │ ├── FontAwesome5_Solid.ttf │ │ │ │ │ ├── SFProDisplay-Light.ttf │ │ │ │ │ ├── SFProDisplay-Regular.ttf │ │ │ │ │ └── MaterialCommunityIcons.ttf │ │ │ ├── res │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ ├── splash.png │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ ├── ic_launcher_round.png │ │ │ │ │ └── ic_notification.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ ├── splash.png │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ ├── ic_launcher_round.png │ │ │ │ │ └── ic_notification.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ ├── splash.png │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ ├── ic_notification.png │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ ├── splash.png │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ ├── ic_notification.png │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ ├── splash.png │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ ├── ic_notification.png │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── values │ │ │ │ │ ├── colors.xml │ │ │ │ │ ├── strings.xml │ │ │ │ │ └── styles.xml │ │ │ │ └── layout │ │ │ │ │ └── launch_screen.xml │ │ │ ├── java │ │ │ │ └── com │ │ │ │ │ └── proximity │ │ │ │ │ └── app │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ └── MainApplication.java │ │ │ └── AndroidManifest.xml │ │ └── debug │ │ │ └── AndroidManifest.xml │ ├── .classpath │ ├── proguard-rules.pro │ ├── .project │ ├── build_defs.bzl │ ├── google-services.json │ └── _BUCK ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── settings.gradle ├── .project ├── gradle.properties ├── build.gradle └── gradlew.bat ├── react-native.config.js ├── assets ├── images │ └── proximity-logo.png └── fonts │ ├── SFProDisplay-Bold.ttf │ ├── SFProDisplay-Light.ttf │ └── SFProDisplay-Regular.ttf ├── ios ├── Proximity │ ├── Images.xcassets │ │ ├── Contents.json │ │ ├── Splash.imageset │ │ │ ├── splash-1.png │ │ │ ├── splash-2.png │ │ │ ├── splash.png │ │ │ └── Contents.json │ │ └── AppIcon.appiconset │ │ │ ├── icon_20@2x.png │ │ │ ├── icon_20@3x.png │ │ │ ├── icon_29@2x.png │ │ │ ├── icon_29@3x.png │ │ │ ├── icon_40@2x.png │ │ │ ├── icon_40@3x.png │ │ │ ├── icon_60@2x.png │ │ │ ├── icon_60@3x.png │ │ │ ├── icon_1024@1x.png │ │ │ └── Contents.json │ ├── Proximity.entitlements │ ├── AppDelegate.h │ ├── main.m │ ├── Base.lproj │ │ └── LaunchScreen.xib │ ├── AppDelegate.m │ └── Info.plist ├── Proximity.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── Config.xcconfig ├── ProximityTests │ ├── Info.plist │ └── ProximityTests.m ├── Proximity-tvOSTests │ └── Info.plist ├── GoogleService-Info.plist ├── Proximity-tvOS │ └── Info.plist └── Podfile ├── jest.config.js ├── .buckconfig ├── .prettierrc.js ├── declarations.d.ts ├── index.js ├── __tests__ └── App-test.js ├── app ├── theme │ ├── index.ts │ └── Typography.ts ├── screens │ ├── ConversationScreen │ │ └── components │ │ │ ├── CustomScrollToBottom.tsx │ │ │ ├── ChatHeaderAvatar.tsx │ │ │ ├── CustomSend.tsx │ │ │ ├── CustomMessageText.tsx │ │ │ ├── CustomComposer.tsx │ │ │ ├── CustomInputToolbar.tsx │ │ │ └── CustomBubble.tsx │ ├── ExploreScreen │ │ ├── hooks │ │ │ ├── useDebounce.ts │ │ │ └── useExploreFeed.ts │ │ └── components │ │ │ ├── UserSearchResults.tsx │ │ │ ├── ExploreGrid.tsx │ │ │ └── ExplorePostCard.tsx │ ├── index.ts │ ├── ProfileViewScreen │ │ └── components │ │ │ └── ProfileOptionsBottomSheet.tsx │ ├── PostViewScreen │ │ └── components │ │ │ ├── Comments.tsx │ │ │ ├── LikeBounceAnimation.tsx │ │ │ ├── PostOptionsBottomSheet.tsx │ │ │ ├── EditPostBottomSheet.tsx │ │ │ ├── LikesBottomSheet.tsx │ │ │ ├── CommentCard.tsx │ │ │ └── CommentInput.tsx │ ├── NotificationScreen │ │ └── index.tsx │ ├── UploadScreen │ │ └── components │ │ │ └── UploadBanner.tsx │ ├── MessageScreen │ │ └── components │ │ │ └── NewMessageBottomSheet.tsx │ └── ProfileScreen │ │ └── components │ │ └── SettingsBottomSheet.tsx ├── layout │ ├── misc │ │ ├── LoadingIndicator.tsx │ │ ├── NativeImage.tsx │ │ ├── SvgBanner.tsx │ │ ├── ListEmptyComponent.tsx │ │ └── BounceView.tsx │ ├── placeholders │ │ ├── PlaceholderAnimation.tsx │ │ ├── ConversationScreen.Placeholder.tsx │ │ ├── PostCard.Placeholder.tsx │ │ ├── MessageScreen.Placeholder.tsx │ │ ├── NotificationScreen.Placeholder.tsx │ │ ├── Connections.Placeholder.tsx │ │ ├── SearchUsers.Placeholder.tsx │ │ ├── PostViewScreen.Placeholder.tsx │ │ └── ExploreScreen.Placeholder.tsx │ ├── headers │ │ ├── Header.tsx │ │ ├── BottomSheetHeader.tsx │ │ ├── SearchBar.tsx │ │ ├── HomeHeader.tsx │ │ ├── GoBackHeader.tsx │ │ └── AnimatedSearchBar.tsx │ ├── shared │ │ ├── PostThumbnail.tsx │ │ ├── DeleteCardRightActions.tsx │ │ ├── Option.tsx │ │ ├── UserCard.tsx │ │ ├── ConfirmationModal.tsx │ │ └── ConnectionsBottomSheet.tsx │ ├── controls │ │ ├── IconButton.tsx │ │ ├── Button.tsx │ │ └── FormInput.tsx │ └── index.ts ├── types │ ├── auth.ts │ ├── theme.ts │ ├── screens.ts │ └── constants.ts ├── navigation │ ├── Routes.ts │ ├── TabBarComponent │ │ ├── TabIcon.tsx │ │ └── index.tsx │ ├── Transition.ts │ └── index.tsx ├── utils │ ├── authentication.ts │ ├── storage.ts │ ├── notifications.ts │ └── firebase.ts ├── config │ └── index.ts ├── graphql │ ├── subscription │ │ └── index.ts │ └── client │ │ └── index.ts ├── context │ └── index.tsx └── constants │ └── index.ts ├── appcenter-pre-build.sh ├── metro.config.js ├── .eslintrc.js ├── tsconfig.json ├── babel.config.js ├── .gitignore ├── .flowconfig ├── App.tsx └── package.json /.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Proximity", 3 | "displayName": "Proximity" 4 | } -------------------------------------------------------------------------------- /android/.settings/org.eclipse.buildship.core.prefs: -------------------------------------------------------------------------------- 1 | connection.project.dir= 2 | eclipse.preferences.version=1 3 | -------------------------------------------------------------------------------- /android/app/.settings/org.eclipse.buildship.core.prefs: -------------------------------------------------------------------------------- 1 | connection.project.dir=.. 2 | eclipse.preferences.version=1 3 | -------------------------------------------------------------------------------- /android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/debug.keystore -------------------------------------------------------------------------------- /react-native.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | assets: ['react-native-vector-icons', './assets/fonts'] 3 | }; 4 | -------------------------------------------------------------------------------- /assets/images/proximity-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/assets/images/proximity-logo.png -------------------------------------------------------------------------------- /ios/Proximity/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /assets/fonts/SFProDisplay-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/assets/fonts/SFProDisplay-Bold.ttf -------------------------------------------------------------------------------- /assets/fonts/SFProDisplay-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/assets/fonts/SFProDisplay-Light.ttf -------------------------------------------------------------------------------- /assets/fonts/SFProDisplay-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/assets/fonts/SFProDisplay-Regular.ttf -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'react-native', 3 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], 4 | }; 5 | -------------------------------------------------------------------------------- /.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Entypo.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/assets/fonts/Entypo.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Feather.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/assets/fonts/Feather.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Zocial.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/assets/fonts/Zocial.ttf -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | bracketSpacing: false, 3 | jsxBracketSameLine: true, 4 | singleQuote: true, 5 | trailingComma: 'all', 6 | }; 7 | -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/AntDesign.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/assets/fonts/AntDesign.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/EvilIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/assets/fonts/EvilIcons.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Fontisto.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/assets/fonts/Fontisto.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Foundation.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/assets/fonts/Foundation.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Ionicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/assets/fonts/Ionicons.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Octicons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/assets/fonts/Octicons.ttf -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/res/mipmap-hdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/res/mipmap-mdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/res/mipmap-xhdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/FontAwesome.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/assets/fonts/FontAwesome.ttf -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/res/mipmap-xxhdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/res/mipmap-xxxhdpi/splash.png -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/MaterialIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/assets/fonts/MaterialIcons.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/SimpleLineIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/assets/fonts/SimpleLineIcons.ttf -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/SFProDisplay-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/assets/fonts/SFProDisplay-Bold.ttf -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/assets/fonts/FontAwesome5_Brands.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/assets/fonts/FontAwesome5_Regular.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/assets/fonts/FontAwesome5_Solid.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/SFProDisplay-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/assets/fonts/SFProDisplay-Light.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/SFProDisplay-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/assets/fonts/SFProDisplay-Regular.ttf -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/res/mipmap-hdpi/ic_notification.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/res/mipmap-mdpi/ic_notification.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_notification.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_notification.png -------------------------------------------------------------------------------- /android/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | #846BE2 3 | #FFFFFF 4 | 5 | -------------------------------------------------------------------------------- /ios/Proximity/Images.xcassets/Splash.imageset/splash-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/ios/Proximity/Images.xcassets/Splash.imageset/splash-1.png -------------------------------------------------------------------------------- /ios/Proximity/Images.xcassets/Splash.imageset/splash-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/ios/Proximity/Images.xcassets/Splash.imageset/splash-2.png -------------------------------------------------------------------------------- /ios/Proximity/Images.xcassets/Splash.imageset/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/ios/Proximity/Images.xcassets/Splash.imageset/splash.png -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/assets/fonts/MaterialCommunityIcons.ttf -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_notification.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /ios/Proximity/Images.xcassets/AppIcon.appiconset/icon_20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/ios/Proximity/Images.xcassets/AppIcon.appiconset/icon_20@2x.png -------------------------------------------------------------------------------- /ios/Proximity/Images.xcassets/AppIcon.appiconset/icon_20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/ios/Proximity/Images.xcassets/AppIcon.appiconset/icon_20@3x.png -------------------------------------------------------------------------------- /ios/Proximity/Images.xcassets/AppIcon.appiconset/icon_29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/ios/Proximity/Images.xcassets/AppIcon.appiconset/icon_29@2x.png -------------------------------------------------------------------------------- /ios/Proximity/Images.xcassets/AppIcon.appiconset/icon_29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/ios/Proximity/Images.xcassets/AppIcon.appiconset/icon_29@3x.png -------------------------------------------------------------------------------- /ios/Proximity/Images.xcassets/AppIcon.appiconset/icon_40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/ios/Proximity/Images.xcassets/AppIcon.appiconset/icon_40@2x.png -------------------------------------------------------------------------------- /ios/Proximity/Images.xcassets/AppIcon.appiconset/icon_40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/ios/Proximity/Images.xcassets/AppIcon.appiconset/icon_40@3x.png -------------------------------------------------------------------------------- /ios/Proximity/Images.xcassets/AppIcon.appiconset/icon_60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/ios/Proximity/Images.xcassets/AppIcon.appiconset/icon_60@2x.png -------------------------------------------------------------------------------- /ios/Proximity/Images.xcassets/AppIcon.appiconset/icon_60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/ios/Proximity/Images.xcassets/AppIcon.appiconset/icon_60@3x.png -------------------------------------------------------------------------------- /ios/Proximity/Images.xcassets/AppIcon.appiconset/icon_1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karanpratapsingh/Proximity/HEAD/ios/Proximity/Images.xcassets/AppIcon.appiconset/icon_1024@1x.png -------------------------------------------------------------------------------- /declarations.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.png'; 2 | declare module '*.svg' { 3 | import { SvgProps } from 'react-native-svg'; 4 | const content: React.StatelessComponent; 5 | export default content; 6 | } -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'Proximity' 2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 3 | include ':app' 4 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import 'react-native-gesture-handler'; 2 | import { AppRegistry } from 'react-native'; 3 | import App from './App'; 4 | import { name as appName } from './app.json'; 5 | 6 | AppRegistry.registerComponent(appName, () => App); 7 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Proximity 3 | 4 | DeploymentKey 5 | 6 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.5-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /__tests__/App-test.js: -------------------------------------------------------------------------------- 1 | import 'react-native'; 2 | import React from 'react'; 3 | import App from '../App'; 4 | 5 | // Note: test renderer must be required after react-native. 6 | import renderer from 'react-test-renderer'; 7 | 8 | it('renders correctly', () => { 9 | renderer.create(); 10 | }); 11 | -------------------------------------------------------------------------------- /ios/Proximity.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ios/Proximity.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /android/app/.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/theme/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Theme, 3 | ThemeStatic, 4 | ThemeVariant, 5 | MaterialColors, 6 | HandleAvailableColor, 7 | OnlineDotColor 8 | } from './Colors'; 9 | import Typography from './Typography'; 10 | 11 | export { 12 | Theme, 13 | ThemeStatic, 14 | ThemeVariant, 15 | MaterialColors, 16 | HandleAvailableColor, 17 | OnlineDotColor, 18 | Typography 19 | }; 20 | -------------------------------------------------------------------------------- /ios/Config.xcconfig: -------------------------------------------------------------------------------- 1 | // 2 | // Config.xcconfig 3 | // Proximity 4 | // 5 | // Created by Vertigo 101 on 30/11/19. 6 | // Copyright © 2019 Facebook. All rights reserved. 7 | // 8 | 9 | // Configuration settings file format documentation can be found at: 10 | // https://help.apple.com/xcode/#/dev745c5c974 11 | 12 | GOOGLE_REVERSED_CLIENT_ID=com.googleusercontent.apps.649469906394-cunn0sogttuea6fhvmekebm85h70rqeq 13 | -------------------------------------------------------------------------------- /ios/Proximity/Proximity.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | aps-environment 6 | development 7 | com.apple.developer.applesignin 8 | 9 | Default 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/screens/ConversationScreen/components/CustomScrollToBottom.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Entypo from 'react-native-vector-icons/Entypo'; 3 | import { IconSizes } from '@app/constants'; 4 | import { ThemeStatic } from '@app/theme'; 5 | 6 | const CustomScrollToBottom = () => ; 11 | 12 | export default CustomScrollToBottom; -------------------------------------------------------------------------------- /app/layout/misc/LoadingIndicator.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { DotIndicator } from 'react-native-indicators'; 3 | 4 | interface LoadingIndicatorProps { 5 | size: number, 6 | color?: string, 7 | count?: number 8 | }; 9 | 10 | const LoadingIndicator: React.FC = ({ size, color, count }) => 11 | ; 12 | 13 | export default LoadingIndicator; -------------------------------------------------------------------------------- /app/types/auth.ts: -------------------------------------------------------------------------------- 1 | export type GoogleAuthResult = { 2 | idToken: string | null; 3 | accessToken: string | undefined; 4 | }; 5 | 6 | export type AppleAuthResult = { 7 | identityToken: string | null; 8 | nonce: string; 9 | }; 10 | 11 | export enum SocialSignInType { 12 | GOOGLE, 13 | APPLE, 14 | } 15 | 16 | export type SocialSignInResult = { 17 | token: string; 18 | avatar: string | null; 19 | name: string; 20 | email: string; 21 | }; 22 | -------------------------------------------------------------------------------- /ios/Proximity/AppDelegate.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (nonatomic, strong) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ios/Proximity/main.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -------------------------------------------------------------------------------- /app/screens/ExploreScreen/hooks/useDebounce.ts: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from 'react'; 2 | 3 | export default function useDebounce(value: string, delay: number) { 4 | const [debouncedValue, setDebouncedValue] = useState(value); 5 | 6 | useEffect(() => { 7 | const handler = setTimeout(() => { 8 | setDebouncedValue(value); 9 | }, delay); 10 | 11 | return () => { 12 | clearTimeout(handler); 13 | }; 14 | }, [value]); 15 | 16 | return debouncedValue; 17 | } 18 | -------------------------------------------------------------------------------- /android/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | Proximity 4 | Project android created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.buildship.core.gradleprojectbuilder 10 | 11 | 12 | 13 | 14 | 15 | org.eclipse.buildship.core.gradleprojectnature 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/layout/misc/NativeImage.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { View } from 'react-native'; 3 | import FastImage from 'react-native-fast-image'; 4 | 5 | interface NativeImageProps { 6 | uri: string, 7 | style: any 8 | }; 9 | 10 | const NativeImage: React.FC = ({ uri, style }) => { 11 | 12 | if (!uri || !uri.includes('http')) return ; 13 | return 14 | }; 15 | 16 | export default NativeImage; -------------------------------------------------------------------------------- /ios/Proximity/Images.xcassets/Splash.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "splash.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "splash-1.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "splash-2.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /appcenter-pre-build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | node node_modules/jetifier/bin/jetify 4 | 5 | if [[ ! -z "$GOOGLE_SERVICES_JSON" ]]; then 6 | echo "$GOOGLE_SERVICES_JSON" | base64 --decode > android/app/google-services.json 7 | fi 8 | 9 | if [[ ! -z "$GOOGLE_SERVICES_PLIST" ]]; then 10 | echo "$GOOGLE_SERVICES_PLIST" | base64 --decode > ios/GoogleService-Info.plist 11 | echo "$XCCONFIG" | base64 --decode > ios/Config.xcconfig 12 | fi 13 | 14 | mkdir app/config 15 | echo "$APP_CONFIG" | base64 --decode > app/config/index.ts 16 | -------------------------------------------------------------------------------- /metro.config.js: -------------------------------------------------------------------------------- 1 | const { getDefaultConfig } = require('metro-config'); 2 | 3 | module.exports = (async () => { 4 | const { 5 | resolver: { sourceExts, assetExts } 6 | } = await getDefaultConfig(); 7 | return { 8 | transformer: { 9 | experimentalImportSupport: false, 10 | inlineRequires: false, 11 | babelTransformerPath: require.resolve('react-native-svg-transformer'), 12 | }, 13 | resolver: { 14 | assetExts: assetExts.filter(ext => ext !== 'svg'), 15 | sourceExts: [...sourceExts, 'svg'] 16 | } 17 | }; 18 | })(); 19 | -------------------------------------------------------------------------------- /app/navigation/Routes.ts: -------------------------------------------------------------------------------- 1 | import { 2 | HomeScreen, 3 | ExploreScreen, 4 | UploadScreen, 5 | NotificationScreen, 6 | ProfileScreen, 7 | ProfileViewScreen, 8 | MessageScreen, 9 | ConversationScreen, 10 | PostViewScreen, 11 | LoginScreen 12 | } from '@app/screens'; 13 | 14 | export const TabBarRoutes = { 15 | HomeScreen, 16 | ExploreScreen, 17 | UploadScreen, 18 | NotificationScreen, 19 | ProfileScreen 20 | }; 21 | 22 | export const StackRoutes = { 23 | MessageScreen, 24 | ConversationScreen, 25 | ProfileViewScreen, 26 | PostViewScreen, 27 | LoginScreen 28 | }; -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'parser': 'babel-eslint', 3 | 'env': { 4 | 'jest': true, 5 | }, 6 | 'parserOptions': { 7 | 'ecmaVersion': 7, 8 | 'sourceType': 'module', 9 | 'ecmaFeatures': { 10 | 'jsx': true, 11 | } 12 | }, 13 | 'rules': { 14 | 'no-use-before-define': 'off', 15 | 'react/jsx-filename-extension': 'off', 16 | 'react/prop-types': 'off', 17 | 'comma-dangle': 'off', 18 | 'quotes': ['error', 'single'], 19 | 'semi': ['error', 'always'], 20 | 'indent': ['error', 2] 21 | }, 22 | 'globals': { 23 | 'fetch': false 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /android/app/.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | app 4 | Project app created by Buildship. 5 | 6 | 7 | 8 | 9 | org.eclipse.jdt.core.javabuilder 10 | 11 | 12 | 13 | 14 | org.eclipse.buildship.core.gradleprojectbuilder 15 | 16 | 17 | 18 | 19 | 20 | org.eclipse.jdt.core.javanature 21 | org.eclipse.buildship.core.gradleprojectnature 22 | 23 | 24 | -------------------------------------------------------------------------------- /android/app/build_defs.bzl: -------------------------------------------------------------------------------- 1 | """Helper definitions to glob .aar and .jar targets""" 2 | 3 | def create_aar_targets(aarfiles): 4 | for aarfile in aarfiles: 5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] 6 | lib_deps.append(":" + name) 7 | android_prebuilt_aar( 8 | name = name, 9 | aar = aarfile, 10 | ) 11 | 12 | def create_jar_targets(jarfiles): 13 | for jarfile in jarfiles: 14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")] 15 | lib_deps.append(":" + name) 16 | prebuilt_jar( 17 | name = name, 18 | binary_jar = jarfile, 19 | ) 20 | -------------------------------------------------------------------------------- /app/layout/placeholders/PlaceholderAnimation.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { Shine, ShineOverlay } from 'rn-placeholder'; 3 | import { AppContext } from '@app/context'; 4 | import { ThemeVariant } from '@app/theme'; 5 | 6 | const AnimationBackground = { 7 | light: '#DFDFDF', 8 | dark: '#242424' 9 | }; 10 | 11 | const PlaceholderAnimation = props => { 12 | const { themeType } = useContext(AppContext); 13 | const backgroundColor = AnimationBackground[themeType]; 14 | 15 | if (themeType === ThemeVariant.light) { 16 | return ; 17 | } 18 | 19 | return ; 20 | }; 21 | 22 | export default PlaceholderAnimation; -------------------------------------------------------------------------------- /app/layout/placeholders/ConversationScreen.Placeholder.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, View } from 'react-native'; 3 | import { IconSizes } from '@app/constants'; 4 | import { ThemeStatic } from '@app/theme'; 5 | import LoadingIndicator from '../misc/LoadingIndicator'; 6 | 7 | const ConversationScreenPlaceholder = () => ( 8 | 9 | 10 | 11 | ); 12 | 13 | const styles = StyleSheet.create({ 14 | container: { 15 | flex: 1, 16 | paddingHorizontal: 10, 17 | alignItems: 'center', 18 | justifyContent: 'center' 19 | } 20 | }); 21 | 22 | export default ConversationScreenPlaceholder; -------------------------------------------------------------------------------- /android/app/src/main/res/layout/launch_screen.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 | 18 | -------------------------------------------------------------------------------- /app/screens/ConversationScreen/components/ChatHeaderAvatar.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet, TouchableOpacity } from 'react-native'; 3 | import { NativeImage } from '@app/layout'; 4 | 5 | const ChatHeaderAvatar = ({ avatar, onPress }) => ( 6 | 7 | 8 | 9 | ); 10 | 11 | const styles = StyleSheet.create({ 12 | container: { 13 | height: 36, 14 | width: 36, 15 | overflow: 'hidden', 16 | marginHorizontal: 10, 17 | borderRadius: 20 18 | }, 19 | avatarImage: { 20 | flex: 1 21 | } 22 | }); 23 | 24 | export default ChatHeaderAvatar; -------------------------------------------------------------------------------- /app/utils/authentication.ts: -------------------------------------------------------------------------------- 1 | import { messaging, crashlytics, auth } from './firebase'; 2 | import { StorageErrorTypes, removeToken } from './storage'; 3 | import { Errors } from '@app/constants'; 4 | 5 | export const handleLoginError = async (errorType: string) => { 6 | switch (errorType) { 7 | case StorageErrorTypes.Expired: 8 | await signOut(); 9 | break; 10 | 11 | case StorageErrorTypes.NotFound: 12 | break; 13 | 14 | default: 15 | break; 16 | } 17 | }; 18 | 19 | export const signOut = async () => { 20 | try { 21 | await messaging.deleteToken(); 22 | await removeToken(); 23 | await auth.signOut(); 24 | } catch ({ message }) { 25 | crashlytics.recordCustomError(Errors.SIGN_OUT, message); 26 | } 27 | }; -------------------------------------------------------------------------------- /app/screens/index.ts: -------------------------------------------------------------------------------- 1 | import HomeScreen from './HomeScreen'; 2 | import ExploreScreen from './ExploreScreen'; 3 | import UploadScreen from './UploadScreen'; 4 | import NotificationScreen from './NotificationScreen'; 5 | import ProfileScreen from './ProfileScreen'; 6 | import ProfileViewScreen from './ProfileViewScreen'; 7 | import MessageScreen from './MessageScreen'; 8 | import ConversationScreen from './ConversationScreen'; 9 | import PostViewScreen from './PostViewScreen'; 10 | import LoginScreen from './LoginScreen'; 11 | 12 | export { 13 | HomeScreen, 14 | ExploreScreen, 15 | UploadScreen, 16 | NotificationScreen, 17 | ProfileScreen, 18 | ProfileViewScreen, 19 | MessageScreen, 20 | ConversationScreen, 21 | PostViewScreen, 22 | LoginScreen 23 | }; -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowJs": true, 4 | "allowSyntheticDefaultImports": true, 5 | "esModuleInterop": true, 6 | "isolatedModules": true, 7 | "jsx": "react", 8 | "lib": [ 9 | "es6" 10 | ], 11 | "moduleResolution": "node", 12 | "noEmit": true, 13 | "strict": true, 14 | "target": "esnext", 15 | "baseUrl": ".", 16 | "noImplicitAny": false, 17 | "paths": { 18 | "*": [ 19 | "./app/*", 20 | ], 21 | "@app/*": [ 22 | "./app/*" 23 | ], 24 | "@app/assets/*": [ 25 | "./assets/*" 26 | ], 27 | }, 28 | }, 29 | "exclude": [ 30 | "node_modules", 31 | "babel.config.js", 32 | "metro.config.js", 33 | "jest.config.js" 34 | ] 35 | } -------------------------------------------------------------------------------- /app/screens/ConversationScreen/components/CustomSend.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet } from 'react-native'; 3 | import { Send } from 'react-native-gifted-chat'; 4 | import FontAwesome from 'react-native-vector-icons/FontAwesome'; 5 | import { IconSizes } from '@app/constants'; 6 | import { ThemeStatic } from '@app/theme'; 7 | 8 | const CustomSend: React.FC = sendProps => ( 9 | 12 | 17 | 18 | ); 19 | 20 | const styles = StyleSheet.create({ 21 | container: { 22 | alignItems: 'center', 23 | justifyContent: 'center', 24 | paddingHorizontal: 20 25 | } 26 | }); 27 | 28 | export default CustomSend; -------------------------------------------------------------------------------- /ios/ProximityTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/screens/ConversationScreen/components/CustomMessageText.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet } from 'react-native'; 3 | import { MessageText } from 'react-native-gifted-chat'; 4 | import { Typography, ThemeStatic } from '@app/theme'; 5 | 6 | const { FontWeights, FontSizes } = Typography; 7 | 8 | const CustomMessageText: React.FC = messageTextProps => ( 9 | 16 | ); 17 | 18 | const styles = StyleSheet.create({ 19 | left: { 20 | ...FontWeights.Light, 21 | ...FontSizes.Body, 22 | color: ThemeStatic.black 23 | }, 24 | right: { 25 | ...FontWeights.Light, 26 | ...FontSizes.Body, 27 | color: ThemeStatic.white 28 | } 29 | }); 30 | 31 | export default CustomMessageText; -------------------------------------------------------------------------------- /ios/Proximity-tvOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/theme/Typography.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Typography: 3 | * This contains all the typography config for the application 4 | * #Note: color and font size are defaulted as they can be overridden 5 | * as required. 6 | */ 7 | 8 | const FontWeights = { 9 | Bold: { 10 | fontFamily: 'SFProDisplay-Bold', 11 | color: '#000' 12 | }, 13 | Regular: { 14 | fontFamily: 'SFProDisplay-Regular', 15 | color: '#000' 16 | }, 17 | Light: { 18 | fontFamily: 'SFProDisplay-Light', 19 | color: '#000' 20 | } 21 | }; 22 | 23 | const FontSizes = { 24 | Heading: { 25 | fontSize: 32 26 | }, 27 | SubHeading: { 28 | fontSize: 24 29 | }, 30 | Label: { 31 | fontSize: 20 32 | }, 33 | Body: { 34 | fontSize: 16 35 | }, 36 | Caption: { 37 | fontSize: 14 38 | } 39 | }; 40 | 41 | const Typography = { FontWeights, FontSizes }; 42 | 43 | export default Typography; 44 | -------------------------------------------------------------------------------- /app/config/index.ts: -------------------------------------------------------------------------------- 1 | import { Platform } from 'react-native'; 2 | 3 | const { 4 | author: { 5 | name, 6 | email, 7 | url 8 | }, 9 | repository: { 10 | url: repository 11 | }, 12 | version 13 | } = require('../../package.json'); 14 | 15 | const codepush = { 16 | staging: Platform.select({ 17 | ios: '', 18 | android: '' 19 | }), 20 | production: Platform.select({ 21 | ios: '', 22 | android: '' 23 | }) 24 | }; 25 | 26 | const webClientId: string = '649469906394-0d9hghf2jv5n9n0t0o763e5bheer720f.apps.googleusercontent.com'; 27 | 28 | const Config = { 29 | author: { name, email, url }, 30 | repository, 31 | version, 32 | codepush, 33 | url: { 34 | https: 'https://proximity-development.herokuapp.com/', 35 | wss: 'wss://proximity-development.herokuapp.com/', 36 | }, 37 | webClientId 38 | }; 39 | 40 | export default Config; 41 | -------------------------------------------------------------------------------- /app/screens/ConversationScreen/components/CustomComposer.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { StyleSheet, Platform } from 'react-native'; 3 | import { Composer } from 'react-native-gifted-chat'; 4 | import { AppContext } from '@app/context'; 5 | import { Typography } from '@app/theme'; 6 | import { ThemeColors } from '@app/types/theme'; 7 | 8 | const { FontWeights, FontSizes } = Typography; 9 | 10 | const CustomComposer: React.FC = composerProps => { 11 | const { theme } = useContext(AppContext); 12 | return ( 13 | 18 | ); 19 | }; 20 | 21 | const styles = (theme = {} as ThemeColors) => StyleSheet.create({ 22 | inputStyle: { 23 | ...FontWeights.Light, 24 | ...FontSizes.Body, 25 | color: theme.text01, 26 | paddingTop: 10, 27 | paddingLeft: 10 28 | } 29 | }); 30 | 31 | export default CustomComposer; -------------------------------------------------------------------------------- /app/screens/ConversationScreen/components/CustomInputToolbar.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet } from 'react-native'; 3 | import { InputToolbar } from 'react-native-gifted-chat'; 4 | import { ThemeStatic } from '@app/theme'; 5 | 6 | const CustomInputToolbar: React.FC = inputToolbarProps => ( 7 | 12 | ); 13 | 14 | const styles = StyleSheet.create({ 15 | container: { 16 | height: 40, 17 | alignItems: 'center', 18 | justifyContent: 'center', 19 | borderTopWidth: 0, 20 | marginBottom: 10, 21 | backgroundColor: 'transparent' 22 | }, 23 | primary: { 24 | alignItems: 'center', 25 | justifyContent: 'center', 26 | borderRadius: 40, 27 | marginHorizontal: 10, 28 | borderWidth: StyleSheet.hairlineWidth, 29 | borderColor: ThemeStatic.text02 30 | } 31 | }); 32 | 33 | export default CustomInputToolbar; -------------------------------------------------------------------------------- /android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | android.useAndroidX=true 21 | android.enableJetifier=true 22 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | plugins: [ 4 | [ 5 | 'module-resolver', 6 | { 7 | root: ['.'], 8 | extensions: [ 9 | '.ios.ts', 10 | '.android.ts', 11 | '.ts', 12 | '.ios.tsx', 13 | '.android.tsx', 14 | '.tsx', 15 | '.jsx', 16 | '.js', 17 | '.json', 18 | ], 19 | alias: { 20 | '@app/config': './app/config', 21 | '@app/context': './app/context', 22 | '@app/graphql': './app/graphql', 23 | '@app/constants': './app/constants', 24 | '@app/layout': './app/layout', 25 | '@app/navigation': './app/navigation', 26 | '@app/screens': './app/screens', 27 | '@app/theme': './app/theme', 28 | '@app/types': './app/types', 29 | '@app/utils': './app/utils', 30 | '@app/assets': './assets', 31 | }, 32 | }, 33 | ], 34 | ], 35 | }; 36 | -------------------------------------------------------------------------------- /app/types/theme.ts: -------------------------------------------------------------------------------- 1 | import { StatusBarStyle } from 'react-native'; 2 | 3 | export type ThemeStaticType = { 4 | accent: string, 5 | white: string, 6 | black: string, 7 | text01: string, 8 | text02: string, 9 | placeholder: string, 10 | like: string, 11 | unlike: string, 12 | translucent: string, 13 | delete: string, 14 | badge: string 15 | }; 16 | 17 | export type ThemeColors = { 18 | accent: string, 19 | base: string, 20 | text01: string, 21 | text02: string, 22 | placeholder: string, 23 | white: string 24 | }; 25 | 26 | export type ThemeVariantType = { 27 | light: string, 28 | dark: string 29 | }; 30 | 31 | export type ThemeType = { 32 | type: string, 33 | colors: ThemeColors 34 | }; 35 | 36 | export type HandleAvailableColorType = { 37 | true: string, 38 | false: string 39 | }; 40 | 41 | export type OnlineDotColorType = { 42 | true: string, 43 | false: string 44 | }; 45 | 46 | export type DynamicStatusBarType = { 47 | [key: string]: { 48 | barStyle: StatusBarStyle, 49 | backgroundColor: string 50 | } 51 | }; -------------------------------------------------------------------------------- /app/layout/headers/Header.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { StyleSheet, Text, View } from 'react-native'; 3 | import { Typography } from '@app/theme'; 4 | import { AppContext } from '@app/context'; 5 | import { ThemeColors } from '@app/types/theme'; 6 | 7 | const { FontWeights, FontSizes } = Typography; 8 | 9 | interface HeaderProps { 10 | title: string, 11 | IconRight?: React.FC 12 | }; 13 | 14 | const Header: React.FC = ({ title, IconRight }) => { 15 | 16 | const { theme } = useContext(AppContext); 17 | return ( 18 | 19 | {title} 20 | {IconRight && } 21 | 22 | ); 23 | }; 24 | 25 | const styles = (theme = {} as ThemeColors) => StyleSheet.create({ 26 | container: { 27 | flexDirection: 'row', 28 | alignItems: 'center', 29 | justifyContent: 'space-between', 30 | paddingVertical: 10, 31 | paddingHorizontal: 20 32 | }, 33 | title: { 34 | ...FontWeights.Bold, 35 | ...FontSizes.Heading, 36 | color: theme.text01 37 | } 38 | }); 39 | 40 | export default Header; -------------------------------------------------------------------------------- /app/layout/headers/BottomSheetHeader.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { View, Text, StyleSheet } from 'react-native'; 3 | import { AppContext } from '@app/context'; 4 | import { ThemeColors } from '@app/types/theme'; 5 | import { Typography } from '@app/theme'; 6 | 7 | const { FontWeights, FontSizes } = Typography; 8 | 9 | interface BottomSheetHeaderProps { 10 | heading: string, 11 | subHeading: string 12 | }; 13 | 14 | const BottomSheetHeader: React.FC = ({ heading, subHeading }) => { 15 | const { theme } = useContext(AppContext); 16 | return ( 17 | 18 | {heading} 19 | {subHeading} 20 | 21 | ); 22 | }; 23 | 24 | const styles = (theme = {} as ThemeColors) => StyleSheet.create({ 25 | container: {}, 26 | heading: { 27 | ...FontWeights.Bold, 28 | ...FontSizes.Label, 29 | color: theme.text01 30 | }, 31 | subHeading: { 32 | ...FontWeights.Regular, 33 | ...FontSizes.Body, 34 | marginTop: 2, 35 | color: theme.text02 36 | } 37 | }); 38 | 39 | export default BottomSheetHeader; -------------------------------------------------------------------------------- /app/screens/ExploreScreen/hooks/useExploreFeed.ts: -------------------------------------------------------------------------------- 1 | import { useQuery } from '@apollo/react-hooks'; 2 | 3 | import { QUERY_POSTS } from '@app/graphql/query'; 4 | import { Pagination } from '@app/constants'; 5 | 6 | export default function useExploreFeed(userId: string) { 7 | const defaultInput = { 8 | userId, 9 | last: Pagination.PAGE_SIZE, 10 | }; 11 | 12 | const { 13 | data: postsData, 14 | loading: postsLoading, 15 | error: postsError, 16 | fetchMore, 17 | refetch: refetchPosts, 18 | } = useQuery(QUERY_POSTS, { 19 | variables: defaultInput, 20 | }); 21 | 22 | const fetchMorePosts = async () => { 23 | const { posts } = postsData; 24 | const variables = { 25 | ...defaultInput, 26 | last: posts.length + Pagination.CURSOR_SIZE, 27 | }; 28 | 29 | const updateQuery = (prev, { fetchMoreResult }) => { 30 | if (!fetchMoreResult) return prev; 31 | 32 | return { posts: [...fetchMoreResult.posts] }; 33 | }; 34 | 35 | if (fetchMore) { 36 | // @ts-ignore 37 | fetchMore({ variables, updateQuery }); 38 | } 39 | }; 40 | 41 | return { postsData, postsLoading, postsError, fetchMorePosts, refetchPosts }; 42 | } 43 | -------------------------------------------------------------------------------- /app/layout/placeholders/PostCard.Placeholder.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { StyleSheet, View } from 'react-native'; 3 | import { Placeholder, PlaceholderLine } from 'rn-placeholder'; 4 | import PlaceholderAnimation from './PlaceholderAnimation'; 5 | import { AppContext } from '@app/context'; 6 | import { PostDimensions } from '@app/constants'; 7 | 8 | const PostCardPlaceholder = () => { 9 | const { theme } = useContext(AppContext); 10 | 11 | return ( 12 | 13 | 14 | {new Array(4) 15 | .fill({}) 16 | .map((_, index) => 17 | 24 | )} 25 | 26 | 27 | ); 28 | }; 29 | 30 | const styles = StyleSheet.create({ 31 | container: { 32 | paddingTop: 2, 33 | paddingHorizontal: 20 34 | }, 35 | card: { 36 | marginTop: 20, 37 | borderRadius: 10 38 | } 39 | }); 40 | 41 | export default PostCardPlaceholder; -------------------------------------------------------------------------------- /app/utils/storage.ts: -------------------------------------------------------------------------------- 1 | import Storage from 'react-native-storage'; 2 | import AsyncStorage from '@react-native-community/async-storage'; 3 | 4 | const storage = new Storage({ 5 | size: 1000, 6 | storageBackend: AsyncStorage, 7 | defaultExpires: 7 * 1000 * 3600 * 24, // 7 days, eg: 1 day (1000 * 3600 * 24 milliseconds) 8 | enableCache: true 9 | }); 10 | 11 | export const StorageErrorTypes = { 12 | Expired: 'ExpiredError', 13 | NotFound: 'NotFoundError' 14 | }; 15 | 16 | export const saveToken = (token: string) => { 17 | return storage.save({ 18 | key: 'proximity:token', 19 | data: token 20 | }); 21 | }; 22 | 23 | export const loadToken = () => { 24 | return storage.load({ 25 | key: 'proximity:token' 26 | }); 27 | }; 28 | 29 | export const removeToken = () => { 30 | return storage.remove({ 31 | key: 'proximity:token' 32 | }); 33 | }; 34 | 35 | export const saveThemeType = (themeType: string) => { 36 | return storage.save({ 37 | key: 'proximity:theme', 38 | data: themeType, 39 | expires: null // never expires until changed 40 | }); 41 | }; 42 | 43 | export const loadThemeType = () => { 44 | return storage.load({ 45 | key: 'proximity:theme' 46 | }); 47 | }; 48 | 49 | export default storage; 50 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | 24 | # Android/IntelliJ 25 | # 26 | build/ 27 | .idea 28 | .gradle 29 | local.properties 30 | *.iml 31 | 32 | # node.js 33 | # 34 | node_modules/ 35 | npm-debug.log 36 | yarn-error.log 37 | 38 | # BUCK 39 | buck-out/ 40 | \.buckd/ 41 | *.keystore 42 | !debug.keystore 43 | 44 | # fastlane 45 | # 46 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 47 | # screenshots whenever they are needed. 48 | # For more information about the recommended setup visit: 49 | # https://docs.fastlane.tools/best-practices/source-control/ 50 | 51 | */fastlane/report.xml 52 | */fastlane/Preview.html 53 | */fastlane/screenshots 54 | 55 | # Bundle artifact 56 | *.jsbundle 57 | 58 | # CocoaPods 59 | /ios/Pods/ 60 | 61 | # Firebase 62 | # /android/app/google-services.json 63 | # /ios/GoogleService-Info.plist 64 | 65 | # Config 66 | # /ios/Config.xcconfig 67 | 68 | # App 69 | # /app/config/index.ts -------------------------------------------------------------------------------- /app/screens/ConversationScreen/components/CustomBubble.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleSheet } from 'react-native'; 3 | import { Bubble } from 'react-native-gifted-chat'; 4 | import { ThemeStatic } from '@app/theme'; 5 | import posed, { Transition } from 'react-native-pose'; 6 | 7 | const TransitionBubble = posed.View({ 8 | enter: { opacity: 1, x: 0 }, 9 | exit: { opacity: 0.5, x: ({ offset }) => offset } 10 | }); 11 | 12 | const CustomBubble: React.FC = bubbleProps => { 13 | // @ts-ignore 14 | const { user: { _id: authorId }, currentMessage: { user: { _id: currentId } } } = bubbleProps; 15 | 16 | const offset = authorId === currentId ? 20 : -20; 17 | 18 | return ( 19 | 20 | 21 | 26 | 27 | 28 | ); 29 | }; 30 | 31 | const styles = StyleSheet.create({ 32 | container: { 33 | flex: 1 34 | }, 35 | right: { 36 | marginVertical: 4, 37 | backgroundColor: ThemeStatic.accent 38 | } 39 | }); 40 | 41 | export default CustomBubble; -------------------------------------------------------------------------------- /android/app/src/main/java/com/proximity/app/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.proximity.app; 2 | 3 | import android.os.Bundle; 4 | import com.facebook.react.ReactActivity; 5 | import com.facebook.react.ReactActivityDelegate; 6 | import com.facebook.react.ReactRootView; 7 | import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView; 8 | 9 | import org.devio.rn.splashscreen.SplashScreen; 10 | 11 | public class MainActivity extends ReactActivity { 12 | 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) { 15 | SplashScreen.show(this); 16 | super.onCreate(savedInstanceState); 17 | } 18 | 19 | /** 20 | * Returns the name of the main component registered from JavaScript. This is 21 | * used to schedule rendering of the component. 22 | */ 23 | @Override 24 | protected String getMainComponentName() { 25 | return "Proximity"; 26 | } 27 | 28 | @Override 29 | protected ReactActivityDelegate createReactActivityDelegate() { 30 | return new ReactActivityDelegate(this, getMainComponentName()) { 31 | @Override 32 | protected ReactRootView createRootView() { 33 | return new RNGestureHandlerEnabledRootView(MainActivity.this); 34 | } 35 | }; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/navigation/TabBarComponent/TabIcon.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import AntDesign from 'react-native-vector-icons/AntDesign'; 3 | import Entypo from 'react-native-vector-icons/Entypo'; 4 | import Feather from 'react-native-vector-icons/Feather'; 5 | import { IconSizes } from '@app/constants'; 6 | import { AppContext } from '@app/context'; 7 | 8 | const TabIcon = ({ route, isActive }) => { 9 | const { theme } = useContext(AppContext); 10 | 11 | switch (route) { 12 | case 'HomeScreen': 13 | 14 | return ; 15 | 16 | case 'ExploreScreen': 17 | 18 | return ; 19 | 20 | case 'UploadScreen': 21 | 22 | return ; 23 | 24 | case 'NotificationScreen': 25 | 26 | return ; 27 | 28 | case 'ProfileScreen': 29 | 30 | return ; 31 | 32 | default: 33 | return null; 34 | }; 35 | }; 36 | 37 | export default TabIcon; -------------------------------------------------------------------------------- /app/layout/misc/SvgBanner.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { StyleProp, StyleSheet, Text, TextStyle, View } from 'react-native'; 3 | import { responsiveHeight } from 'react-native-responsive-dimensions'; 4 | import { AppContext } from '@app/context'; 5 | import { Typography } from '@app/theme'; 6 | import { ThemeColors } from '@app/types/theme'; 7 | 8 | const { FontWeights, FontSizes } = Typography; 9 | 10 | interface SvgBannerProps { 11 | Svg: any, 12 | placeholder: string, 13 | spacing?: number, 14 | textStyle?: StyleProp 15 | }; 16 | 17 | const SvgBanner: React.FC = ({ Svg, placeholder, spacing, textStyle }) => { 18 | const { theme } = useContext(AppContext); 19 | 20 | return ( 21 | 22 | 23 | {placeholder} 24 | 25 | ); 26 | }; 27 | 28 | const styles = (theme = {} as ThemeColors) => StyleSheet.create({ 29 | container: { 30 | alignItems: 'center', 31 | justifyContent: 'center', 32 | marginHorizontal: 10 33 | }, 34 | placeholderText: { 35 | ...FontWeights.Light, 36 | ...FontSizes.Label, 37 | color: theme.text02, 38 | marginTop: 40 39 | } 40 | }); 41 | 42 | export default SvgBanner; -------------------------------------------------------------------------------- /app/graphql/subscription/index.ts: -------------------------------------------------------------------------------- 1 | import gql from 'graphql-tag'; 2 | 3 | export const SUBSCRIPTION_CHAT = gql` 4 | subscription Chat($chatId: String!) { 5 | chat(chatId: $chatId) { 6 | messages(last: 40) { 7 | id 8 | body 9 | createdAt 10 | author { 11 | id 12 | name 13 | avatar 14 | } 15 | } 16 | } 17 | } 18 | `; 19 | 20 | export const SUBSCRIPTION_POST = gql` 21 | subscription Post($postId: String!) { 22 | post(postId: $postId) { 23 | author { 24 | id 25 | handle 26 | avatar 27 | } 28 | comments { 29 | id 30 | body 31 | author { 32 | id 33 | avatar 34 | handle 35 | } 36 | createdAt 37 | } 38 | uri 39 | likes 40 | caption 41 | createdAt 42 | } 43 | } 44 | `; 45 | 46 | // Legacy 47 | // export const SUBSCRIPTION_USER = gql` 48 | // subscription User($userId: String!) { 49 | // user(userId: $userId) { 50 | // id 51 | // avatar 52 | // name 53 | // handle 54 | // about 55 | // following { 56 | // id 57 | // } 58 | // followers { 59 | // id 60 | // } 61 | // posts { 62 | // id 63 | // uri 64 | // } 65 | // } 66 | // } 67 | // `; -------------------------------------------------------------------------------- /app/navigation/TabBarComponent/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { View, TouchableOpacity, StyleSheet } from 'react-native'; 3 | import { ThemeColors } from '@app/types/theme'; 4 | import TabIcon from './TabIcon'; 5 | import { TabBarRoutes } from '../Routes'; 6 | import { AppContext } from '@app/context'; 7 | 8 | const TabBarComponent = ({ navigation, ...data }) => { 9 | const { theme } = useContext(AppContext); 10 | const currentRouteName = navigation.state.routes[navigation.state.index].key; 11 | return ( 12 | 13 | {Object.keys(TabBarRoutes).map(key => ( 14 | navigation.navigate(key)}> 15 | 16 | 17 | ))} 18 | 19 | ); 20 | }; 21 | 22 | const styles = (theme = {} as ThemeColors) => StyleSheet.create({ 23 | container: { 24 | flexDirection: 'row', 25 | alignItems: 'center', 26 | justifyContent: 'space-between', 27 | paddingVertical: 12, 28 | paddingHorizontal: 10, 29 | backgroundColor: theme.base 30 | }, 31 | icon: { 32 | flex: 1, 33 | alignItems: 'center', 34 | justifyContent: 'center' 35 | } 36 | }); 37 | 38 | export default TabBarComponent; -------------------------------------------------------------------------------- /ios/GoogleService-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CLIENT_ID 6 | 649469906394-cunn0sogttuea6fhvmekebm85h70rqeq.apps.googleusercontent.com 7 | REVERSED_CLIENT_ID 8 | com.googleusercontent.apps.649469906394-cunn0sogttuea6fhvmekebm85h70rqeq 9 | API_KEY 10 | AIzaSyBUDLaueKfWfkbhgxTDOFMDuSh-ReUAxjU 11 | GCM_SENDER_ID 12 | 649469906394 13 | PLIST_VERSION 14 | 1 15 | BUNDLE_ID 16 | com.proximity.app 17 | PROJECT_ID 18 | proximity-developement 19 | STORAGE_BUCKET 20 | proximity-developement.appspot.com 21 | IS_ADS_ENABLED 22 | 23 | IS_ANALYTICS_ENABLED 24 | 25 | IS_APPINVITE_ENABLED 26 | 27 | IS_GCM_ENABLED 28 | 29 | IS_SIGNIN_ENABLED 30 | 31 | GOOGLE_APP_ID 32 | 1:649469906394:ios:13504c0882dfc87c30c4e3 33 | DATABASE_URL 34 | https://proximity-developement.firebaseio.com 35 | 36 | -------------------------------------------------------------------------------- /app/layout/shared/PostThumbnail.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { StyleSheet, TouchableOpacity } from 'react-native'; 3 | import { useNavigation } from 'react-navigation-hooks'; 4 | import { Routes } from '@app/constants'; 5 | import { AppContext } from '@app/context'; 6 | import { ThemeColors } from '@app/types/theme'; 7 | import { Dimensions } from '@app/types/constants'; 8 | import NativeImage from '../misc/NativeImage'; 9 | 10 | interface PostThumbnailProps { 11 | id: string, 12 | uri: string, 13 | dimensions: Dimensions 14 | }; 15 | 16 | const PostThumbnail: React.FC = ({ id, uri, dimensions }) => { 17 | const { theme } = useContext(AppContext); 18 | const { navigate } = useNavigation(); 19 | 20 | const navigateToPost = () => navigate(Routes.PostViewScreen, { postId: id }); 21 | 22 | return ( 23 | 24 | 25 | 26 | ); 27 | }; 28 | 29 | const styles = (theme = {} as ThemeColors) => StyleSheet.create({ 30 | container: { 31 | backgroundColor: theme.placeholder, 32 | overflow: 'hidden', 33 | borderRadius: 5 34 | }, 35 | thumbnailImage: { 36 | flex: 1 37 | } 38 | }); 39 | 40 | export default PostThumbnail; -------------------------------------------------------------------------------- /app/layout/controls/IconButton.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { StyleProp, StyleSheet, Text, TouchableOpacity, View, ViewStyle } from 'react-native'; 3 | import { ThemeStatic, Typography } from '@app/theme'; 4 | 5 | const { FontWeights, FontSizes } = Typography; 6 | 7 | interface IconButtonProps { 8 | Icon: React.FC, 9 | onPress: () => void, 10 | style?: StyleProp, 11 | hasBadge?: boolean 12 | badgeCount?: number 13 | }; 14 | 15 | const IconButton: React.FC = ({ Icon, onPress, style, hasBadge, badgeCount }) => ( 16 | 17 | 18 | {hasBadge && 19 | {badgeCount} 20 | } 21 | 22 | ); 23 | 24 | const styles = StyleSheet.create({ 25 | container: { 26 | alignItems: 'flex-end', 27 | width: 40 28 | }, 29 | badge: { 30 | position: 'absolute', 31 | height: 20, 32 | width: 20, 33 | alignItems: 'center', 34 | justifyContent: 'center', 35 | top: -10, 36 | right: -10, 37 | borderRadius: 20, 38 | backgroundColor: ThemeStatic.badge 39 | }, 40 | badgeText: { 41 | ...FontWeights.Regular, 42 | ...FontSizes.Caption, 43 | color: ThemeStatic.white 44 | } 45 | }); 46 | 47 | export default IconButton; -------------------------------------------------------------------------------- /app/graphql/client/index.ts: -------------------------------------------------------------------------------- 1 | import { InMemoryCache } from 'apollo-cache-inmemory'; 2 | import ApolloClient from 'apollo-client'; 3 | import { ApolloLink, split } from 'apollo-link'; 4 | import { onError } from 'apollo-link-error'; 5 | import { HttpLink } from 'apollo-link-http'; 6 | import { WebSocketLink } from 'apollo-link-ws'; 7 | import { getMainDefinition } from 'apollo-utilities'; 8 | import Config from '@app/config'; 9 | 10 | const httpLink = new HttpLink({ uri: Config.url.https }); 11 | 12 | const wsLink = new WebSocketLink({ 13 | uri: Config.url.wss, 14 | options: { reconnect: true } 15 | }); 16 | 17 | const link = split( 18 | ({ query }) => { 19 | const definition = getMainDefinition(query); 20 | return ( 21 | definition.kind === 'OperationDefinition' && 22 | definition.operation === 'subscription' 23 | ); 24 | }, 25 | wsLink, 26 | httpLink, 27 | ); 28 | 29 | const client = new ApolloClient({ 30 | link: ApolloLink.from([ 31 | onError(({ graphQLErrors, networkError }) => { 32 | if (graphQLErrors) 33 | graphQLErrors.forEach(({ message, locations, path }) => 34 | console.log( 35 | `[GraphQL error]: Message: ${message}, Location: ${locations}, Path: ${path}`, 36 | ), 37 | ); 38 | if (networkError) console.log(`[Network error]: ${networkError}`); 39 | }), 40 | link 41 | ]), 42 | cache: new InMemoryCache() 43 | }); 44 | 45 | export default client; 46 | -------------------------------------------------------------------------------- /app/layout/headers/SearchBar.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { Platform, StyleSheet, TextInput } from 'react-native'; 3 | import { AppContext } from '@app/context'; 4 | import { Typography } from '@app/theme'; 5 | import { ThemeColors } from '@app/types/theme'; 6 | 7 | const { FontWeights, FontSizes } = Typography; 8 | 9 | interface SearchBarProps { 10 | value: string, 11 | onChangeText: any, 12 | onFocus?: any, 13 | onBlur?: any, 14 | placeholder: string, 15 | style?: object 16 | }; 17 | 18 | const SearchBar: React.FC = ({ value, onChangeText, onFocus, onBlur, placeholder, style }) => { 19 | const { theme } = useContext(AppContext); 20 | 21 | return ( 22 | 31 | ); 32 | }; 33 | 34 | const styles = (theme = {} as ThemeColors) => StyleSheet.create({ 35 | container: { 36 | ...FontWeights.Light, 37 | ...FontSizes.Body, 38 | width: '90%', 39 | alignSelf: 'center', 40 | paddingVertical: Platform.select({ ios: 10, android: 5 }), 41 | paddingHorizontal: 20, 42 | backgroundColor: theme.placeholder, 43 | color: theme.text01, 44 | borderRadius: 20, 45 | marginVertical: 5 46 | } 47 | }); 48 | 49 | export default SearchBar; -------------------------------------------------------------------------------- /ios/Proximity/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "icon_20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "icon_20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "icon_29@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "icon_29@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "icon_40@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "icon_40@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "icon_60@2x.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "icon_60@3x.png", 49 | "scale" : "3x" 50 | }, 51 | { 52 | "size" : "1024x1024", 53 | "idiom" : "ios-marketing", 54 | "filename" : "icon_1024@1x.png", 55 | "scale" : "1x" 56 | } 57 | ], 58 | "info" : { 59 | "version" : 1, 60 | "author" : "xcode" 61 | } 62 | } -------------------------------------------------------------------------------- /app/layout/shared/DeleteCardRightActions.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Animated, StyleSheet, StyleProp, ViewStyle } from 'react-native'; 3 | import MaterialIcons from 'react-native-vector-icons/MaterialIcons'; 4 | import { IconSizes } from '@app/constants'; 5 | import { ThemeStatic } from '@app/theme'; 6 | 7 | interface DeleteCardRightActionsProps { 8 | progress: any, 9 | dragX: any, 10 | onDelete: () => void, 11 | style?: StyleProp 12 | }; 13 | 14 | const DeleteCardRightActions: React.FC = ({ progress, dragX, onDelete, style }) => { 15 | const translateX = dragX.interpolate({ 16 | inputRange: [0, 80, 100, 101], 17 | outputRange: [-10, 0, 0, 1] 18 | }); 19 | 20 | const slideEffect = { opacity: progress, transform: [{ translateX }] }; 21 | 22 | return ( 23 | 24 | 31 | 32 | ); 33 | }; 34 | 35 | const styles = StyleSheet.create({ 36 | container: { 37 | width: 80, 38 | alignItems: 'center', 39 | justifyContent: 'center', 40 | backgroundColor: ThemeStatic.delete, 41 | borderTopRightRadius: 5, 42 | borderBottomRightRadius: 5 43 | }, 44 | delete: { 45 | width: 50, 46 | textAlign: 'center' 47 | } 48 | }); 49 | 50 | export default DeleteCardRightActions; -------------------------------------------------------------------------------- /android/app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "649469906394", 4 | "firebase_url": "https://proximity-developement.firebaseio.com", 5 | "project_id": "proximity-developement", 6 | "storage_bucket": "proximity-developement.appspot.com" 7 | }, 8 | "client": [ 9 | { 10 | "client_info": { 11 | "mobilesdk_app_id": "1:649469906394:android:c134c41d6e0cc61330c4e3", 12 | "android_client_info": { 13 | "package_name": "com.proximity.app" 14 | } 15 | }, 16 | "oauth_client": [ 17 | { 18 | "client_id": "649469906394-0d9hghf2jv5n9n0t0o763e5bheer720f.apps.googleusercontent.com", 19 | "client_type": 3 20 | } 21 | ], 22 | "api_key": [ 23 | { 24 | "current_key": "AIzaSyBlJ_2T901-PkDvy0_upe7rocbPjewmjbc" 25 | } 26 | ], 27 | "services": { 28 | "appinvite_service": { 29 | "other_platform_oauth_client": [ 30 | { 31 | "client_id": "649469906394-0d9hghf2jv5n9n0t0o763e5bheer720f.apps.googleusercontent.com", 32 | "client_type": 3 33 | }, 34 | { 35 | "client_id": "649469906394-cunn0sogttuea6fhvmekebm85h70rqeq.apps.googleusercontent.com", 36 | "client_type": 2, 37 | "ios_info": { 38 | "bundle_id": "com.proximity.app" 39 | } 40 | } 41 | ] 42 | } 43 | } 44 | } 45 | ], 46 | "configuration_version": "1" 47 | } -------------------------------------------------------------------------------- /android/app/_BUCK: -------------------------------------------------------------------------------- 1 | # To learn about Buck see [Docs](https://buckbuild.com/). 2 | # To run your application with Buck: 3 | # - install Buck 4 | # - `npm start` - to start the packager 5 | # - `cd android` 6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` 7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck 8 | # - `buck install -r android/app` - compile, install and run application 9 | # 10 | 11 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets") 12 | 13 | lib_deps = [] 14 | 15 | create_aar_targets(glob(["libs/*.aar"])) 16 | 17 | create_jar_targets(glob(["libs/*.jar"])) 18 | 19 | android_library( 20 | name = "all-libs", 21 | exported_deps = lib_deps, 22 | ) 23 | 24 | android_library( 25 | name = "app-code", 26 | srcs = glob([ 27 | "src/main/java/**/*.java", 28 | ]), 29 | deps = [ 30 | ":all-libs", 31 | ":build_config", 32 | ":res", 33 | ], 34 | ) 35 | 36 | android_build_config( 37 | name = "build_config", 38 | package = "com.boilerplate", 39 | ) 40 | 41 | android_resource( 42 | name = "res", 43 | package = "com.boilerplate", 44 | res = "src/main/res", 45 | ) 46 | 47 | android_binary( 48 | name = "app", 49 | keystore = "//android/keystores:debug", 50 | manifest = "src/main/AndroidManifest.xml", 51 | package_type = "debug", 52 | deps = [ 53 | ":app-code", 54 | ], 55 | ) 56 | -------------------------------------------------------------------------------- /app/layout/headers/HomeHeader.tsx: -------------------------------------------------------------------------------- 1 | import dateFormat from 'dateformat'; 2 | import React, { useContext } from 'react'; 3 | import { Platform, StyleSheet, Text, View } from 'react-native'; 4 | import { AppContext } from '@app/context'; 5 | import { Typography } from '@app/theme'; 6 | import { ThemeColors } from '@app/types/theme'; 7 | 8 | const { FontWeights, FontSizes } = Typography; 9 | 10 | interface HomeHeaderProps { 11 | IconRight?: React.FC 12 | }; 13 | 14 | const HomeHeader: React.FC = ({ IconRight }) => { 15 | 16 | const { theme } = useContext(AppContext); 17 | const weekdayNow = dateFormat(new Date(), 'dddd'); 18 | return ( 19 | 20 | 21 | PROXIMITY 22 | {weekdayNow} 23 | 24 | {IconRight && } 25 | 26 | ); 27 | }; 28 | 29 | const styles = (theme = {} as ThemeColors) => StyleSheet.create({ 30 | container: { 31 | flexDirection: 'row', 32 | alignItems: 'center', 33 | justifyContent: 'space-between', 34 | paddingVertical: 10, 35 | paddingHorizontal: 20 36 | }, 37 | topTitle: { 38 | ...FontWeights.Light, 39 | ...FontSizes.Caption, 40 | color: theme.text02, 41 | letterSpacing: 4 42 | }, 43 | title: { 44 | ...FontWeights.Light, 45 | ...FontSizes.Heading, 46 | marginTop: Platform.select({ ios: 2, android: 0 }), 47 | color: theme.text01 48 | } 49 | }); 50 | 51 | export default HomeHeader; -------------------------------------------------------------------------------- /app/layout/misc/ListEmptyComponent.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { View, Text, StyleSheet, StyleProp, TextStyle, ViewStyle } from 'react-native'; 3 | import { AppContext } from '@app/context'; 4 | import { ThemeColors } from '@app/types/theme'; 5 | import { Typography } from '@app/theme'; 6 | import { responsiveHeight } from 'react-native-responsive-dimensions'; 7 | 8 | const { FontWeights, FontSizes } = Typography; 9 | 10 | interface ListEmptyComponentProps { 11 | listType?: string, 12 | spacing: number, 13 | style?: StyleProp, 14 | placeholder?: string, 15 | placeholderStyle?: StyleProp 16 | }; 17 | 18 | const ListEmptyComponent: React.FC = ({ listType, spacing, style, placeholder, placeholderStyle }) => { 19 | const { theme } = useContext(AppContext); 20 | let content = `No ${listType} yet`; 21 | if (placeholder) { 22 | content = placeholder; 23 | } 24 | 25 | return ( 26 | 27 | {content} 28 | 29 | ); 30 | }; 31 | 32 | const styles = (theme = {} as ThemeColors) => StyleSheet.create({ 33 | container: { 34 | flex: 1, 35 | alignItems: 'center', 36 | justifyContent: 'center', 37 | marginHorizontal: 10 38 | }, 39 | placeholderText: { 40 | ...FontWeights.Light, 41 | ...FontSizes.Label, 42 | color: theme.text02 43 | } 44 | }); 45 | 46 | export default ListEmptyComponent; -------------------------------------------------------------------------------- /app/screens/ExploreScreen/components/UserSearchResults.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { StyleSheet } from 'react-native'; 3 | import { responsiveWidth } from 'react-native-responsive-dimensions'; 4 | import { FlatGrid } from 'react-native-super-grid'; 5 | import { ListEmptyComponent } from '@app/layout'; 6 | import { UserCard } from '@app/layout'; 7 | import { AppContext } from '@app/context'; 8 | import { SearchResult } from '@app/types/screens'; 9 | 10 | interface UserSearchResultsProps { 11 | searchResults: SearchResult[] 12 | }; 13 | 14 | const UserSearchResults: React.FC = ({ searchResults }) => { 15 | const { user } = useContext(AppContext); 16 | 17 | const filteredSearchResults = [...searchResults].filter(result => result.id !== user.id); 18 | 19 | const renderItem = ({ item }) => { 20 | const { id, avatar, handle, name } = item; 21 | return ( 22 | 28 | ); 29 | }; 30 | 31 | return ( 32 | } 37 | style={styles.container} 38 | spacing={20} 39 | renderItem={renderItem} 40 | /> 41 | ); 42 | }; 43 | 44 | const styles = StyleSheet.create({ 45 | container: { 46 | flex: 1, 47 | width: responsiveWidth(100) 48 | } 49 | }); 50 | 51 | export default UserSearchResults; -------------------------------------------------------------------------------- /app/layout/controls/Button.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { TouchableOpacity, Text, StyleSheet, StyleProp, ViewStyle, TextStyle } from 'react-native'; 3 | import LoadingIndicator from '../misc/LoadingIndicator'; 4 | import { ThemeStatic, Typography } from '@app/theme'; 5 | 6 | const { FontWeights, FontSizes } = Typography; 7 | 8 | interface ButtonProps { 9 | Icon?: React.FC, 10 | label: string, 11 | onPress: any, 12 | loading: boolean, 13 | containerStyle?: StyleProp, 14 | labelStyle?: StyleProp, 15 | indicatorColor?: string 16 | }; 17 | 18 | const Button: React.FC = ({ Icon, label, onPress, loading, containerStyle, labelStyle, indicatorColor }) => { 19 | 20 | let content = ; 21 | if (!loading) content = ( 22 | <> 23 | {Icon && } 24 | {label} 25 | 26 | ); 27 | 28 | return ( 29 | 30 | {content} 31 | 32 | ); 33 | }; 34 | 35 | const styles = StyleSheet.create({ 36 | container: { 37 | height: 40, 38 | width: '100%', 39 | flexDirection: 'row', 40 | alignItems: 'center', 41 | justifyContent: 'center', 42 | paddingVertical: 10, 43 | borderRadius: 40, 44 | backgroundColor: ThemeStatic.accent 45 | }, 46 | label: { 47 | ...FontWeights.Light, 48 | ...FontSizes.Body, 49 | marginLeft: 5, 50 | color: ThemeStatic.white 51 | } 52 | }); 53 | 54 | export default Button; -------------------------------------------------------------------------------- /app/types/screens.ts: -------------------------------------------------------------------------------- 1 | import { NotificationTextType } from './constants'; 2 | 3 | // Profile Screen 4 | 5 | export type Connection = { 6 | id: string, 7 | avatar: string, 8 | name: string, 9 | handle: string 10 | } 11 | 12 | // Notification Screen 13 | 14 | export type ActionUser = { 15 | id: string, 16 | avatar: string, 17 | handle: string 18 | }; 19 | 20 | export type Notification = { 21 | actionUser: ActionUser, 22 | type: keyof NotificationTextType, 23 | createdAt: string 24 | }; 25 | 26 | // Post View Screen 27 | 28 | export type Author = { 29 | id: string, 30 | avatar: string, 31 | handle: string 32 | }; 33 | 34 | export type Comment = { 35 | author: Author, 36 | body: string, 37 | createdAt: string 38 | }; 39 | 40 | export type PostViewType = { 41 | author: Author, 42 | comments: Comment[], 43 | uri: string, 44 | likes: string, 45 | caption: string, 46 | createdAt: string 47 | }; 48 | 49 | // Explore Screen 50 | 51 | export type ExplorePost = { 52 | id: string, 53 | uri: string 54 | }; 55 | 56 | export type SearchResult = { 57 | id: string, 58 | avatar: string, 59 | name: string, 60 | handle: string 61 | }; 62 | 63 | // Message Screen 64 | 65 | export type Participant = { 66 | id: string, 67 | avatar: string, 68 | handle: string, 69 | }; 70 | 71 | export type MessageAuthor = { 72 | id: string 73 | }; 74 | 75 | export type Message = { 76 | id: string, 77 | body: string, 78 | seen: boolean, 79 | author: MessageAuthor, 80 | createdAt: string 81 | }; 82 | 83 | export type Chat = { 84 | id: string, 85 | participants: Participant[], 86 | messages: Message[] 87 | }; 88 | -------------------------------------------------------------------------------- /app/layout/shared/Option.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'; 3 | import Ionicons from 'react-native-vector-icons/Ionicons'; 4 | import { IconSizes } from '@app/constants'; 5 | import { AppContext } from '@app/context'; 6 | import { Typography } from '@app/theme'; 7 | import { ThemeColors } from '@app/types/theme'; 8 | 9 | const { FontWeights, FontSizes } = Typography; 10 | 11 | interface OptionProps { 12 | label?: string, 13 | iconName: string, 14 | onPress?: () => void, 15 | children?: any, 16 | color?: string 17 | }; 18 | 19 | const Option: React.FC = ({ label, iconName, onPress, children, color }) => { 20 | const { theme } = useContext(AppContext); 21 | 22 | if (children) 23 | return ( 24 | 25 | 26 | {children} 27 | 28 | ); 29 | 30 | return ( 31 | 32 | 33 | {label} 34 | 35 | ); 36 | }; 37 | 38 | const styles = (theme = {} as ThemeColors) => StyleSheet.create({ 39 | container: { 40 | flexDirection: 'row', 41 | alignItems: 'center', 42 | marginVertical: 8 43 | }, 44 | label: { 45 | ...FontWeights.Light, 46 | ...FontSizes.Body, 47 | marginLeft: 10 48 | } 49 | }); 50 | 51 | export default Option; -------------------------------------------------------------------------------- /app/screens/ProfileViewScreen/components/ProfileOptionsBottomSheet.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { StyleSheet, View } from 'react-native'; 3 | import { Modalize } from 'react-native-modalize'; 4 | import { AppContext } from '@app/context'; 5 | import { BottomSheetHeader, Option } from '@app/layout'; 6 | import { ThemeStatic } from '@app/theme'; 7 | import { ThemeColors } from '@app/types/theme'; 8 | 9 | interface ProfileOptionsBottomSheetProps { 10 | ref: React.Ref, 11 | onBlockUser: () => void 12 | }; 13 | 14 | const ProfileOptionsBottomSheet: React.FC = React.forwardRef(({ onBlockUser }, ref) => { 15 | 16 | const { theme } = useContext(AppContext); 17 | 18 | return ( 19 | 25 | 29 | 30 | 37 | 38 | ); 39 | }); 40 | 41 | const styles = (theme = {} as ThemeColors) => StyleSheet.create({ 42 | container: { 43 | padding: 20, 44 | backgroundColor: theme.base 45 | }, 46 | content: { 47 | flex: 1, 48 | paddingTop: 20, 49 | paddingBottom: 16 50 | } 51 | }); 52 | 53 | export default ProfileOptionsBottomSheet; -------------------------------------------------------------------------------- /app/navigation/Transition.ts: -------------------------------------------------------------------------------- 1 | import { Animated, Easing, I18nManager } from 'react-native'; 2 | 3 | function forInitial(props) { 4 | 5 | const { navigation, scene } = props; 6 | 7 | const focused = navigation.state.index === scene.index; 8 | const opacity = focused ? 1 : 0; 9 | const translate = focused ? 0 : 1000000; 10 | return { 11 | opacity, 12 | transform: [{ translateX: translate }, { translateY: translate }], 13 | }; 14 | }; 15 | 16 | function forHorizontal(props) { 17 | 18 | const { layout, position, scene } = props; 19 | 20 | if (!layout.isMeasured) { 21 | return forInitial(props); 22 | } 23 | 24 | const index = scene.index; 25 | const inputRange = [index - 1, index, index + 1]; 26 | 27 | const width = layout.initWidth; 28 | const outputRange = I18nManager.isRTL 29 | ? [-width, 0, width * 0.3] 30 | : [width, 0, width * -0.3]; 31 | 32 | const opacity = position.interpolate({ 33 | inputRange: [ 34 | index - 1, 35 | index - 0.99, 36 | index, 37 | index + 0.99, 38 | index + 1, 39 | ], 40 | outputRange: [0, 1, 1, 0.3, 0], 41 | }); 42 | 43 | const translateY = 0; 44 | const translateX = position.interpolate({ 45 | inputRange, 46 | outputRange, 47 | }); 48 | 49 | return { 50 | opacity, 51 | transform: [{ translateX }, { translateY }], 52 | }; 53 | }; 54 | 55 | export default function getSlideFromRightTransitionConfig() { 56 | return { 57 | transitionSpec: { 58 | duration: 400, 59 | easing: Easing.out(Easing.poly(4)), 60 | timing: Animated.timing, 61 | useNativeDriver: true 62 | }, 63 | screenInterpolator: forHorizontal, 64 | }; 65 | }; -------------------------------------------------------------------------------- /app/context/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, createContext, } from 'react'; 2 | import { Theme } from '@app/theme'; 3 | import { ThemeColors } from '@app/types/theme'; 4 | import { saveThemeType } from '@app/utils/storage'; 5 | 6 | type UserType = { 7 | id: string, 8 | avatar: string, 9 | handle: string 10 | }; 11 | 12 | type AppContextType = { 13 | user: UserType, 14 | updateUser: (user: UserType) => void 15 | theme: ThemeColors, 16 | themeType: string, 17 | toggleTheme: (type: string) => void, 18 | unreadMessages: number, 19 | updateUnreadMessages: (count: number) => void, 20 | }; 21 | 22 | export const AppContext = createContext({} as AppContextType); 23 | 24 | export const AppContextProvider = props => { 25 | const [user, setUser] = useState({ 26 | id: '', 27 | avatar: '', 28 | handle: '' 29 | }); 30 | const [theme, setTheme] = useState(Theme.light.colors); 31 | const [themeType, setThemeType] = useState(Theme.light.type); 32 | const [unreadMessages, setUnreadMessages] = useState(0); 33 | 34 | const updateUser = (user: UserType) => { 35 | setUser(user); 36 | }; 37 | 38 | const toggleTheme = (type: string) => { 39 | setTheme(Theme[type].colors); 40 | setThemeType(type); 41 | saveThemeType(type); 42 | }; 43 | 44 | const updateUnreadMessages = (count: number) => { 45 | setUnreadMessages(count); 46 | }; 47 | 48 | const value = { 49 | user, 50 | updateUser, 51 | theme, 52 | themeType, 53 | toggleTheme, 54 | unreadMessages, 55 | updateUnreadMessages 56 | }; 57 | 58 | return ( 59 | 60 | {props.children} 61 | 62 | ); 63 | }; -------------------------------------------------------------------------------- /android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext { 5 | buildToolsVersion = "28.0.3" 6 | minSdkVersion = 16 7 | compileSdkVersion = 28 8 | targetSdkVersion = 28 9 | supportLibVersion = "28.0.0" 10 | googlePlayServicesAuthVersion = "16.0.1" 11 | } 12 | repositories { 13 | google() 14 | jcenter() 15 | // Firebase Crashlytics 16 | maven { 17 | url 'https://maven.fabric.io/public' 18 | } 19 | } 20 | dependencies { 21 | classpath("com.android.tools.build:gradle:3.4.2") 22 | 23 | classpath 'com.google.gms:google-services:4.2.0' 24 | // Firebase Crashlytics [CUSTOM] 25 | classpath 'io.fabric.tools:gradle:1.28.1' 26 | // NOTE: Do not place your application dependencies here; they belong 27 | // in the individual module build.gradle files 28 | } 29 | } 30 | 31 | allprojects { 32 | repositories { 33 | mavenLocal() 34 | google() 35 | maven { 36 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 37 | url("$rootDir/../node_modules/react-native/android") 38 | } 39 | maven { 40 | // Android JSC is installed from npm 41 | url("$rootDir/../node_modules/jsc-android/dist") 42 | } 43 | 44 | google() 45 | jcenter() 46 | maven { url 'https://jitpack.io' } 47 | 48 | // react-native-image-crop-picker [CUSTOM] 49 | maven { url 'https://maven.google.com' } 50 | maven { url "https://www.jitpack.io" } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /ios/Proximity-tvOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSExceptionDomains 28 | 29 | localhost 30 | 31 | NSExceptionAllowsInsecureHTTPLoads 32 | 33 | 34 | 35 | 36 | NSLocationWhenInUseUsageDescription 37 | 38 | UILaunchStoryboardName 39 | LaunchScreen 40 | UIRequiredDeviceCapabilities 41 | 42 | armv7 43 | 44 | UISupportedInterfaceOrientations 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationLandscapeLeft 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | UIViewControllerBasedStatusBarAppearance 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /app/layout/placeholders/MessageScreen.Placeholder.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { StyleSheet, View } from 'react-native'; 3 | import { Placeholder, PlaceholderLine, PlaceholderMedia } from 'rn-placeholder'; 4 | import PlaceholderAnimation from './PlaceholderAnimation'; 5 | import { AppContext } from '@app/context'; 6 | 7 | const MessageScreenPlaceholder: React.FC = () => { 8 | const { theme } = useContext(AppContext); 9 | 10 | return ( 11 | 12 | 13 | {new Array(20) 14 | .fill({}) 15 | .map((_, index) => 16 | 17 | 18 | 19 | 25 | 31 | 32 | 33 | )} 34 | 35 | 36 | ); 37 | }; 38 | 39 | const styles = StyleSheet.create({ 40 | container: { 41 | flex: 1, 42 | padding: 20, 43 | paddingBottom: 0 44 | }, 45 | cardContainer: { 46 | flexDirection: 'row', 47 | marginBottom: 20 48 | }, 49 | infoContainer: { 50 | flex: 1, 51 | paddingLeft: 10 52 | }, 53 | userChatPlaceholder: { 54 | borderRadius: 10, 55 | marginTop: 10 56 | } 57 | }); 58 | 59 | export default MessageScreenPlaceholder; -------------------------------------------------------------------------------- /app/layout/headers/GoBackHeader.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { StyleSheet, Text, View, StyleProp, TextProps, TextStyle } from 'react-native'; 3 | import { Typography } from '@app/theme'; 4 | import { AppContext } from '@app/context'; 5 | import { ThemeColors } from '@app/types/theme'; 6 | import Entypo from 'react-native-vector-icons/Entypo'; 7 | import { useNavigation } from 'react-navigation-hooks'; 8 | 9 | const { FontWeights, FontSizes } = Typography; 10 | 11 | interface GoBackHeaderProps { 12 | title?: string, 13 | onTitlePress?: () => void, 14 | ContentLeft?: React.FC, 15 | IconRight?: React.FC, 16 | iconSize: number, 17 | titleStyle?: StyleProp 18 | }; 19 | 20 | const GoBackHeader: React.FC = ({ title, onTitlePress, ContentLeft, IconRight, iconSize, titleStyle }) => { 21 | 22 | const { theme } = useContext(AppContext); 23 | const { goBack } = useNavigation(); 24 | const navigateBack = () => goBack(); 25 | 26 | return ( 27 | 28 | 29 | {ContentLeft && } 30 | {title && {title}} 31 | {IconRight && } 32 | 33 | ); 34 | }; 35 | 36 | const styles = (theme = {} as ThemeColors) => StyleSheet.create({ 37 | container: { 38 | flexDirection: 'row', 39 | alignItems: 'center', 40 | padding: 10 41 | }, 42 | title: { 43 | ...FontWeights.Bold, 44 | ...FontSizes.Label, 45 | color: theme.text01, 46 | marginLeft: 20 47 | }, 48 | underline: { 49 | marginTop: 16, 50 | height: 2, 51 | width: 20, 52 | borderRadius: 10, 53 | backgroundColor: theme.text01 54 | } 55 | }); 56 | 57 | export default GoBackHeader; -------------------------------------------------------------------------------- /app/layout/controls/FormInput.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { StyleSheet } from 'react-native'; 3 | import { TextField } from 'react-native-material-textfield'; 4 | import { AppContext } from '@app/context'; 5 | import { ThemeColors } from '@app/types/theme'; 6 | import { Typography } from '@app/theme'; 7 | 8 | const { FontWeights, FontSizes } = Typography; 9 | 10 | interface FormInputProps { 11 | ref: React.Ref, 12 | label: string, 13 | placeholder: string, 14 | value: string, 15 | onChangeText: any, 16 | multiline?: boolean, 17 | characterRestriction?: number, 18 | children?: any, 19 | error?: string 20 | }; 21 | 22 | const FormInput: React.FC = React.forwardRef(({ label, placeholder, value, onChangeText, children, multiline, characterRestriction, error }, ref) => { 23 | const { theme } = useContext(AppContext); 24 | return ( 25 | children} 45 | /> 46 | ); 47 | }); 48 | 49 | const styles = (theme = {} as ThemeColors) => StyleSheet.create({ 50 | labelTextStyle: { 51 | ...FontWeights.Regular 52 | }, 53 | textStyle: { 54 | ...FontWeights.Light, 55 | color: theme.text01 56 | } 57 | }); 58 | 59 | export default FormInput; -------------------------------------------------------------------------------- /app/layout/placeholders/NotificationScreen.Placeholder.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { StyleSheet, View } from 'react-native'; 3 | import { Placeholder, PlaceholderLine, PlaceholderMedia } from 'rn-placeholder'; 4 | import PlaceholderAnimation from './PlaceholderAnimation'; 5 | import { AppContext } from '@app/context'; 6 | 7 | const NotificationScreenPlaceholder: React.FC = () => { 8 | 9 | const { theme } = useContext(AppContext); 10 | 11 | return ( 12 | 13 | 14 | {new Array(20) 15 | .fill({}) 16 | .map((_, index) => 17 | 18 | 19 | 20 | 26 | 32 | 33 | 34 | )} 35 | 36 | 37 | ); 38 | }; 39 | 40 | const styles = StyleSheet.create({ 41 | container: { 42 | flex: 1, 43 | padding: 20, 44 | paddingBottom: 0 45 | }, 46 | cardContainer: { 47 | flexDirection: 'row', 48 | marginBottom: 20 49 | }, 50 | infoContainer: { 51 | flex: 1, 52 | paddingLeft: 10 53 | }, 54 | notificationCardPlaceholder: { 55 | borderRadius: 10, 56 | marginTop: 10 57 | } 58 | }); 59 | 60 | export default NotificationScreenPlaceholder; -------------------------------------------------------------------------------- /app/layout/placeholders/Connections.Placeholder.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { StyleSheet, View } from 'react-native'; 3 | import { responsiveWidth } from 'react-native-responsive-dimensions'; 4 | import { Placeholder, PlaceholderLine, PlaceholderMedia } from 'rn-placeholder'; 5 | import PlaceholderAnimation from './PlaceholderAnimation'; 6 | import { AppContext } from '@app/context'; 7 | 8 | const ConnectionsPlaceholder: React.FC = () => { 9 | const { theme } = useContext(AppContext); 10 | 11 | return ( 12 | 13 | 14 | {new Array(10) 15 | .fill({}) 16 | .map((_, index) => 17 | 18 | 19 | 20 | 26 | 32 | 33 | 34 | )} 35 | 36 | 37 | ); 38 | }; 39 | 40 | const styles = StyleSheet.create({ 41 | container: { 42 | flex: 1, 43 | marginTop: 20, 44 | paddingBottom: 0 45 | }, 46 | cardContainer: { 47 | flexDirection: 'row', 48 | marginBottom: 20 49 | }, 50 | infoContainer: { 51 | flex: 1, 52 | paddingLeft: 10 53 | }, 54 | userInfoPlaceholder: { 55 | borderRadius: 10, 56 | marginTop: 10 57 | } 58 | }); 59 | 60 | export default ConnectionsPlaceholder; -------------------------------------------------------------------------------- /app/layout/placeholders/SearchUsers.Placeholder.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { StyleSheet, View } from 'react-native'; 3 | import { responsiveWidth } from 'react-native-responsive-dimensions'; 4 | import { Placeholder, PlaceholderLine, PlaceholderMedia } from 'rn-placeholder'; 5 | import PlaceholderAnimation from './PlaceholderAnimation'; 6 | import { AppContext } from '@app/context'; 7 | 8 | const SearchUsersPlaceholder: React.FC = () => { 9 | const { theme } = useContext(AppContext); 10 | 11 | return ( 12 | 13 | 14 | {new Array(20) 15 | .fill({}) 16 | .map((_, index) => 17 | 18 | 19 | 20 | 26 | 32 | 33 | 34 | )} 35 | 36 | 37 | ); 38 | }; 39 | 40 | const styles = StyleSheet.create({ 41 | container: { 42 | flex: 1, 43 | padding: 20, 44 | paddingBottom: 0 45 | }, 46 | cardContainer: { 47 | flexDirection: 'row', 48 | marginBottom: 20 49 | }, 50 | infoContainer: { 51 | flex: 1, 52 | paddingLeft: 10 53 | }, 54 | userInfoPlaceholder: { 55 | borderRadius: 10, 56 | marginTop: 10 57 | } 58 | }); 59 | 60 | export default SearchUsersPlaceholder; -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /app/navigation/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Platform } from 'react-native'; 3 | import { createAppContainer } from 'react-navigation'; 4 | import createAnimatedSwitchNavigator from 'react-navigation-animated-switch'; 5 | import { createStackNavigator } from 'react-navigation-stack'; 6 | import { createBottomTabNavigator } from 'react-navigation-tabs'; 7 | import { StackRoutes, TabBarRoutes } from './Routes'; 8 | import TabBarComponent from './TabBarComponent'; 9 | import getSlideFromRightTransitionConfig from './Transition'; 10 | 11 | const TabNavigator = createBottomTabNavigator({ 12 | HomeScreen: { 13 | screen: TabBarRoutes.HomeScreen 14 | }, 15 | ExploreScreen: { 16 | screen: TabBarRoutes.ExploreScreen 17 | }, 18 | UploadScreen: { 19 | screen: TabBarRoutes.UploadScreen 20 | }, 21 | NotificationScreen: { 22 | screen: TabBarRoutes.NotificationScreen 23 | }, 24 | ProfileScreen: { 25 | screen: TabBarRoutes.ProfileScreen 26 | }, 27 | }, { 28 | lazy: true, 29 | tabBarOptions: { 30 | showLabel: false, 31 | }, 32 | tabBarComponent: props => 33 | }); 34 | 35 | const AuthStack = createStackNavigator({ 36 | LoginScreen: { 37 | screen: StackRoutes.LoginScreen 38 | } 39 | }, { headerMode: 'none' }); 40 | 41 | const AppStack = createStackNavigator({ 42 | TabNavigator: { 43 | screen: TabNavigator 44 | }, 45 | MessageScreen: { 46 | screen: StackRoutes.MessageScreen 47 | }, 48 | ConversationScreen: { 49 | screen: StackRoutes.ConversationScreen 50 | }, 51 | ProfileViewScreen: { 52 | screen: StackRoutes.ProfileViewScreen 53 | }, 54 | PostViewScreen: { 55 | screen: StackRoutes.PostViewScreen 56 | } 57 | }, { 58 | headerMode: 'none', 59 | transitionConfig: Platform.OS === 'ios' ? undefined : getSlideFromRightTransitionConfig 60 | }); 61 | 62 | const SwitchNavigator = createAnimatedSwitchNavigator({ 63 | Auth: AuthStack, 64 | App: AppStack 65 | }, { 66 | initialRouteName: 'Auth' 67 | }); 68 | 69 | const AppNavigator = createAppContainer(SwitchNavigator as any); 70 | 71 | export default AppNavigator; -------------------------------------------------------------------------------- /app/layout/shared/UserCard.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { StyleProp, StyleSheet, Text, TouchableOpacity, View, ViewStyle } from 'react-native'; 3 | import { useNavigation } from 'react-navigation-hooks'; 4 | import { Routes } from '@app/constants'; 5 | import { AppContext } from '@app/context'; 6 | import { Typography } from '@app/theme'; 7 | import { ThemeColors } from '@app/types/theme'; 8 | import NativeImage from '../misc/NativeImage'; 9 | 10 | const { FontWeights, FontSizes } = Typography; 11 | 12 | interface UserCardProps { 13 | userId: string, 14 | avatar: string, 15 | handle: string, 16 | name: string, 17 | style?: StyleProp, 18 | onPress?: any 19 | }; 20 | 21 | const UserCard: React.FC = ({ userId, avatar, handle, name, onPress, style }) => { 22 | 23 | const { user, theme } = useContext(AppContext); 24 | const { navigate } = useNavigation(); 25 | 26 | const navigateToProfile = () => { 27 | if (userId === user.id) return; 28 | navigate(Routes.ProfileViewScreen, { userId }); 29 | }; 30 | 31 | return ( 32 | 33 | 34 | 35 | {handle} 36 | {name} 37 | 38 | 39 | ); 40 | }; 41 | 42 | const styles = (theme = {} as ThemeColors) => StyleSheet.create({ 43 | container: { 44 | flexDirection: 'row', 45 | borderRadius: 5, 46 | width: '100%', 47 | }, 48 | avatarImage: { 49 | height: 50, 50 | width: 50, 51 | borderRadius: 50, 52 | backgroundColor: theme.placeholder 53 | }, 54 | info: { 55 | flex: 1, 56 | justifyContent: 'center', 57 | paddingLeft: 10 58 | }, 59 | handleText: { 60 | ...FontWeights.Regular, 61 | ...FontSizes.Body, 62 | color: theme.text01 63 | }, 64 | nameText: { 65 | ...FontWeights.Light, 66 | ...FontSizes.Caption, 67 | color: theme.text02, 68 | marginTop: 5 69 | } 70 | }); 71 | 72 | export default UserCard; -------------------------------------------------------------------------------- /app/layout/misc/BounceView.tsx: -------------------------------------------------------------------------------- 1 | // @ts-nocheck 2 | import React, { Component } from 'react'; 3 | import { Animated, PanResponder, View } from 'react-native'; 4 | 5 | const truthy = () => true; 6 | const noop = () => { }; 7 | 8 | class BounceView extends Component { 9 | 10 | static defaultProps = { 11 | onPress: noop, 12 | scale: 1.1, // Max scale of animation 13 | moveSlop: 15, // Slop area for press 14 | delay: 40 // Animation delay in milliseconds 15 | }; 16 | 17 | state = { 18 | scale: new Animated.Value(1) 19 | }; 20 | 21 | UNSAFE_componentWillMount() { 22 | this.panResponder = PanResponder.create({ 23 | onStartShouldSetPanResponder: truthy, 24 | onStartShouldSetPanResponderCapture: truthy, 25 | onMoveShouldSetPanResponder: truthy, 26 | onMoveShouldSetPanResponderCapture: truthy, 27 | onPanResponderTerminationRequest: truthy, 28 | onPanResponderTerminate: noop, 29 | onPanResponderGrant: () => { 30 | Animated.timing(this.state.scale, { 31 | toValue: this.props.scale, 32 | friction: 1, 33 | duration: 200, 34 | useNativeDriver: true 35 | }).start(); 36 | }, 37 | onPanResponderRelease: (evt, gestureState) => { 38 | const { moveSlop, delay, onPress } = this.props; 39 | 40 | const isOutOfRange = gestureState.dy > moveSlop || gestureState.dy < (-moveSlop) || gestureState.dx > moveSlop || gestureState.dx < (-moveSlop); 41 | 42 | if (!isOutOfRange) { 43 | setTimeout(() => { 44 | Animated.spring(this.state.scale, { 45 | toValue: 1, 46 | friction: 1, 47 | duration: 200, 48 | useNativeDriver: true 49 | }).start(); 50 | onPress(evt); 51 | }, delay); 52 | } 53 | } 54 | }); 55 | }; 56 | 57 | render() { 58 | const { scale } = this.state; 59 | const { children, style, ...rest } = this.props; 60 | 61 | return ( 62 | 66 | 67 | {children} 68 | 69 | 70 | ); 71 | }; 72 | }; 73 | 74 | export default BounceView; -------------------------------------------------------------------------------- /ios/Proximity/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /ios/ProximityTests/ProximityTests.m: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | * This source code is licensed under the MIT license found in the 5 | * LICENSE file in the root directory of this source tree. 6 | */ 7 | 8 | #import 9 | #import 10 | 11 | #import 12 | #import 13 | 14 | #define TIMEOUT_SECONDS 600 15 | #define TEXT_TO_LOOK_FOR @"Welcome to React" 16 | 17 | @interface ProximityTests : XCTestCase 18 | 19 | @end 20 | 21 | @implementation ProximityTests 22 | 23 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test 24 | { 25 | if (test(view)) { 26 | return YES; 27 | } 28 | for (UIView *subview in [view subviews]) { 29 | if ([self findSubviewInView:subview matching:test]) { 30 | return YES; 31 | } 32 | } 33 | return NO; 34 | } 35 | 36 | - (void)testRendersWelcomeScreen 37 | { 38 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 39 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 40 | BOOL foundElement = NO; 41 | 42 | __block NSString *redboxError = nil; 43 | #ifdef DEBUG 44 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 45 | if (level >= RCTLogLevelError) { 46 | redboxError = message; 47 | } 48 | }); 49 | #endif 50 | 51 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 52 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 53 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 54 | 55 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { 56 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 57 | return YES; 58 | } 59 | return NO; 60 | }]; 61 | } 62 | 63 | #ifdef DEBUG 64 | RCTSetLogFunction(RCTDefaultLogFunction); 65 | #endif 66 | 67 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 68 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 69 | } 70 | 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /app/screens/PostViewScreen/components/Comments.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { StyleSheet, Text, FlatList } from 'react-native'; 3 | import { AppContext } from '@app/context'; 4 | import { ListEmptyComponent } from '@app/layout'; 5 | import { Typography } from '@app/theme'; 6 | import { ThemeColors } from '@app/types/theme'; 7 | import CommentCard from './CommentCard'; 8 | import { Comment } from '@app/types/screens'; 9 | 10 | const { FontWeights, FontSizes } = Typography; 11 | 12 | interface CommentsProps { 13 | postId: string, 14 | comments: Comment[] 15 | }; 16 | 17 | const Comments: React.FC = ({ postId, comments }) => { 18 | const { theme } = useContext(AppContext); 19 | 20 | const renderItem = ({ item }) => { 21 | const { 22 | id: commentId, 23 | author: { 24 | id: authorId, 25 | avatar, 26 | handle 27 | }, 28 | body, 29 | createdAt 30 | } = item; 31 | 32 | return ( 33 | 42 | ); 43 | }; 44 | 45 | const ListHeaderComponent = () => Comments 46 | 47 | const marginBottom = comments.length === 0 ? 0 : 20; 48 | 49 | return ( 50 | 58 | 63 | } 64 | /> 65 | ); 66 | }; 67 | 68 | const styles = (theme = {} as ThemeColors) => StyleSheet.create({ 69 | commentsHeader: { 70 | ...FontWeights.Regular, 71 | ...FontSizes.Body, 72 | color: theme.text01 73 | }, 74 | listStyle: { 75 | marginBottom: 10 76 | }, 77 | placeholderStyle: { 78 | ...FontSizes.Body 79 | } 80 | }); 81 | 82 | export default Comments; -------------------------------------------------------------------------------- /app/layout/shared/ConfirmationModal.tsx: -------------------------------------------------------------------------------- 1 | import React, { useContext } from 'react'; 2 | import { View, Text, StyleSheet } from 'react-native'; 3 | import Modal from 'react-native-modal'; 4 | import { Typography } from '@app/theme'; 5 | import { AppContext } from '@app/context'; 6 | import { ThemeColors } from '@app/types/theme'; 7 | import Button from '../controls/Button'; 8 | 9 | const { FontWeights, FontSizes } = Typography; 10 | 11 | interface ConfirmationModalModal { 12 | title: string, 13 | description: string, 14 | isVisible: boolean, 15 | toggle: () => void, 16 | label: string, 17 | color?: string, 18 | onConfirm: () => void 19 | }; 20 | 21 | const ConfirmationModal: React.FC = ({ title, description, isVisible, toggle, label, color, onConfirm }) => { 22 | 23 | const { theme } = useContext(AppContext); 24 | 25 | return ( 26 | 35 | 36 | {title} 37 | {description} 38 |