├── .env ├── .gitignore ├── .vscode └── settings.json ├── App.tsx ├── LICENSE ├── Readme.md ├── android.bak ├── .gitignore ├── app │ ├── build.gradle │ ├── debug.keystore │ ├── google-services.json │ ├── proguard-rules.pro │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── me │ │ │ └── isaacojo │ │ │ └── qui │ │ │ ├── MainActivity.kt │ │ │ └── MainApplication.kt │ │ └── res │ │ ├── drawable-hdpi │ │ ├── notification_icon.png │ │ └── splashscreen_image.png │ │ ├── drawable-mdpi │ │ ├── notification_icon.png │ │ └── splashscreen_image.png │ │ ├── drawable-xhdpi │ │ ├── notification_icon.png │ │ └── splashscreen_image.png │ │ ├── drawable-xxhdpi │ │ ├── notification_icon.png │ │ └── splashscreen_image.png │ │ ├── drawable-xxxhdpi │ │ ├── notification_icon.png │ │ └── splashscreen_image.png │ │ ├── drawable │ │ ├── rn_edit_text_material.xml │ │ └── splashscreen.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── values-night │ │ └── colors.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── react-settings-plugin │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── kotlin │ │ └── expo │ │ └── plugins │ │ └── ReactSettingsPlugin.kt └── settings.gradle ├── android ├── .gitignore ├── app │ ├── build.gradle │ ├── debug.keystore │ ├── google-services.json │ ├── proguard-rules.pro │ └── src │ │ ├── debug │ │ └── AndroidManifest.xml │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── me │ │ │ └── isaacojo │ │ │ └── qui │ │ │ ├── MainActivity.kt │ │ │ └── MainApplication.kt │ │ └── res │ │ ├── drawable-hdpi │ │ ├── notification_icon.png │ │ └── splashscreen_image.png │ │ ├── drawable-mdpi │ │ ├── notification_icon.png │ │ └── splashscreen_image.png │ │ ├── drawable-xhdpi │ │ ├── notification_icon.png │ │ └── splashscreen_image.png │ │ ├── drawable-xxhdpi │ │ ├── notification_icon.png │ │ └── splashscreen_image.png │ │ ├── drawable-xxxhdpi │ │ ├── notification_icon.png │ │ └── splashscreen_image.png │ │ ├── drawable │ │ ├── rn_edit_text_material.xml │ │ └── splashscreen.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_foreground.png │ │ └── ic_launcher_round.png │ │ ├── values-night │ │ └── colors.xml │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── app.json ├── assets ├── Theme │ └── index.ts ├── adaptive-icon.png ├── avatar │ ├── 1.jpg │ ├── 2.jpg │ ├── 3.jpg │ └── placeholder.png ├── favicon.png ├── fonts │ ├── Instagram.ttf │ ├── Mulish-Black.ttf │ ├── Mulish-Bold.ttf │ ├── Mulish-ExtraBold.ttf │ ├── Mulish-Light.ttf │ ├── Mulish-Medium.ttf │ ├── Mulish.ttf │ ├── Panton.ttf │ ├── PlusJakartaSans-ExtraBold.ttf │ ├── PlusJakartaSans-Medium.ttf │ ├── PlusJakartaSans-SemiBold.ttf │ ├── Roboto-Bold.ttf │ ├── Roboto-Medium.ttf │ ├── UberMove-Bold.ttf │ ├── inst-bold.otf │ └── inst-regular.otf ├── icon.png ├── images │ ├── auth.png │ ├── bg.webp │ ├── emptyNot.png │ ├── emptySearch.png │ ├── image1.jpg │ ├── move.png │ ├── notification.png │ ├── phone.png │ ├── place-dark.svg │ ├── placeholder.jpg │ ├── placeholder.png │ ├── profile-black.svg │ ├── profile-white.svg │ ├── q.png │ ├── seek.png │ ├── shoot.png │ ├── tv-static.gif │ └── welcome.png ├── lottie │ ├── emptyList.json │ ├── isTyping-black.json │ ├── isTyping-light.json │ ├── like.json │ ├── notification.json │ ├── play.json │ └── robot.json ├── notification.png ├── qc.png ├── splash copy.png ├── splash-lightmode.png └── splash.png ├── babel.config.js ├── bun.lockb ├── components ├── chat │ ├── ChatBox.tsx │ ├── ChatBuilderText.tsx │ ├── ModalChatText.tsx │ ├── PickImageButton.tsx │ └── TypingBox.tsx ├── discover │ ├── HeaderTag │ │ └── index.tsx │ ├── PeopleContainer │ │ └── index.tsx │ ├── PostsContainer │ │ └── index.tsx │ ├── SearchBar │ │ └── index.tsx │ └── Skeleton │ │ ├── PostSearchSkeleton.tsx │ │ └── SearchSkeleton.tsx ├── editProfile │ └── EditContent.tsx ├── followingFollowers │ └── FollowingFollowerContainer.tsx ├── global │ ├── AnimatedScreen │ │ ├── FadeInView.tsx │ │ └── index.tsx │ ├── BottomSheetContainer │ │ ├── components │ │ │ ├── CheckBoxPair.tsx │ │ │ ├── CustomBg.tsx │ │ │ └── DarkModeView.tsx │ │ └── index.tsx │ ├── Buttons │ │ ├── AddPostButton.tsx │ │ ├── BottomBarButtons.tsx │ │ ├── Button.tsx │ │ └── IconButton.tsx │ ├── Modal │ │ └── LoadingOverlay.tsx │ └── Toast │ │ └── index.tsx ├── home │ ├── drawer │ │ ├── CustomDrawer.tsx │ │ └── HeaderDrawer.tsx │ ├── header │ │ ├── CustomDrawerHeader.tsx │ │ └── ProfileButton.tsx │ ├── misc │ │ ├── EmptyList.tsx │ │ ├── Skeleton.tsx │ │ └── SkeletonGroupPost.tsx │ └── post │ │ ├── FullScreenPost.tsx │ │ ├── PostBuilder.tsx │ │ ├── comment │ │ ├── CommentBuilder.tsx │ │ └── PostButton.tsx │ │ ├── components │ │ ├── AudioPlayLottie.tsx │ │ ├── AudioPost.tsx │ │ ├── CommentButton.tsx │ │ ├── EmptyLottie.tsx │ │ ├── Engagements.tsx │ │ ├── EngagementsFullScreen.tsx │ │ ├── Fab.tsx │ │ ├── LikeButton.tsx │ │ ├── LinkPost.tsx │ │ ├── LoadingIndicator.tsx │ │ ├── NameAndTag.tsx │ │ ├── NameAndTagFullScreen.tsx │ │ ├── PhotoPost.tsx │ │ ├── PhotoPostFullScreen.tsx │ │ ├── ProfileImage.tsx │ │ ├── RepostButton.tsx │ │ ├── RingAudio.tsx │ │ ├── TextPost.tsx │ │ ├── VideoPost.tsx │ │ └── VideoPostForFullScreen.tsx │ │ ├── misc │ │ ├── EngagementText.tsx │ │ └── Robot.tsx │ │ └── testVideo.tsx ├── icons │ └── index.tsx ├── messages │ ├── ChatList │ │ ├── ChatListView.tsx │ │ ├── ChatModal.tsx │ │ ├── Fab.tsx │ │ ├── ListContainer.tsx │ │ └── index.tsx │ └── Recent │ │ ├── AvatarName.tsx │ │ ├── Me.tsx │ │ └── index.tsx ├── notifications │ ├── NotifLottie.tsx │ └── NotificationBuilder │ │ └── index.tsx ├── postContent │ ├── PickAudioButton.tsx │ ├── PickImageButton.tsx │ ├── PickVideoButton.tsx │ ├── PostButton.tsx │ ├── TextArea.tsx │ └── VideoTextArea.tsx ├── profile │ ├── Bio.tsx │ ├── EditProfile.tsx │ ├── Header.tsx │ ├── UploadGif.tsx │ ├── UploadPhotoModal.tsx │ └── UploadPic.tsx ├── profilePeople │ ├── Bio.tsx │ ├── FollowerUser.tsx │ ├── Header.tsx │ └── ViewProfilePhoto.tsx └── searchUser │ ├── SearchBox.tsx │ └── UserContainer.tsx ├── credentials.json ├── data ├── chatDummyData.ts ├── dummyChat.ts ├── murphy.ts └── test.ts ├── eas.json ├── google-services.json ├── hooks ├── Debounce.tsx ├── GetMode.tsx └── Socket.tsx ├── ios ├── .gitignore ├── .xcode.env ├── Podfile ├── Podfile.lock ├── Podfile.properties.json ├── Qui.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── Qui.xcscheme ├── Qui.xcworkspace │ └── contents.xcworkspacedata └── Qui │ ├── AppDelegate.h │ ├── AppDelegate.mm │ ├── Images.xcassets │ ├── AppIcon.appiconset │ │ ├── App-Icon-1024x1024@1x.png │ │ └── Contents.json │ ├── Contents.json │ ├── SplashScreen.imageset │ │ ├── Contents.json │ │ └── image.png │ └── SplashScreenBackground.imageset │ │ ├── Contents.json │ │ └── image.png │ ├── Info.plist │ ├── PrivacyInfo.xcprivacy │ ├── Qui-Bridging-Header.h │ ├── Qui.entitlements │ ├── SplashScreen.storyboard │ ├── Supporting │ └── Expo.plist │ ├── main.m │ └── noop-file.swift ├── models.json ├── package.json ├── redux ├── api │ ├── auth.ts │ ├── chat.ts │ ├── services.ts │ └── user.ts ├── hooks │ └── hooks.ts ├── slice │ ├── bottomSheet │ │ └── index.tsx │ ├── chat │ │ ├── chatlist.ts │ │ └── online.ts │ ├── currentPage │ │ └── index.ts │ ├── modal │ │ └── loading.ts │ ├── people │ │ └── search.ts │ ├── post │ │ ├── audio.ts │ │ ├── followed.ts │ │ ├── index.ts │ │ └── search.ts │ ├── prefs │ │ └── index.ts │ ├── routes │ │ └── index.ts │ ├── toast │ │ └── toast.ts │ └── user │ │ ├── followers.ts │ │ └── index.ts ├── storage.ts └── store.ts ├── routes ├── Auth.tsx ├── Main.tsx ├── Main │ ├── BottomNavigation.tsx │ └── DrawerNavigation.tsx └── OnBoard.tsx ├── screen ├── App │ ├── ChangeData.tsx │ ├── ChangeData │ │ ├── ChangeName.tsx │ │ ├── ChangePassword.tsx │ │ ├── ChangeUserName.tsx │ │ └── DeleteAccountModal.tsx │ ├── ChatScreen.tsx │ ├── Discover.tsx │ ├── DiscoverScreens │ │ ├── Posts.tsx │ │ └── Users.tsx │ ├── EditProfile.tsx │ ├── FollowingFollowerScreens │ │ ├── Followers.tsx │ │ └── Following.tsx │ ├── FollowingFollowers.tsx │ ├── Home.tsx │ ├── HomeScreens │ │ ├── HomeAll.tsx │ │ └── HomeFollowed.tsx │ ├── ImageFullScreen.tsx │ ├── Messages.tsx │ ├── Notifications.tsx │ ├── Post.tsx │ ├── PostContent.tsx │ ├── PostScreen.tsx │ ├── Profile.tsx │ ├── ProfilePeople.tsx │ ├── ProfileScreens │ │ ├── MyPosts.tsx │ │ └── PeoplePosts.tsx │ ├── SearchUsers.tsx │ └── VideoFullScreen.tsx ├── Auth │ ├── Login.tsx │ ├── Register.tsx │ └── components │ │ ├── InputPassword.tsx │ │ └── InputText.tsx └── Onboard │ ├── components │ ├── OnboardBuilder.tsx │ └── TrackerTag.tsx │ └── index.tsx ├── screenshot └── qui.gif ├── tsconfig.json ├── types ├── api.ts ├── app.ts ├── navigation.ts └── socket.ts └── util ├── chatSearch.ts ├── convert.ts ├── date.ts ├── emoji.ts ├── notification.ts └── socket.ts /.env: -------------------------------------------------------------------------------- 1 | EXPO_PUBLIC_API_URL=https://qui.isaacojo.me 2 | # EXPO_PUBLIC_API_URL=http://192.168.0.106 3 | EXPO_PUBLIC_PROJECT_ID=e618bb47-6149-4585-8cc8-884c5992795e 4 | # EXPO_PUBLIC_API_URL=https://285b-102-36-135-22.ngrok.io 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files 2 | 3 | # dependencies 4 | node_modules/ 5 | android/.gradle 6 | # Expo 7 | .expo/ 8 | dist/ 9 | web-build/ 10 | 11 | # Native 12 | *.orig.* 13 | *.jks 14 | *.p8 15 | *.p12 16 | *.key 17 | *.mobileprovision 18 | *.apk 19 | android/keystores/release.keystore 20 | 21 | # Metro 22 | .metro-health-check* 23 | 24 | # debug 25 | npm-debug.* 26 | yarn-debug.* 27 | yarn-error.* 28 | 29 | # macOS 30 | .DS_Store 31 | *.pem 32 | 33 | # local env files 34 | .env*.local 35 | 36 | # typescript 37 | *.tsbuildinfo 38 | 39 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": ["reposting"] 3 | } 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Creative Commons Attribution 4.0 International (CC BY 4.0) 2 | 3 | Copyright (c) 2024 Isaac Ojo 4 | 5 | This work is licensed under the Creative Commons Attribution 4.0 International License. 6 | To view a copy of this license, visit https://creativecommons.org/licenses/by/4.0/ 7 | 8 | You are free to: 9 | - Share: Copy and redistribute the material in any medium or format 10 | - Adapt: Remix, transform, and build upon the material 11 | - Use commercially: Use the material for commercial purposes 12 | 13 | Under the following terms: 14 | - Attribution: You must give appropriate credit, provide a link to the license, and indicate if changes were made. 15 | 16 | No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. -------------------------------------------------------------------------------- /android.bak/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Android/IntelliJ 6 | # 7 | build/ 8 | .idea 9 | .gradle 10 | local.properties 11 | *.iml 12 | *.hprof 13 | .cxx/ 14 | 15 | # Bundle artifacts 16 | *.jsbundle 17 | -------------------------------------------------------------------------------- /android.bak/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/debug.keystore -------------------------------------------------------------------------------- /android.bak/app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "365442112752", 4 | "project_id": "quiapp-698b0", 5 | "storage_bucket": "quiapp-698b0.appspot.com" 6 | }, 7 | "client": [ 8 | { 9 | "client_info": { 10 | "mobilesdk_app_id": "1:365442112752:android:f7cad07868aaef170af635", 11 | "android_client_info": { 12 | "package_name": "me.isaacojo.qui" 13 | } 14 | }, 15 | "oauth_client": [], 16 | "api_key": [ 17 | { 18 | "current_key": "AIzaSyBSquawmwCQmx9-dm4u0wD-VArumgSb0H0" 19 | } 20 | ], 21 | "services": { 22 | "appinvite_service": { 23 | "other_platform_oauth_client": [] 24 | } 25 | } 26 | } 27 | ], 28 | "configuration_version": "1" 29 | } -------------------------------------------------------------------------------- /android.bak/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 | # react-native-reanimated 11 | -keep class com.swmansion.reanimated.** { *; } 12 | -keep class com.facebook.react.turbomodule.** { *; } 13 | 14 | # Add any project specific keep options here: 15 | -------------------------------------------------------------------------------- /android.bak/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android.bak/app/src/main/java/me/isaacojo/qui/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package me.isaacojo.qui 2 | 3 | import android.os.Build 4 | import android.os.Bundle 5 | 6 | import com.facebook.react.ReactActivity 7 | import com.facebook.react.ReactActivityDelegate 8 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled 9 | import com.facebook.react.defaults.DefaultReactActivityDelegate 10 | 11 | import expo.modules.ReactActivityDelegateWrapper 12 | 13 | class MainActivity : ReactActivity() { 14 | override fun onCreate(savedInstanceState: Bundle?) { 15 | // Set the theme to AppTheme BEFORE onCreate to support 16 | // coloring the background, status bar, and navigation bar. 17 | // This is required for expo-splash-screen. 18 | setTheme(R.style.AppTheme); 19 | super.onCreate(null) 20 | } 21 | 22 | /** 23 | * Returns the name of the main component registered from JavaScript. This is used to schedule 24 | * rendering of the component. 25 | */ 26 | override fun getMainComponentName(): String = "main" 27 | 28 | /** 29 | * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] 30 | * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] 31 | */ 32 | override fun createReactActivityDelegate(): ReactActivityDelegate { 33 | return ReactActivityDelegateWrapper( 34 | this, 35 | BuildConfig.IS_NEW_ARCHITECTURE_ENABLED, 36 | object : DefaultReactActivityDelegate( 37 | this, 38 | mainComponentName, 39 | fabricEnabled 40 | ){}) 41 | } 42 | 43 | /** 44 | * Align the back button behavior with Android S 45 | * where moving root activities to background instead of finishing activities. 46 | * @see onBackPressed 47 | */ 48 | override fun invokeDefaultOnBackPressed() { 49 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) { 50 | if (!moveTaskToBack(false)) { 51 | // For non-root activities, use the default implementation to finish them. 52 | super.invokeDefaultOnBackPressed() 53 | } 54 | return 55 | } 56 | 57 | // Use the default back button implementation on Android S 58 | // because it's doing more than [Activity.moveTaskToBack] in fact. 59 | super.invokeDefaultOnBackPressed() 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /android.bak/app/src/main/java/me/isaacojo/qui/MainApplication.kt: -------------------------------------------------------------------------------- 1 | package me.isaacojo.qui 2 | 3 | import android.app.Application 4 | import android.content.res.Configuration 5 | 6 | import com.facebook.react.PackageList 7 | import com.facebook.react.ReactApplication 8 | import com.facebook.react.ReactNativeHost 9 | import com.facebook.react.ReactPackage 10 | import com.facebook.react.ReactHost 11 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load 12 | import com.facebook.react.defaults.DefaultReactNativeHost 13 | import com.facebook.soloader.SoLoader 14 | 15 | import expo.modules.ApplicationLifecycleDispatcher 16 | import expo.modules.ReactNativeHostWrapper 17 | 18 | class MainApplication : Application(), ReactApplication { 19 | 20 | override val reactNativeHost: ReactNativeHost = ReactNativeHostWrapper( 21 | this, 22 | object : DefaultReactNativeHost(this) { 23 | override fun getPackages(): List { 24 | // Packages that cannot be autolinked yet can be added manually here, for example: 25 | // packages.add(new MyReactNativePackage()); 26 | return PackageList(this).packages 27 | } 28 | 29 | override fun getJSMainModuleName(): String = ".expo/.virtual-metro-entry" 30 | 31 | override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG 32 | 33 | override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED 34 | override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED 35 | } 36 | ) 37 | 38 | override val reactHost: ReactHost 39 | get() = ReactNativeHostWrapper.createReactHost(applicationContext, reactNativeHost) 40 | 41 | override fun onCreate() { 42 | super.onCreate() 43 | SoLoader.init(this, false) 44 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { 45 | // If you opted-in for the New Architecture, we load the native entry point for this app. 46 | load() 47 | } 48 | ApplicationLifecycleDispatcher.onApplicationCreate(this) 49 | } 50 | 51 | override fun onConfigurationChanged(newConfig: Configuration) { 52 | super.onConfigurationChanged(newConfig) 53 | ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /android.bak/app/src/main/res/drawable-hdpi/notification_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/drawable-hdpi/notification_icon.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/drawable-hdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/drawable-hdpi/splashscreen_image.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/drawable-mdpi/notification_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/drawable-mdpi/notification_icon.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/drawable-mdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/drawable-mdpi/splashscreen_image.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/drawable-xhdpi/notification_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/drawable-xhdpi/notification_icon.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/drawable-xhdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/drawable-xhdpi/splashscreen_image.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/drawable-xxhdpi/notification_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/drawable-xxhdpi/notification_icon.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/drawable-xxhdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/drawable-xxhdpi/splashscreen_image.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/drawable-xxxhdpi/notification_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/drawable-xxxhdpi/notification_icon.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/drawable/rn_edit_text_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 22 | 23 | 24 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /android.bak/app/src/main/res/drawable/splashscreen.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /android.bak/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android.bak/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android.bak/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android.bak/app/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /android.bak/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | #000000 3 | #ffffff 4 | #023c69 5 | #000000 6 | #ffffff 7 | -------------------------------------------------------------------------------- /android.bak/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Qui 3 | contain 4 | false 5 | automatic 6 | -------------------------------------------------------------------------------- /android.bak/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 13 | 17 | -------------------------------------------------------------------------------- /android.bak/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 = findProperty('android.buildToolsVersion') ?: '34.0.0' 6 | minSdkVersion = Integer.parseInt(findProperty('android.minSdkVersion') ?: '23') 7 | compileSdkVersion = Integer.parseInt(findProperty('android.compileSdkVersion') ?: '34') 8 | targetSdkVersion = Integer.parseInt(findProperty('android.targetSdkVersion') ?: '34') 9 | kotlinVersion = findProperty('android.kotlinVersion') ?: '1.9.23' 10 | 11 | ndkVersion = "26.1.10909125" 12 | } 13 | repositories { 14 | google() 15 | mavenCentral() 16 | } 17 | dependencies { 18 | classpath 'com.google.gms:google-services:4.4.1' 19 | classpath('com.android.tools.build:gradle') 20 | classpath('com.facebook.react:react-native-gradle-plugin') 21 | classpath('org.jetbrains.kotlin:kotlin-gradle-plugin') 22 | } 23 | } 24 | 25 | apply plugin: "com.facebook.react.rootproject" 26 | 27 | allprojects { 28 | repositories { 29 | maven { 30 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 31 | url(new File(['node', '--print', "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim(), '../android')) 32 | } 33 | maven { 34 | // Android JSC is installed from npm 35 | url(new File(['node', '--print', "require.resolve('jsc-android/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim(), '../dist')) 36 | } 37 | 38 | google() 39 | mavenCentral() 40 | maven { url 'https://www.jitpack.io' } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /android.bak/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: -Xmx512m -XX:MaxMetaspaceSize=256m 13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m 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 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | 25 | # Automatically convert third-party libraries to use AndroidX 26 | android.enableJetifier=true 27 | 28 | # Enable AAPT2 PNG crunching 29 | android.enablePngCrunchInReleaseBuilds=true 30 | 31 | # Use this property to specify which architecture you want to build. 32 | # You can also override it from the CLI using 33 | # ./gradlew -PreactNativeArchitectures=x86_64 34 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 35 | 36 | # Use this property to enable support to the new architecture. 37 | # This will allow you to use TurboModules and the Fabric render in 38 | # your application. You should enable this flag either if you want 39 | # to write custom TurboModules/Fabric components OR use libraries that 40 | # are providing them. 41 | newArchEnabled=false 42 | 43 | # Use this property to enable or disable the Hermes JS engine. 44 | # If set to false, you will be using JSC instead. 45 | hermesEnabled=true 46 | 47 | # Enable GIF support in React Native images (~200 B increase) 48 | expo.gif.enabled=true 49 | # Enable webp support in React Native images (~85 KB increase) 50 | expo.webp.enabled=true 51 | # Enable animated webp support (~3.4 MB increase) 52 | # Disabled by default because iOS doesn't support animated webp 53 | expo.webp.animated=false 54 | 55 | # Enable network inspector 56 | EX_DEV_CLIENT_NETWORK_INSPECTOR=true 57 | 58 | # Use legacy packaging to compress native libraries in the resulting APK. 59 | expo.useLegacyPackaging=false 60 | 61 | android.extraMavenRepos=[] -------------------------------------------------------------------------------- /android.bak/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android.bak/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android.bak/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-all.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /android.bak/react-settings-plugin/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.tasks.KotlinCompile 2 | 3 | plugins { 4 | kotlin("jvm") version "1.9.24" 5 | id("java-gradle-plugin") 6 | } 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | gradlePlugin { 13 | plugins { 14 | create("reactSettingsPlugin") { 15 | id = "com.facebook.react.settings" 16 | implementationClass = "expo.plugins.ReactSettingsPlugin" 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /android.bak/react-settings-plugin/src/main/kotlin/expo/plugins/ReactSettingsPlugin.kt: -------------------------------------------------------------------------------- 1 | package expo.plugins 2 | 3 | import org.gradle.api.Plugin 4 | import org.gradle.api.initialization.Settings 5 | 6 | class ReactSettingsPlugin : Plugin { 7 | override fun apply(settings: Settings) { 8 | // Do nothing, just register the plugin. 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /android/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Android/IntelliJ 6 | # 7 | build/ 8 | .idea 9 | .gradle 10 | local.properties 11 | *.iml 12 | *.hprof 13 | .cxx/ 14 | 15 | # Bundle artifacts 16 | *.jsbundle 17 | -------------------------------------------------------------------------------- /android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/debug.keystore -------------------------------------------------------------------------------- /android/app/google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "365442112752", 4 | "project_id": "quiapp-698b0", 5 | "storage_bucket": "quiapp-698b0.appspot.com" 6 | }, 7 | "client": [ 8 | { 9 | "client_info": { 10 | "mobilesdk_app_id": "1:365442112752:android:f7cad07868aaef170af635", 11 | "android_client_info": { 12 | "package_name": "me.isaacojo.qui" 13 | } 14 | }, 15 | "oauth_client": [], 16 | "api_key": [ 17 | { 18 | "current_key": "AIzaSyBSquawmwCQmx9-dm4u0wD-VArumgSb0H0" 19 | } 20 | ], 21 | "services": { 22 | "appinvite_service": { 23 | "other_platform_oauth_client": [] 24 | } 25 | } 26 | } 27 | ], 28 | "configuration_version": "1" 29 | } -------------------------------------------------------------------------------- /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 | # react-native-reanimated 11 | -keep class com.swmansion.reanimated.** { *; } 12 | -keep class com.facebook.react.turbomodule.** { *; } 13 | 14 | # Add any project specific keep options here: 15 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /android/app/src/main/java/me/isaacojo/qui/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package me.isaacojo.qui 2 | 3 | import android.os.Build 4 | import android.os.Bundle 5 | 6 | import com.facebook.react.ReactActivity 7 | import com.facebook.react.ReactActivityDelegate 8 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled 9 | import com.facebook.react.defaults.DefaultReactActivityDelegate 10 | 11 | import expo.modules.ReactActivityDelegateWrapper 12 | 13 | class MainActivity : ReactActivity() { 14 | override fun onCreate(savedInstanceState: Bundle?) { 15 | // Set the theme to AppTheme BEFORE onCreate to support 16 | // coloring the background, status bar, and navigation bar. 17 | // This is required for expo-splash-screen. 18 | setTheme(R.style.AppTheme); 19 | super.onCreate(null) 20 | } 21 | 22 | /** 23 | * Returns the name of the main component registered from JavaScript. This is used to schedule 24 | * rendering of the component. 25 | */ 26 | override fun getMainComponentName(): String = "main" 27 | 28 | /** 29 | * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] 30 | * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] 31 | */ 32 | override fun createReactActivityDelegate(): ReactActivityDelegate { 33 | return ReactActivityDelegateWrapper( 34 | this, 35 | BuildConfig.IS_NEW_ARCHITECTURE_ENABLED, 36 | object : DefaultReactActivityDelegate( 37 | this, 38 | mainComponentName, 39 | fabricEnabled 40 | ){}) 41 | } 42 | 43 | /** 44 | * Align the back button behavior with Android S 45 | * where moving root activities to background instead of finishing activities. 46 | * @see onBackPressed 47 | */ 48 | override fun invokeDefaultOnBackPressed() { 49 | if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R) { 50 | if (!moveTaskToBack(false)) { 51 | // For non-root activities, use the default implementation to finish them. 52 | super.invokeDefaultOnBackPressed() 53 | } 54 | return 55 | } 56 | 57 | // Use the default back button implementation on Android S 58 | // because it's doing more than [Activity.moveTaskToBack] in fact. 59 | super.invokeDefaultOnBackPressed() 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /android/app/src/main/java/me/isaacojo/qui/MainApplication.kt: -------------------------------------------------------------------------------- 1 | package me.isaacojo.qui 2 | 3 | import android.app.Application 4 | import android.content.res.Configuration 5 | 6 | import com.facebook.react.PackageList 7 | import com.facebook.react.ReactApplication 8 | import com.facebook.react.ReactNativeHost 9 | import com.facebook.react.ReactPackage 10 | import com.facebook.react.ReactHost 11 | import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load 12 | import com.facebook.react.defaults.DefaultReactNativeHost 13 | import com.facebook.react.soloader.OpenSourceMergedSoMapping 14 | import com.facebook.soloader.SoLoader 15 | 16 | import expo.modules.ApplicationLifecycleDispatcher 17 | import expo.modules.ReactNativeHostWrapper 18 | 19 | class MainApplication : Application(), ReactApplication { 20 | 21 | override val reactNativeHost: ReactNativeHost = ReactNativeHostWrapper( 22 | this, 23 | object : DefaultReactNativeHost(this) { 24 | override fun getPackages(): List { 25 | val packages = PackageList(this).packages 26 | // Packages that cannot be autolinked yet can be added manually here, for example: 27 | // packages.add(new MyReactNativePackage()); 28 | return packages 29 | } 30 | 31 | override fun getJSMainModuleName(): String = ".expo/.virtual-metro-entry" 32 | 33 | override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG 34 | 35 | override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED 36 | override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED 37 | } 38 | ) 39 | 40 | override val reactHost: ReactHost 41 | get() = ReactNativeHostWrapper.createReactHost(applicationContext, reactNativeHost) 42 | 43 | override fun onCreate() { 44 | super.onCreate() 45 | SoLoader.init(this, OpenSourceMergedSoMapping) 46 | if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { 47 | // If you opted-in for the New Architecture, we load the native entry point for this app. 48 | load() 49 | } 50 | ApplicationLifecycleDispatcher.onApplicationCreate(this) 51 | } 52 | 53 | override fun onConfigurationChanged(newConfig: Configuration) { 54 | super.onConfigurationChanged(newConfig) 55 | ApplicationLifecycleDispatcher.onConfigurationChanged(this, newConfig) 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-hdpi/notification_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/drawable-hdpi/notification_icon.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-hdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/drawable-hdpi/splashscreen_image.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-mdpi/notification_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/drawable-mdpi/notification_icon.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-mdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/drawable-mdpi/splashscreen_image.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xhdpi/notification_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/drawable-xhdpi/notification_icon.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xhdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/drawable-xhdpi/splashscreen_image.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxhdpi/notification_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/drawable-xxhdpi/notification_icon.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxhdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/drawable-xxhdpi/splashscreen_image.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxxhdpi/notification_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/drawable-xxxhdpi/notification_icon.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/drawable-xxxhdpi/splashscreen_image.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/rn_edit_text_material.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 22 | 23 | 24 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable/splashscreen.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/values-night/colors.xml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | #000000 3 | #ffffff 4 | #023c69 5 | #000000 6 | #ffffff 7 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Qui 3 | contain 4 | false 5 | automatic 6 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 13 | 16 | -------------------------------------------------------------------------------- /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 = findProperty('android.buildToolsVersion') ?: '35.0.0' 6 | minSdkVersion = Integer.parseInt(findProperty('android.minSdkVersion') ?: '24') 7 | compileSdkVersion = Integer.parseInt(findProperty('android.compileSdkVersion') ?: '35') 8 | targetSdkVersion = Integer.parseInt(findProperty('android.targetSdkVersion') ?: '34') 9 | kotlinVersion = findProperty('android.kotlinVersion') ?: '1.9.24' 10 | 11 | ndkVersion = "26.1.10909125" 12 | } 13 | repositories { 14 | google() 15 | mavenCentral() 16 | } 17 | dependencies { 18 | classpath 'com.google.gms:google-services:4.4.1' 19 | classpath('com.android.tools.build:gradle') 20 | classpath('com.facebook.react:react-native-gradle-plugin') 21 | classpath('org.jetbrains.kotlin:kotlin-gradle-plugin') 22 | } 23 | } 24 | 25 | apply plugin: "com.facebook.react.rootproject" 26 | 27 | allprojects { 28 | repositories { 29 | maven { 30 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 31 | url(new File(['node', '--print', "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim(), '../android')) 32 | } 33 | maven { 34 | // Android JSC is installed from npm 35 | url(new File(['node', '--print', "require.resolve('jsc-android/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim(), '../dist')) 36 | } 37 | 38 | google() 39 | mavenCentral() 40 | maven { url 'https://www.jitpack.io' } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /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: -Xmx512m -XX:MaxMetaspaceSize=256m 13 | org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m 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 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | 25 | # Enable AAPT2 PNG crunching 26 | android.enablePngCrunchInReleaseBuilds=true 27 | 28 | # Use this property to specify which architecture you want to build. 29 | # You can also override it from the CLI using 30 | # ./gradlew -PreactNativeArchitectures=x86_64 31 | reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 32 | 33 | # Use this property to enable support to the new architecture. 34 | # This will allow you to use TurboModules and the Fabric render in 35 | # your application. You should enable this flag either if you want 36 | # to write custom TurboModules/Fabric components OR use libraries that 37 | # are providing them. 38 | newArchEnabled=false 39 | 40 | # Use this property to enable or disable the Hermes JS engine. 41 | # If set to false, you will be using JSC instead. 42 | hermesEnabled=true 43 | 44 | # Enable GIF support in React Native images (~200 B increase) 45 | expo.gif.enabled=true 46 | # Enable webp support in React Native images (~85 KB increase) 47 | expo.webp.enabled=true 48 | # Enable animated webp support (~3.4 MB increase) 49 | # Disabled by default because iOS doesn't support animated webp 50 | expo.webp.animated=false 51 | 52 | # Enable network inspector 53 | EX_DEV_CLIENT_NETWORK_INSPECTOR=true 54 | 55 | # Use legacy packaging to compress native libraries in the resulting APK. 56 | expo.useLegacyPackaging=false 57 | 58 | android.extraMavenRepos=[] -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | includeBuild(new File(["node", "--print", "require.resolve('@react-native/gradle-plugin/package.json')"].execute(null, rootDir).text.trim()).getParentFile().toString()) 3 | } 4 | plugins { id("com.facebook.react.settings") } 5 | 6 | extensions.configure(com.facebook.react.ReactSettingsExtension) { ex -> 7 | if (System.getenv('EXPO_USE_COMMUNITY_AUTOLINKING') == '1') { 8 | ex.autolinkLibrariesFromCommand() 9 | } else { 10 | def command = [ 11 | 'node', 12 | '--no-warnings', 13 | '--eval', 14 | 'require(require.resolve(\'expo-modules-autolinking\', { paths: [require.resolve(\'expo/package.json\')] }))(process.argv.slice(1))', 15 | 'react-native-config', 16 | '--json', 17 | '--platform', 18 | 'android' 19 | ].toList() 20 | ex.autolinkLibrariesFromCommand(command) 21 | } 22 | } 23 | 24 | rootProject.name = 'Qui' 25 | 26 | dependencyResolutionManagement { 27 | versionCatalogs { 28 | reactAndroidLibs { 29 | from(files(new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim(), "../gradle/libs.versions.toml"))) 30 | } 31 | } 32 | } 33 | 34 | apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute(null, rootDir).text.trim(), "../scripts/autolinking.gradle"); 35 | useExpoModules() 36 | 37 | include ':app' 38 | includeBuild(new File(["node", "--print", "require.resolve('@react-native/gradle-plugin/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim()).getParentFile()) 39 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo": { 3 | "name": "Qui", 4 | "slug": "qui", 5 | "version": "1.0.0", 6 | "orientation": "portrait", 7 | "icon": "./assets/icon.png", 8 | "userInterfaceStyle": "automatic", 9 | "splash": { 10 | "image": "./assets/splash.png", 11 | "resizeMode": "contain", 12 | "backgroundColor": "#000000" 13 | }, 14 | "install": { 15 | "exclude": [ 16 | "react-native@~0.74.0", 17 | "react-native-reanimated@~3.10.0", 18 | "react-native-gesture-handler@~2.16.1", 19 | "react-native-screens@~3.31.1" 20 | ] 21 | }, 22 | "assetBundlePatterns": [ 23 | "**/*" 24 | ], 25 | "ios": { 26 | "supportsTablet": true, 27 | "bundleIdentifier": "me.isaacojo.qui" 28 | }, 29 | "android": { 30 | "googleServicesFile": "./google-services.json", 31 | "adaptiveIcon": { 32 | "foregroundImage": "./assets/adaptive-icon.png", 33 | "backgroundColor": "#ffffff" 34 | }, 35 | "package": "me.isaacojo.qui" 36 | }, 37 | "web": { 38 | "favicon": "./assets/favicon.png" 39 | }, 40 | "extra": { 41 | "eas": { 42 | "projectId": "e618bb47-6149-4585-8cc8-884c5992795e" 43 | } 44 | }, 45 | "plugins": [ 46 | [ 47 | "expo-notifications", 48 | { 49 | "icon": "./assets/notification.png", 50 | "color": "#ffffff" 51 | } 52 | ], 53 | "react-native-compressor", 54 | "react-native-edge-to-edge", 55 | [ 56 | "expo-build-properties", 57 | { 58 | "ios": { 59 | "newArchEnabled": false 60 | }, 61 | "android": { 62 | "newArchEnabled": false 63 | } 64 | } 65 | ], 66 | [ 67 | "expo-notifications", 68 | { 69 | "icon": "./assets/notification.png", 70 | "color": "#ffffff" 71 | } 72 | ], 73 | "react-native-compressor", 74 | "react-native-edge-to-edge", 75 | [ 76 | "expo-build-properties", 77 | { 78 | "ios": { 79 | "newArchEnabled": false 80 | }, 81 | "android": { 82 | "newArchEnabled": false 83 | } 84 | } 85 | ], 86 | "expo-video" 87 | ], 88 | "owner": "hojoisaac" 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /assets/Theme/index.ts: -------------------------------------------------------------------------------- 1 | import { Theme } from "@react-navigation/native"; 2 | 3 | export const themeLight: Theme = { 4 | dark: false, 5 | colors: { 6 | primary: "white", 7 | background: "white", 8 | card: "black", 9 | text: "black", 10 | border: "#FFFFFF30", 11 | notification: "black", 12 | }, 13 | }; 14 | export const themeDark: Theme = { 15 | dark: true, 16 | colors: { 17 | primary: "white", 18 | background: "black", 19 | card: "white", 20 | text: "white", 21 | border: "#FFFFFF30", 22 | notification: "white", 23 | }, 24 | }; 25 | -------------------------------------------------------------------------------- /assets/adaptive-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/adaptive-icon.png -------------------------------------------------------------------------------- /assets/avatar/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/avatar/1.jpg -------------------------------------------------------------------------------- /assets/avatar/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/avatar/2.jpg -------------------------------------------------------------------------------- /assets/avatar/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/avatar/3.jpg -------------------------------------------------------------------------------- /assets/avatar/placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/avatar/placeholder.png -------------------------------------------------------------------------------- /assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/favicon.png -------------------------------------------------------------------------------- /assets/fonts/Instagram.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/fonts/Instagram.ttf -------------------------------------------------------------------------------- /assets/fonts/Mulish-Black.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/fonts/Mulish-Black.ttf -------------------------------------------------------------------------------- /assets/fonts/Mulish-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/fonts/Mulish-Bold.ttf -------------------------------------------------------------------------------- /assets/fonts/Mulish-ExtraBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/fonts/Mulish-ExtraBold.ttf -------------------------------------------------------------------------------- /assets/fonts/Mulish-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/fonts/Mulish-Light.ttf -------------------------------------------------------------------------------- /assets/fonts/Mulish-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/fonts/Mulish-Medium.ttf -------------------------------------------------------------------------------- /assets/fonts/Mulish.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/fonts/Mulish.ttf -------------------------------------------------------------------------------- /assets/fonts/Panton.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/fonts/Panton.ttf -------------------------------------------------------------------------------- /assets/fonts/PlusJakartaSans-ExtraBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/fonts/PlusJakartaSans-ExtraBold.ttf -------------------------------------------------------------------------------- /assets/fonts/PlusJakartaSans-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/fonts/PlusJakartaSans-Medium.ttf -------------------------------------------------------------------------------- /assets/fonts/PlusJakartaSans-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/fonts/PlusJakartaSans-SemiBold.ttf -------------------------------------------------------------------------------- /assets/fonts/Roboto-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/fonts/Roboto-Bold.ttf -------------------------------------------------------------------------------- /assets/fonts/Roboto-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/fonts/Roboto-Medium.ttf -------------------------------------------------------------------------------- /assets/fonts/UberMove-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/fonts/UberMove-Bold.ttf -------------------------------------------------------------------------------- /assets/fonts/inst-bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/fonts/inst-bold.otf -------------------------------------------------------------------------------- /assets/fonts/inst-regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/fonts/inst-regular.otf -------------------------------------------------------------------------------- /assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/icon.png -------------------------------------------------------------------------------- /assets/images/auth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/images/auth.png -------------------------------------------------------------------------------- /assets/images/bg.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/images/bg.webp -------------------------------------------------------------------------------- /assets/images/emptyNot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/images/emptyNot.png -------------------------------------------------------------------------------- /assets/images/emptySearch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/images/emptySearch.png -------------------------------------------------------------------------------- /assets/images/image1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/images/image1.jpg -------------------------------------------------------------------------------- /assets/images/move.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/images/move.png -------------------------------------------------------------------------------- /assets/images/notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/images/notification.png -------------------------------------------------------------------------------- /assets/images/phone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/images/phone.png -------------------------------------------------------------------------------- /assets/images/place-dark.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/placeholder.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/images/placeholder.jpg -------------------------------------------------------------------------------- /assets/images/placeholder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/images/placeholder.png -------------------------------------------------------------------------------- /assets/images/profile-black.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/profile-white.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/images/q.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/images/q.png -------------------------------------------------------------------------------- /assets/images/seek.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/images/seek.png -------------------------------------------------------------------------------- /assets/images/shoot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/images/shoot.png -------------------------------------------------------------------------------- /assets/images/tv-static.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/images/tv-static.gif -------------------------------------------------------------------------------- /assets/images/welcome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/images/welcome.png -------------------------------------------------------------------------------- /assets/notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/notification.png -------------------------------------------------------------------------------- /assets/qc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/qc.png -------------------------------------------------------------------------------- /assets/splash copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/splash copy.png -------------------------------------------------------------------------------- /assets/splash-lightmode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/splash-lightmode.png -------------------------------------------------------------------------------- /assets/splash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/assets/splash.png -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | return { 4 | presets: ["babel-preset-expo"], 5 | plugins: ["react-native-reanimated/plugin"], 6 | env: { 7 | production: { 8 | plugins: ["react-native-paper/babel","transform-remove-console"], 9 | }, 10 | }, 11 | }; 12 | }; 13 | -------------------------------------------------------------------------------- /bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/bun.lockb -------------------------------------------------------------------------------- /components/chat/ChatBox.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, TextInput, Pressable, TextInputProps,Platform } from "react-native"; 2 | import React from "react"; 3 | import { BlurView } from "expo-blur"; 4 | import { SendIcon } from "../icons"; 5 | import useGetMode from "../../hooks/GetMode"; 6 | import { IChatMessage } from "../../types/api"; 7 | import PickImageButton from "./PickImageButton"; 8 | 9 | export default function ChatBox({ 10 | props, 11 | onPress, 12 | handleSetPhotoPost, 13 | }: { 14 | props: TextInputProps; 15 | onPress: () => void; 16 | handleSetPhotoPost: (mimeType: string, uri: string, size: number) => void; 17 | }) { 18 | const dark = useGetMode(); 19 | const color = dark ? "white" : "black"; 20 | const tint = dark ? "dark" : "light"; 21 | const rippleColor = dark ? "#000000" : "#A1A0A0"; 22 | return ( 23 | 36 | 42 | 43 | 58 | 59 | 68 | 80 | 81 | 82 | 83 | 84 | 85 | ); 86 | } 87 | -------------------------------------------------------------------------------- /components/chat/PickImageButton.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, Pressable } from "react-native"; 2 | import React from "react"; 3 | import { CameraIcon } from "../icons"; 4 | import ImagePicker from "react-native-image-crop-picker"; 5 | import useGetMode from "../../hooks/GetMode"; 6 | export default function PickImageButton({ 7 | handleSetPhotoPost, 8 | }: { 9 | handleSetPhotoPost: (mimeType: string, uri: string, size: number) => void; 10 | }) { 11 | const dark = useGetMode(); 12 | const backgroundColor = dark ? "white" : "black"; 13 | const backgroundColorView = "#FD5E02" ; 14 | const rippleColor = !dark ? "#ABABAB" : "#55555500"; 15 | 16 | return ( 17 | 29 | { 31 | ImagePicker.openPicker({ 32 | cropperStatusBarColor: "#000000", 33 | cropperToolbarColor: "#000000", 34 | showCropGuidelines: false, 35 | cropperTintColor: "red", 36 | cropperActiveWidgetColor: "red", 37 | mediaType: "photo", 38 | cropperToolbarWidgetColor: "#FFFFFF", 39 | cropperCancelText: "#FFFFFF", 40 | cropperChooseColor: "#FFFFFF", 41 | }) 42 | .then((image) => { 43 | handleSetPhotoPost(image?.mime, image?.path, image?.size); 44 | }) 45 | .catch((e) => {}); 46 | }} 47 | android_ripple={{ color: rippleColor, foreground: true }} 48 | style={{ 49 | width: 30, 50 | height: 30, 51 | justifyContent: "center", 52 | alignItems: "center", 53 | }} 54 | > 55 | 56 | 57 | 58 | ); 59 | } 60 | -------------------------------------------------------------------------------- /components/chat/TypingBox.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, Dimensions } from "react-native"; 2 | import React, { useEffect, useRef } from "react"; 3 | import useGetMode from "../../hooks/GetMode"; 4 | import { formatDateForChat } from "../../util/date"; 5 | import Lottie from "lottie-react-native"; 6 | import Animated, { 7 | FadeIn, 8 | FadeInDown, 9 | FadeInUp, 10 | FadeOutDown, 11 | FadeOutLeft, 12 | } from "react-native-reanimated"; 13 | const { width } = Dimensions.get("window"); 14 | export default function TypingBox() { 15 | const dark = useGetMode(); 16 | const backgroundColorForMe = dark ? "#35383A" : "#0c81f8"; 17 | const backgroundColor = dark ? "#181B1D" : "#e8e8eb"; 18 | const color = dark ? "white" : "black"; 19 | const animationRef = useRef(null); 20 | 21 | useEffect(() => { 22 | animationRef.current?.play(); 23 | 24 | return () => { 25 | animationRef.current?.reset(); 26 | }; 27 | }, []); 28 | return ( 29 | 34 | 35 | 47 | 55 | 64 | 65 | 66 | 67 | 68 | ); 69 | } 70 | -------------------------------------------------------------------------------- /components/discover/HeaderTag/index.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, Pressable } from "react-native"; 2 | import React from "react"; 3 | import useGetMode from "../../../hooks/GetMode"; 4 | 5 | export default function HeaderTag({ 6 | text, 7 | onPress, 8 | selected, 9 | }: { 10 | text: string; 11 | onPress: () => void; 12 | selected: boolean; 13 | }) { 14 | const dark = useGetMode(); 15 | const color = !dark ? "white" : "black"; 16 | const backgroundColor = !dark ? "black" : "white"; 17 | return ( 18 | 28 | 42 | 43 | {text} 44 | 45 | 46 | 47 | ); 48 | } 49 | -------------------------------------------------------------------------------- /components/discover/SearchBar/index.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | View, 3 | Text, 4 | TextInput, 5 | StyleProp, 6 | ViewStyle, 7 | Dimensions, 8 | } from "react-native"; 9 | import useGetMode from "../../../hooks/GetMode"; 10 | import Animated, { FadeInRight } from "react-native-reanimated"; 11 | import { useCallback, useEffect, useMemo, useState } from "react"; 12 | import { useDebounce } from "../../../hooks/Debounce"; 13 | import { 14 | useLazySearchPeopleQuery, 15 | useLazySearchPostsQuery, 16 | } from "../../../redux/api/services"; 17 | import { useSafeAreaInsets } from "react-native-safe-area-context"; 18 | 19 | const { width } = Dimensions.get("window"); 20 | export default function SearchBar() { 21 | const dark = useGetMode(); 22 | const [searchParam, setSearchParam] = useState(""); 23 | const color = dark ? "white" : "black"; 24 | const placeholderColor = !dark ? "grey" : "grey"; 25 | const borderColor = dark ? "#FFFFFF" : "#DAD9D9"; 26 | const backgroundColor = dark ? "#383838" : "#EAEBEB"; 27 | const query = useDebounce(searchParam, 1000); 28 | const insets = useSafeAreaInsets(); 29 | const [getSearchPosts, res] = useLazySearchPostsQuery(); 30 | const [getSearchPeople] = useLazySearchPeopleQuery(); 31 | 32 | useEffect(() => { 33 | if (query) { 34 | getSearchPosts({ q: query }); 35 | getSearchPeople({ q: query }); 36 | } 37 | }, [query]); 38 | 39 | return ( 40 | 56 | setSearchParam(text)} 60 | placeholderTextColor={placeholderColor} 61 | style={{ 62 | width: "100%", 63 | fontSize: 16, 64 | color, 65 | fontFamily: "jakara", 66 | includeFontPadding: false, 67 | }} 68 | /> 69 | 70 | ); 71 | } 72 | -------------------------------------------------------------------------------- /components/discover/Skeleton/PostSearchSkeleton.tsx: -------------------------------------------------------------------------------- 1 | import { Dimensions, Text, View } from "react-native"; 2 | import useGetMode from "../../../hooks/GetMode"; 3 | 4 | const { width } = Dimensions.get("window"); 5 | 6 | export const PostSearchSkeleton = () => { 7 | const dark = useGetMode(); 8 | const backgroundColor = dark ? "#343434" : "#BBBBBB"; 9 | return ( 10 | 11 | 12 | 20 | 21 | 22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /components/discover/Skeleton/SearchSkeleton.tsx: -------------------------------------------------------------------------------- 1 | import { Dimensions, Text, View } from "react-native"; 2 | import useGetMode from "../../../hooks/GetMode"; 3 | 4 | const { width } = Dimensions.get("window"); 5 | 6 | export const SearchSkeleton = () => { 7 | const dark = useGetMode(); 8 | const shimmerColors = dark 9 | ? ["#4C4C4C", "#696969", "#383838"] 10 | : ["#ebebeb", "#c5c5c5", "#ebebeb"]; 11 | const backgroundColor = dark ? "#343434" : "#BBBBBB"; 12 | return ( 13 | 14 | 15 | 23 | 24 | 25 | ); 26 | }; 27 | -------------------------------------------------------------------------------- /components/editProfile/EditContent.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, Pressable } from "react-native"; 2 | import useGetMode from "../../hooks/GetMode"; 3 | 4 | export default function EditContent({ 5 | text, 6 | Icon, 7 | color, 8 | onPress, 9 | }: { 10 | text: string; 11 | Icon: React.ElementType; 12 | color: string; 13 | onPress: () => void; 14 | }) { 15 | const dark = useGetMode(); 16 | const backgroundColor = !dark ? "#E5E9F899" : "#25252599"; 17 | const textColor = !dark ? "black" : "white"; 18 | const rColor = !dark ? "#00000014" : "#BBBBBB"; 19 | return ( 20 | 21 | 22 | 33 | 34 | 42 | {text} 43 | 44 | 45 | 46 | 47 | ); 48 | } 49 | -------------------------------------------------------------------------------- /components/global/AnimatedScreen/FadeInView.tsx: -------------------------------------------------------------------------------- 1 | import { PropsWithChildren, useRef, useEffect } from "react"; 2 | import { ViewStyle, Animated } from "react-native"; 3 | 4 | type FadeInViewProps = PropsWithChildren<{ style: ViewStyle }>; 5 | 6 | export const FadeInView: React.FC = (props) => { 7 | const fadeAnim = useRef(new Animated.Value(0)).current; // Initial value for opacity: 0 8 | 9 | useEffect(() => { 10 | Animated.timing(fadeAnim, { 11 | toValue: 1, 12 | 13 | duration: 1000, 14 | useNativeDriver: true, 15 | }).start(); 16 | }, [fadeAnim]); 17 | 18 | return ( 19 | 25 | {props.children} 26 | 27 | ); 28 | }; 29 | -------------------------------------------------------------------------------- /components/global/AnimatedScreen/index.tsx: -------------------------------------------------------------------------------- 1 | import { ReactNode, useCallback, useEffect } from "react"; 2 | 3 | import Animated, { 4 | interpolate, 5 | useAnimatedStyle, 6 | useSharedValue, 7 | withTiming, 8 | } from "react-native-reanimated"; 9 | import { useFocusEffect, useRoute } from "@react-navigation/native"; 10 | import { 11 | ImageBackground, 12 | StyleProp, 13 | View, 14 | ViewStyle, 15 | useColorScheme, 16 | } from "react-native"; 17 | import useGetMode from "../../../hooks/GetMode"; 18 | import { Image } from "expo-image"; 19 | 20 | export default function AnimatedScreen({ 21 | children, 22 | style, 23 | }: { 24 | children: ReactNode; 25 | style?: ViewStyle; 26 | }) { 27 | const opacity = useSharedValue(0); 28 | const animatedStyle = useAnimatedStyle(() => { 29 | return { 30 | opacity: interpolate(opacity.value, [0, 1], [0, 1]), // map opacity value to range between 0 and 1 31 | }; 32 | }); 33 | 34 | useFocusEffect( 35 | useCallback(() => { 36 | opacity.value = withTiming(1, { duration: 250 }); 37 | 38 | return () => { 39 | Image.clearMemoryCache(); 40 | opacity.value = withTiming(0, { duration: 250 }); 41 | }; 42 | }, [opacity]) 43 | ); 44 | return ( 45 | 46 | 53 | {children} 54 | 55 | 56 | ); 57 | } 58 | -------------------------------------------------------------------------------- /components/global/BottomSheetContainer/components/CheckBoxPair.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text } from "react-native"; 2 | import BouncyCheckbox from "react-native-bouncy-checkbox"; 3 | import { useAppDispatch } from "../../../../redux/hooks/hooks"; 4 | import { setMode } from "../../../../redux/slice/prefs"; 5 | import useGetMode from "../../../../hooks/GetMode"; 6 | 7 | export default function CheckBoxPair({ 8 | text, 9 | type, 10 | checked, 11 | }: { 12 | text: string; 13 | checked: boolean; 14 | type: "system" | "light" | "dark"; 15 | }) { 16 | const dispatch = useAppDispatch(); 17 | const dark = useGetMode(); 18 | const color = !dark ? "black" : "white"; 19 | const fillColor = !dark ? "black" : "white"; 20 | const unFillColor = !dark ? "#505050" : "#757575"; 21 | const handleUpdateMode = ()=>{ 22 | dispatch(setMode({ mode: type })); 23 | } 24 | return ( 25 | 36 | 45 | {text} 46 | 47 | 48 | 58 | 59 | 60 | ); 61 | } 62 | -------------------------------------------------------------------------------- /components/global/BottomSheetContainer/components/CustomBg.tsx: -------------------------------------------------------------------------------- 1 | import React, { useMemo } from "react"; 2 | import { BottomSheetBackgroundProps } from "@gorhom/bottom-sheet"; 3 | import Animated, { 4 | useAnimatedStyle, 5 | interpolateColor, 6 | } from "react-native-reanimated"; 7 | import { View, useColorScheme } from "react-native"; 8 | import { BlurView } from "expo-blur"; 9 | import useGetMode from "../../../../hooks/GetMode"; 10 | import { useAppSelector } from "../../../../redux/hooks/hooks"; 11 | 12 | export const CustomBackground: React.FC = ({ 13 | style, 14 | animatedIndex, 15 | }) => { 16 | //#region styles 17 | const dark = useGetMode(); 18 | 19 | const isDarkTheme = dark; 20 | const tint = isDarkTheme ? "dark": "light" 21 | const backgroundColor = isDarkTheme ? "white": "black" 22 | const containerAnimatedStyle = useAnimatedStyle(() => ({ 23 | // @ts-ignore 24 | backgroundColor: interpolateColor( 25 | animatedIndex.value, 26 | [0, 1], 27 | ["#D7EBA800", isDarkTheme ? "#06060600" : "#D7EBA800"] 28 | ), 29 | })); 30 | 31 | const containerStyle = useMemo( 32 | () => [style, containerAnimatedStyle], 33 | [style, containerAnimatedStyle] 34 | ); 35 | const isHighEndDevice = useAppSelector((state) => state?.prefs?.isHighEnd); 36 | // render 37 | return ( 38 | <> 39 | 43 | 49 | 50 | 51 | 52 | ); 53 | }; 54 | 55 | export default CustomBackground; 56 | -------------------------------------------------------------------------------- /components/global/BottomSheetContainer/components/DarkModeView.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text } from "react-native"; 2 | 3 | import CheckBoxPair from "./CheckBoxPair"; 4 | import { useEffect, useMemo, useState } from "react"; 5 | import { useAppSelector } from "../../../../redux/hooks/hooks"; 6 | import useGetMode from "../../../../hooks/GetMode"; 7 | 8 | export default function DarkModeView() { 9 | const mode = useAppSelector((state) => state?.prefs?.mode); 10 | const dark = useGetMode(); 11 | const backgroundColor = dark ? "#969696" : "#B5AEAE"; 12 | const color = dark ? "#FFFFFF" : "#000000"; 13 | const [checked, setChecked] = useState(() => { 14 | return { 15 | system: mode === "system", 16 | dark: mode === "dark", 17 | light: mode === "light", 18 | }; 19 | }); 20 | 21 | useMemo(() => { 22 | setChecked({ 23 | system: mode === "system" ? true : false, 24 | dark: mode === "dark" ? true : false, 25 | light: mode === "light" ? true : false, 26 | }); 27 | }, [mode]); 28 | 29 | return ( 30 | 31 | 32 | 33 | Dark mode 34 | 35 | 36 | 37 | 45 | 46 | 47 | 52 | 53 | 54 | ); 55 | } 56 | -------------------------------------------------------------------------------- /components/global/Buttons/AddPostButton.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, Pressable } from "react-native"; 2 | import React from "react"; 3 | import { AddIcon } from "../../icons"; 4 | 5 | export default function AddPostButton() { 6 | return ( 7 | 15 | 22 | 23 | 24 | 25 | ); 26 | } 27 | -------------------------------------------------------------------------------- /components/global/Buttons/BottomBarButtons.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, Pressable, useColorScheme } from "react-native"; 2 | import React, { ElementType } from "react"; 3 | import { useNavigation } from "@react-navigation/native"; 4 | import { HomeNavigationProp, RootStackParamList } from "../../../types/navigation"; 5 | import useGetMode from "../../../hooks/GetMode"; 6 | 7 | export default function IconButtons({ 8 | Icon, 9 | onPress, 10 | }: { 11 | Icon: ElementType; 12 | onPress: () => void; 13 | }) { 14 | const navigate = useNavigation(); 15 | const dark = useGetMode(); 16 | const isDark = dark; 17 | const color = isDark ? "white" : "black"; 18 | return ( 19 | 29 | { 42 | onPress(); 43 | 44 | }} 45 | > 46 | 47 | 48 | 49 | ); 50 | } 51 | -------------------------------------------------------------------------------- /components/global/Buttons/Button.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | View, 3 | Text, 4 | Pressable, 5 | useColorScheme, 6 | ActivityIndicator, 7 | } from "react-native"; 8 | import React, { ReactNode } from "react"; 9 | import useGetMode from "../../../hooks/GetMode"; 10 | 11 | export default function Button({ 12 | children, 13 | onPress, 14 | loading, 15 | }: { 16 | children: ReactNode; 17 | onPress: () => void; 18 | loading: boolean; 19 | }) { 20 | const dark = useGetMode(); 21 | const isDark = dark; 22 | const backgroundColor = isDark ? "white" : "black"; 23 | const color = !isDark ? "white" : "black"; 24 | const loadingColor = isDark ? "black" : "white"; 25 | return ( 26 | 35 | 47 | {loading ? : children} 48 | 49 | 50 | ); 51 | } 52 | -------------------------------------------------------------------------------- /components/global/Buttons/IconButton.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, Pressable } from "react-native"; 2 | import React, { ElementType } from "react"; 3 | 4 | export type IconButton = { Icon: JSX.Element; onPress: () => void }; 5 | 6 | export default function IconButton({ Icon, onPress }: IconButton) { 7 | return ( 8 | 9 | 12 | {Icon} 13 | 14 | 15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /components/global/Modal/LoadingOverlay.tsx: -------------------------------------------------------------------------------- 1 | import { BlurView } from "expo-blur"; 2 | import React, { useState } from "react"; 3 | import { 4 | Alert, 5 | Modal, 6 | StyleSheet, 7 | Text, 8 | Pressable, 9 | View, 10 | Dimensions, 11 | } from "react-native"; 12 | import { ActivityIndicator, Portal } from "react-native-paper"; 13 | import useGetMode from "../../../hooks/GetMode"; 14 | import { useAppDispatch, useAppSelector } from "../../../redux/hooks/hooks"; 15 | import { 16 | closeLoadingModal, 17 | openLoadingModal, 18 | } from "../../../redux/slice/modal/loading"; 19 | 20 | const { height, width } = Dimensions.get("screen"); 21 | export const LoadingModal = () => { 22 | const loadingModal = useAppSelector((state) => state.loadingModal); 23 | const dispatch = useAppDispatch(); 24 | const dark = useGetMode(); 25 | const color = !dark ? "black" : "white"; 26 | const tint = dark ? "dark" : "light"; 27 | const isHighEndDevice = useAppSelector((state) => state?.prefs?.isHighEnd); 28 | return ( 29 | 30 | 31 | { 37 | dispatch(closeLoadingModal()); 38 | }} 39 | > 40 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | ); 54 | }; 55 | 56 | const styles = StyleSheet.create({ 57 | centeredView: { 58 | flex: 1, 59 | justifyContent: "center", 60 | alignItems: "center", 61 | }, 62 | }); 63 | -------------------------------------------------------------------------------- /components/home/header/CustomDrawerHeader.tsx: -------------------------------------------------------------------------------- 1 | import { BlurView } from "expo-blur"; 2 | import { 3 | View, 4 | Text, 5 | StyleSheet, 6 | SafeAreaView, 7 | useColorScheme, 8 | } from "react-native"; 9 | import { useNavigation } from "@react-navigation/native"; 10 | import ProfileButton from "./ProfileButton"; 11 | import React from "react"; 12 | import { HomeNavigationProp } from "../../../types/navigation"; 13 | import Animated from "react-native-reanimated"; 14 | import { 15 | DrawerHeaderProps, 16 | DrawerProps, 17 | } from "@react-navigation/drawer/lib/typescript/src/types"; 18 | import useGetMode from "../../../hooks/GetMode"; 19 | import { useAppSelector } from "../../../redux/hooks/hooks"; 20 | function CustomDrawerHeader(props: DrawerHeaderProps) { 21 | const navigation = useNavigation(); 22 | const dark = useGetMode(); 23 | const isDark = dark; 24 | const TextColor = isDark ? "white" : "black"; 25 | const isHighEndDevice = useAppSelector((state) => state?.prefs?.isHighEnd); 26 | return ( 27 | 28 | 37 | 38 | 39 | props.navigation.toggleDrawer()} 41 | size={45} 42 | color={isDark ? "white" : "black"} 43 | /> 44 | 45 | 46 | 47 | 48 | {props.options.title} 49 | 50 | 51 | 52 | 53 | 54 | 55 | ); 56 | } 57 | 58 | export default React.memo(CustomDrawerHeader); 59 | const style = StyleSheet.create({ 60 | blurView: { 61 | position: "absolute", 62 | top: 0, 63 | left: 0, 64 | height: 90, 65 | paddingHorizontal: 10, 66 | borderBlockColor: "#0000002F", 67 | borderBottomWidth: 0.5, 68 | right: 0, 69 | alignItems: "center", 70 | }, 71 | titleView: { 72 | paddingTop: 44, 73 | paddingBottom: 10, 74 | width: "100%", 75 | height: "100%", 76 | flexDirection: "row", 77 | alignItems: "center", 78 | }, 79 | headerStyle: { 80 | fontFamily: "instaBold", 81 | fontSize: 20, 82 | }, 83 | }); 84 | -------------------------------------------------------------------------------- /components/home/header/ProfileButton.tsx: -------------------------------------------------------------------------------- 1 | import { Pressable, StyleProp, View, ViewStyle } from "react-native"; 2 | import { ProfileIcon } from "../../icons"; 3 | import { ViewProps } from "react-native-svg/lib/typescript/fabric/utils"; 4 | import { useAppSelector } from "../../../redux/hooks/hooks"; 5 | import { Image } from "expo-image"; 6 | import useGetMode from "../../../hooks/GetMode"; 7 | 8 | type ProfileButtonType = { 9 | onPress: () => void; 10 | color: string; 11 | size: number; 12 | style?: StyleProp; 13 | }; 14 | export default function ProfileButton({ 15 | onPress, 16 | color, 17 | size, 18 | style, 19 | }: ProfileButtonType) { 20 | const imageUri = useAppSelector((state) => state.user.data?.imageUri); 21 | const dark = useGetMode(); 22 | return ( 23 | 24 | 25 | {imageUri ? ( 26 | 36 | ) : ( 37 | 38 | )} 39 | 40 | 41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /components/home/misc/EmptyList.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, Pressable } from "react-native"; 2 | import React from "react"; 3 | import Animated, { FadeInDown, FadeOutDown } from "react-native-reanimated"; 4 | import EmptyLottie from "../post/components/EmptyLottie"; 5 | import useGetMode from "../../../hooks/GetMode"; 6 | import { ReloadIcon } from "../../icons"; 7 | import { useLazyGetAllPostsQuery } from "../../../redux/api/services"; 8 | 9 | export default function EmptyList({handleRefetch}:{handleRefetch:()=>void}) { 10 | const dark = useGetMode(); 11 | const isDark = dark; 12 | const [getPosts] = useLazyGetAllPostsQuery(); 13 | const color = isDark ? "white" : "black"; 14 | const backgroundColor = !isDark ? "#FFFFFFD2" : "#0000008F"; 15 | return ( 16 | 17 | 27 | 28 | 41 | 55 | 56 | 57 | 58 | 59 | 60 | ); 61 | } 62 | -------------------------------------------------------------------------------- /components/home/misc/Skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { Dimensions, Text, View } from "react-native"; 2 | import useGetMode from "../../../hooks/GetMode"; 3 | 4 | const { width } = Dimensions.get("window"); 5 | export const Skeleton = () => { 6 | const dark = useGetMode(); 7 | const shimmerColors = dark 8 | ? ["#4C4C4C", "#696969", "#383838"] 9 | : ["#ebebeb", "#c5c5c5", "#ebebeb"]; 10 | 11 | const backgroundColor = dark ? "#343434" : "#BBBBBB"; 12 | return ( 13 | 14 | 17 | 18 | 26 | 34 | 35 | 43 | 44 | 45 | ); 46 | }; 47 | -------------------------------------------------------------------------------- /components/home/misc/SkeletonGroupPost.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text } from "react-native"; 2 | import React, { useEffect } from "react"; 3 | import { Skeleton } from "./Skeleton"; 4 | import Animated, { 5 | cancelAnimation, 6 | interpolate, 7 | useAnimatedStyle, 8 | useSharedValue, 9 | withRepeat, 10 | withTiming, 11 | } from "react-native-reanimated"; 12 | 13 | export default function SkeletonGroupPost() { 14 | const opacity = useSharedValue(0); 15 | const animatedStyle = useAnimatedStyle(() => { 16 | return { 17 | opacity: interpolate(opacity.value, [0, 1], [1, 0]), 18 | }; 19 | }); 20 | 21 | useEffect(() => { 22 | opacity.value = withRepeat(withTiming(1, { duration: 900 }), -1, true); 23 | return () => { 24 | cancelAnimation(opacity); 25 | }; 26 | }, []); 27 | 28 | return ( 29 | 35 | {[0, 1, 2].map((idx) => ( 36 | 37 | ))} 38 | 39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /components/home/post/comment/PostButton.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, Pressable } from "react-native"; 2 | import React from "react"; 3 | import useGetMode from "../../../../hooks/GetMode"; 4 | import Animated, { 5 | BounceIn, 6 | BounceOut, 7 | FadeInDown, 8 | FadeInUp, 9 | FadeOutDown, 10 | } from "react-native-reanimated"; 11 | 12 | export default function CommentButton({ 13 | isLoading, 14 | isDisabled, 15 | onPress, 16 | }: { 17 | isLoading: boolean; 18 | isDisabled?: boolean; 19 | onPress: () => void; 20 | }) { 21 | const dark = useGetMode(); 22 | 23 | const backgroundColor = dark ? "white" : "black"; 24 | const backgroundColorLoad = dark ? "#FFFFFF38" : "#00000041"; 25 | const rippleColor = !dark ? "white" : "black"; 26 | const color = !dark ? "white" : "black"; 27 | return ( 28 | 40 | 53 | Post 54 | 55 | 56 | ); 57 | } 58 | -------------------------------------------------------------------------------- /components/home/post/components/AudioPlayLottie.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from "react"; 2 | import Lottie from "lottie-react-native"; 3 | import { View } from "react-native"; 4 | import { useAppSelector } from "../../../../redux/hooks/hooks"; 5 | import { Image } from "expo-image"; 6 | 7 | 8 | export default function AudioPlayLottie({ 9 | animationRef, 10 | src, 11 | }: { 12 | animationRef: React.RefObject; 13 | src: string; 14 | }) { 15 | useEffect(() => { 16 | animationRef.current?.pause(); 17 | }, []); 18 | 19 | return ( 20 | 28 | 38 | 42 | 43 | 48 | 49 | ); 50 | } 51 | -------------------------------------------------------------------------------- /components/home/post/components/EmptyLottie.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from "react"; 2 | import Lottie from "lottie-react-native"; 3 | import { Dimensions } from "react-native"; 4 | const { width } = Dimensions.get("window"); 5 | export default function EmptyLottie() { 6 | const lottieRef = useRef(null); 7 | 8 | useEffect(() => { 9 | lottieRef.current?.play(); 10 | return () => lottieRef.current?.pause(); 11 | }, []); 12 | 13 | return ( 14 | 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /components/home/post/components/Fab.tsx: -------------------------------------------------------------------------------- 1 | import { BlurView } from "expo-blur"; 2 | import { View, Pressable } from "react-native"; 3 | import useGetMode from "../../../../hooks/GetMode"; 4 | import { useNavigation } from "@react-navigation/native"; 5 | import { HomeNavigationProp } from "../../../../types/navigation"; 6 | import DeviceInfo from "react-native-device-info"; 7 | import { useAppSelector } from "../../../../redux/hooks/hooks"; 8 | 9 | export default function Fab({ item }: { item: JSX.Element }) { 10 | const dark = useGetMode(); 11 | const isDark = dark; 12 | const navigation = useNavigation(); 13 | const tint = isDark ? "dark" : "light"; 14 | const backgroundColor = !isDark ? "#DEDEDE" : "#303030"; 15 | const isHighEndDevice = useAppSelector((state) => state?.prefs?.isHighEnd); 16 | 17 | return ( 18 | 36 | { 39 | navigation.navigate("PostContent"); 40 | }} 41 | style={{ 42 | height: "100%", 43 | width: "100%", 44 | alignItems: "center", 45 | justifyContent: "center", 46 | }} 47 | > 48 | <> 49 | {isHighEndDevice && ( 50 | 63 | )} 64 | {item} 65 | 66 | 67 | 68 | ); 69 | } 70 | -------------------------------------------------------------------------------- /components/home/post/components/LoadingIndicator.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import { ActivityIndicator } from "react-native"; 3 | 4 | function Loading() { 5 | return ; 6 | } 7 | 8 | export default React.memo(Loading); 9 | -------------------------------------------------------------------------------- /components/home/post/components/NameAndTagFullScreen.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, useColorScheme } from "react-native"; 2 | import React from "react"; 3 | import { VerifiedIcon } from "../../../icons"; 4 | import useGetMode from "../../../../hooks/GetMode"; 5 | 6 | export default function NameAndTagFullScreen({ 7 | name, 8 | verified, 9 | 10 | userTag, 11 | }: { 12 | name: string; 13 | 14 | verified: boolean; 15 | userTag: string; 16 | }) { 17 | const dark = useGetMode(); 18 | const isDark = dark; 19 | const color = isDark ? "white" : "black"; 20 | const backgroundColor = isDark ? "white" : "black"; 21 | return ( 22 | 23 | 24 | 25 | 33 | {name} 34 | 35 | {verified && } 36 | 37 | 38 | 47 | @{userTag} 48 | 49 | 50 | 51 | ); 52 | } 53 | -------------------------------------------------------------------------------- /components/home/post/components/PhotoPost.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | View, 3 | Text, 4 | FlatList, 5 | Pressable, 6 | Button, 7 | Image as RNImage, 8 | } from "react-native"; 9 | import { Image } from "expo-image"; 10 | import { useNavigation } from "@react-navigation/native"; 11 | import { HomeNavigationProp } from "../../../../types/navigation"; 12 | import { useState } from "react"; 13 | 14 | export default function PhotoPost({ 15 | photoUri, 16 | width, 17 | height, 18 | id, 19 | }: { 20 | photoUri: string; 21 | width: number; 22 | height: number; 23 | id: string; 24 | }) { 25 | const navigation = useNavigation(); 26 | return ( 27 | 39 | { 42 | navigation.navigate("ImageFullScreen", { 43 | photoUri: photoUri, 44 | id, 45 | height, 46 | width, 47 | }); 48 | }} 49 | style={{ 50 | width: "100%", 51 | height: 200, 52 | borderRadius: 15, 53 | }} 54 | > 55 | 63 | 64 | 65 | ); 66 | } 67 | -------------------------------------------------------------------------------- /components/home/post/components/PhotoPostFullScreen.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | View, 3 | Text, 4 | FlatList, 5 | Pressable, 6 | Button, 7 | Image as RNImage, 8 | } from "react-native"; 9 | import { Image } from "expo-image"; 10 | import { useNavigation } from "@react-navigation/native"; 11 | import { HomeNavigationProp } from "../../../../types/navigation"; 12 | import { useState } from "react"; 13 | 14 | export default function PhotoPost({ 15 | photoUri, 16 | width, 17 | height, 18 | id, 19 | }: { 20 | photoUri: string; 21 | width: number; 22 | height: number; 23 | id: string; 24 | }) { 25 | const navigation = useNavigation(); 26 | return ( 27 | 39 | { 42 | navigation.navigate("ImageFullScreen", { 43 | photoUri: photoUri, 44 | id, 45 | height, 46 | width, 47 | }); 48 | }} 49 | style={{ 50 | width: "100%", 51 | height: 200, 52 | borderRadius: 15, 53 | }} 54 | > 55 | 61 | 62 | 63 | ); 64 | } 65 | -------------------------------------------------------------------------------- /components/home/post/components/ProfileImage.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text } from "react-native"; 2 | import React from "react"; 3 | import { Image } from "expo-image"; 4 | import useGetMode from "../../../../hooks/GetMode"; 5 | 6 | export default function ProfileImage({ imageUri }: { imageUri: string }) { 7 | const dark = useGetMode() 8 | return ( 9 | 10 | 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /components/home/post/components/RingAudio.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from "react"; 2 | import Lottie from "lottie-react-native"; 3 | import { View } from "react-native"; 4 | import { useAppSelector } from "../../../../redux/hooks/hooks"; 5 | import { Image } from "expo-image"; 6 | 7 | 8 | 9 | export default function RingAudio({ 10 | animationRef, 11 | }: { 12 | animationRef: React.RefObject; 13 | }) { 14 | useEffect(() => { 15 | animationRef.current?.pause(); 16 | }, []); 17 | const userImage = useAppSelector((state) => state.user.data?.imageUri); 18 | return ( 19 | 27 | 37 | 41 | 42 | 47 | 48 | ); 49 | } 50 | -------------------------------------------------------------------------------- /components/home/post/components/TextPost.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, useColorScheme } from "react-native"; 2 | import React from "react"; 3 | import useGetMode from "../../../../hooks/GetMode"; 4 | 5 | export default function TextPost({ 6 | postText, 7 | photoUri, 8 | videoUri, 9 | }: { 10 | postText: string; 11 | photoUri: string[]; 12 | videoUri?: string; 13 | }) { 14 | const dark = useGetMode(); 15 | const isDark = dark; 16 | const color = isDark ? "white" : "black"; 17 | const selectionColor = isDark ? "#C5C5C591" : "#0000007A" 18 | return ( 19 | 0 || videoUri ? 2 : 10, 26 | color, 27 | }} 28 | > 29 | {postText} 30 | 31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /components/home/post/components/VideoPost.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | View, 3 | Text, 4 | Pressable, 5 | ActivityIndicator, 6 | useColorScheme, 7 | } from "react-native"; 8 | import React, { useCallback, useEffect, useState } from "react"; 9 | import IconButton from "../../../global/Buttons/IconButton"; 10 | import { AVPlaybackStatus, ResizeMode, Video } from "expo-av"; 11 | import { PlayIcon } from "../../../icons"; 12 | import { Dimensions } from "react-native"; 13 | import { useNavigation } from "@react-navigation/native"; 14 | import Animated, { 15 | FadeIn, 16 | interpolate, 17 | useAnimatedStyle, 18 | useSharedValue, 19 | withDelay, 20 | withTiming, 21 | } from "react-native-reanimated"; 22 | import { Image } from "expo-image"; 23 | import { useFocusEffect } from "@react-navigation/native"; 24 | import useGetMode from "../../../../hooks/GetMode"; 25 | import { current } from "@reduxjs/toolkit"; 26 | import { HomeNavigationProp } from "../../../../types/navigation"; 27 | 28 | function VideoPost({ 29 | videoTitle, 30 | thumbNail, 31 | videoUri, 32 | imageUri, 33 | userTag, 34 | name, 35 | 36 | videoViews, 37 | }: { 38 | videoTitle?: string; 39 | imageUri: string; 40 | videoUri: string; 41 | thumbNail: string | null; 42 | name: string; 43 | userTag: string; 44 | videoViews?: string; 45 | }) { 46 | 47 | 48 | const navigation = useNavigation(); 49 | return ( 50 | 58 | 59 | 69 | { 71 | navigation.navigate("VideoFullScreen", { 72 | videoUri, 73 | videoTitle: videoTitle || "", 74 | videoViews: videoViews || "0", 75 | userTag, 76 | name, 77 | imageUri, 78 | thumbNail, 79 | }); 80 | }} 81 | > 82 | 83 | 84 | 85 | 90 | 91 | 92 | ); 93 | } 94 | 95 | export default VideoPost; 96 | -------------------------------------------------------------------------------- /components/home/post/misc/EngagementText.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text } from "react-native"; 2 | import React from "react"; 3 | import useGetMode from "../../../../hooks/GetMode"; 4 | 5 | export default function EngagementsText({ 6 | engage, 7 | engagementNumber, 8 | }: { 9 | engage: string; 10 | engagementNumber: number; 11 | }) { 12 | const dark = useGetMode(); 13 | 14 | const color = dark ? "white" : "black"; 15 | return ( 16 | 17 | 18 | {engagementNumber} 19 | 20 | 23 | {engage} 24 | {engagementNumber > 1 && "s"} 25 | 26 | 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /components/home/post/misc/Robot.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useRef } from "react"; 2 | import Lottie from "lottie-react-native"; 3 | import { View } from "react-native"; 4 | import { useAppSelector } from "../../../../redux/hooks/hooks"; 5 | import { Image } from "expo-image"; 6 | 7 | export default function Robot() { 8 | const animationRef = useRef(null); 9 | 10 | useEffect(() => { 11 | animationRef.current?.play(); 12 | 13 | }, []); 14 | return ( 15 | 23 | 29 | 30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /components/messages/ChatList/ChatListView.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, FlatList, ListRenderItem } from "react-native"; 2 | import React from "react"; 3 | import TypingBox from "../../chat/TypingBox"; 4 | import { IChatList } from "../../../types/api"; 5 | import Animated, { SequencedTransition } from "react-native-reanimated"; 6 | 7 | function ChatListView({ 8 | isTyping, 9 | messageText, 10 | userChats, 11 | renderItem, 12 | }: { 13 | isTyping: boolean; 14 | messageText: string; 15 | userChats?: IChatList; 16 | renderItem: ListRenderItem; 17 | }) { 18 | 19 | return ( 20 | 21 | { 26 | return ( 27 | 34 | {isTyping && messageText.length < 1 && } 35 | 36 | ); 37 | }} 38 | data={userChats?.messages} 39 | contentContainerStyle={{ gap: 15, padding: 20, paddingBottom: 100 }} 40 | renderItem={renderItem} 41 | /> 42 | 43 | ); 44 | } 45 | export default ChatListView; 46 | -------------------------------------------------------------------------------- /components/messages/ChatList/Fab.tsx: -------------------------------------------------------------------------------- 1 | import { View, Pressable } from "react-native"; 2 | import useGetMode from "../../../hooks/GetMode"; 3 | import { useNavigation } from "@react-navigation/native"; 4 | import { HomeNavigationProp } from "../../../types/navigation"; 5 | 6 | export default function Fab({ item }: { item: JSX.Element }) { 7 | const dark = useGetMode(); 8 | const isDark = dark; 9 | const navigation = useNavigation(); 10 | const backgroundColor = !isDark ? "#FFFFFF" : "#000000"; 11 | const color = isDark ? "#42424260" : "#BABABA64"; 12 | return ( 13 | 29 | { 32 | navigation.navigate("SearchUser"); 33 | }} 34 | style={{ 35 | height: "100%", 36 | width: "100%", 37 | alignItems: "center", 38 | justifyContent: "center", 39 | }} 40 | > 41 | <> 42 | {item} 43 | 44 | 45 | 46 | ); 47 | } 48 | -------------------------------------------------------------------------------- /components/messages/Recent/AvatarName.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, Pressable } from "react-native"; 2 | import React from "react"; 3 | 4 | import useGetMode from "../../../hooks/GetMode"; 5 | import Animated, { FadeInLeft, FadeOutLeft } from "react-native-reanimated"; 6 | import { useNavigation } from "@react-navigation/native"; 7 | import { HomeNavigationProp } from "../../../types/navigation"; 8 | import { ActivityIndicator } from "react-native-paper"; 9 | import { Image } from "expo-image"; 10 | 11 | export default function AvatarName({ 12 | userName, 13 | imageUri, 14 | id, 15 | receiverId, 16 | }: { 17 | userName: string; 18 | imageUri: string; 19 | id: string; 20 | receiverId: string; 21 | }) { 22 | const dark = useGetMode(); 23 | const color = dark ? "#FFFFFF" : "#000000"; 24 | const navigation = useNavigation(); 25 | return ( 26 | <> 27 | 28 | 30 | navigation.navigate("ChatScreen", { 31 | id: id, 32 | receiverId, 33 | name: userName, 34 | imageUri, 35 | }) 36 | } 37 | > 38 | 47 | 51 | 55 | @{userName} 56 | 57 | 58 | 59 | 60 | ); 61 | } 62 | -------------------------------------------------------------------------------- /components/messages/Recent/Me.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, Pressable } from "react-native"; 2 | import React from "react"; 3 | 4 | import useGetMode from "../../../hooks/GetMode"; 5 | import Animated, { FadeInLeft, FadeOutLeft } from "react-native-reanimated"; 6 | import { useNavigation } from "@react-navigation/native"; 7 | import { HomeNavigationProp } from "../../../types/navigation"; 8 | import { ActivityIndicator } from "react-native-paper"; 9 | import { useAppSelector } from "../../../redux/hooks/hooks"; 10 | import { Image } from "expo-image"; 11 | 12 | export default function Me() { 13 | const dark = useGetMode(); 14 | const color = dark ? "#FFFFFF" : "#000000"; 15 | const user = useAppSelector((state) => state.user.data); 16 | return ( 17 | <> 18 | 19 | 28 | 32 | 36 | Me 37 | 38 | 39 | 40 | 41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /components/notifications/NotifLottie.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text } from "react-native"; 2 | import React, { useEffect, useRef } from "react"; 3 | import Lottie from "lottie-react-native"; 4 | 5 | export default function NotifLottie() { 6 | const animationRef = useRef(null); 7 | useEffect(() => { 8 | animationRef.current?.play(); 9 | }, []); 10 | return ( 11 | 20 | 25 | 26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /components/postContent/PickAudioButton.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, Pressable } from "react-native"; 2 | import React from "react"; 3 | import { AudioIcon, CameraIcon } from "../icons"; 4 | import DocumentPicker from "react-native-document-picker"; 5 | import useGetMode from "../../hooks/GetMode"; 6 | export default function PickAudioButton({ 7 | handleSetAudioPost, 8 | }: { 9 | handleSetAudioPost: ( 10 | mimeType: string, 11 | uri: string, 12 | size: number, 13 | name: string 14 | ) => void; 15 | }) { 16 | const dark = useGetMode(); 17 | const backgroundColor = dark ? "white" : "black"; 18 | const backgroundColorView = !dark ? "white" : "black"; 19 | const rippleColor = !dark ? "#ABABAB" : "#55555500"; 20 | return ( 21 | 34 | { 36 | DocumentPicker.pick({ type: "audio/mpeg" }) 37 | .then((e) => { 38 | 39 | handleSetAudioPost( 40 | e[0]?.type as string, 41 | e[0].uri, 42 | e[0]?.size || 0, 43 | e[0]?.name || "any.mp3" 44 | ); 45 | }) 46 | .catch((e) => {}); 47 | }} 48 | android_ripple={{ color: rippleColor, foreground: true }} 49 | style={{ 50 | width: 100, 51 | height: 100, 52 | justifyContent: "center", 53 | alignItems: "center", 54 | }} 55 | > 56 | 57 | 58 | 59 | ); 60 | } 61 | -------------------------------------------------------------------------------- /components/postContent/PickImageButton.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, Pressable } from "react-native"; 2 | import React from "react"; 3 | import { CameraIcon } from "../icons"; 4 | import ImagePicker from "react-native-image-crop-picker"; 5 | import useGetMode from "../../hooks/GetMode"; 6 | export default function PickImageButton({ 7 | handleSetPhotoPost, 8 | }: { 9 | handleSetPhotoPost: (mimeType: string, uri: string, size: number) => void; 10 | }) { 11 | const dark = useGetMode(); 12 | const backgroundColor = dark ? "white" : "black"; 13 | const backgroundColorView = !dark ? "white" : "black"; 14 | const rippleColor = !dark ? "#ABABAB" : "#55555500"; 15 | return ( 16 | 29 | { 31 | ImagePicker.openPicker({ 32 | cropping: true, 33 | cropperStatusBarColor: "#000000", 34 | cropperToolbarColor: "#000000", 35 | showCropGuidelines: false, 36 | cropperTintColor: "red", 37 | cropperActiveWidgetColor: "red", 38 | 39 | cropperToolbarWidgetColor: "#FFFFFF", 40 | cropperCancelText: "#FFFFFF", 41 | cropperChooseColor: "#FFFFFF", 42 | compressImageQuality: 0.5, 43 | }) 44 | .then((image) => { 45 | handleSetPhotoPost(image?.mime, image?.path, image?.size); 46 | }) 47 | .catch((e) => {}); 48 | }} 49 | android_ripple={{ color: rippleColor, foreground: true }} 50 | style={{ 51 | width: 100, 52 | height: 100, 53 | justifyContent: "center", 54 | alignItems: "center", 55 | }} 56 | > 57 | 58 | 59 | 60 | ); 61 | } 62 | -------------------------------------------------------------------------------- /components/postContent/PostButton.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, Pressable } from "react-native"; 2 | import React from "react"; 3 | import useGetMode from "../../hooks/GetMode"; 4 | import { useAppDispatch } from "../../redux/hooks/hooks"; 5 | import { openToast } from "../../redux/slice/toast/toast"; 6 | import { resetPost } from "../../redux/slice/post"; 7 | 8 | export default function PostButton({ 9 | isLoading, 10 | isDisabled, 11 | onPress, 12 | }: { 13 | isLoading: boolean; 14 | isDisabled?: boolean; 15 | onPress: () => void; 16 | }) { 17 | const dark = useGetMode(); 18 | const dispatch = useAppDispatch(); 19 | 20 | const backgroundColor = dark ? "white" : "black"; 21 | const backgroundColorLoad = dark ? "#FFFFFF38" : "#00000041"; 22 | const rippleColor = !dark ? "white" : "black"; 23 | const color = !dark ? "white" : "black"; 24 | return ( 25 | 36 | { 39 | dispatch(resetPost()); 40 | onPress(); 41 | }} 42 | android_ripple={{ color: rippleColor, foreground: true }} 43 | style={{ 44 | height: 45, 45 | width: 80, 46 | 47 | borderRadius: 9999, 48 | justifyContent: "center", 49 | alignItems: "center", 50 | }} 51 | > 52 | Post 53 | 54 | 55 | ); 56 | } 57 | -------------------------------------------------------------------------------- /components/postContent/TextArea.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, TextInput, Dimensions } from "react-native"; 2 | import React, { useState } from "react"; 3 | 4 | import InputText from "../../screen/Auth/components/InputText"; 5 | import useGetMode from "../../hooks/GetMode"; 6 | import { useAppSelector } from "../../redux/hooks/hooks"; 7 | import { ProfileIcon } from "../icons"; 8 | import { Image } from "expo-image"; 9 | 10 | const heightFromScreen = Dimensions.get("window").height; 11 | export default function TextArea({ 12 | handlePostText, 13 | }: { 14 | handlePostText: (text: string) => void; 15 | }) { 16 | const dark = useGetMode(); 17 | const color = dark ? "white" : "black"; 18 | const [height, setHeight] = useState(50); 19 | const userDetails = useAppSelector((state) => state.user.data); 20 | return ( 21 | 22 | 23 | {userDetails?.imageUri ? ( 24 | 28 | ) : ( 29 | 30 | )} 31 | 38 | @{userDetails?.userName} 39 | 40 | 41 | 42 | { 48 | setHeight(event.nativeEvent.contentSize.height); 49 | }} 50 | style={{ 51 | fontSize: 16, 52 | color, 53 | 54 | fontFamily: "mulishMedium", 55 | minHeight: height, 56 | alignItems: "flex-start", 57 | }} 58 | placeholderTextColor={"grey"} 59 | placeholder="What's happening?" 60 | /> 61 | 62 | 63 | ); 64 | } 65 | -------------------------------------------------------------------------------- /components/postContent/VideoTextArea.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | View, 3 | Text, 4 | TextInput, 5 | Dimensions, 6 | TextInputProps, 7 | } from "react-native"; 8 | import React, { useState } from "react"; 9 | import { Image } from "expo-image"; 10 | import InputText from "../../screen/Auth/components/InputText"; 11 | import useGetMode from "../../hooks/GetMode"; 12 | import Animated, { FadeIn, FadeOut } from "react-native-reanimated"; 13 | const heightFromScreen = Dimensions.get("window").height; 14 | export default function VideoTextArea(props: TextInputProps) { 15 | const dark = useGetMode(); 16 | const color = dark ? "white" : "black"; 17 | const [height, setHeight] = useState(50); 18 | return ( 19 | 24 | { 28 | setHeight(event.nativeEvent.contentSize.height); 29 | }} 30 | style={{ 31 | fontSize: 16, 32 | color, 33 | 34 | fontFamily: "mulishMedium", 35 | maxHeight: height, 36 | alignItems: "flex-start", 37 | }} 38 | placeholder="Video Title" 39 | {...props} 40 | /> 41 | 42 | ); 43 | } 44 | -------------------------------------------------------------------------------- /components/profile/EditProfile.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, Pressable } from "react-native"; 2 | import React from "react"; 3 | import useGetMode from "../../hooks/GetMode"; 4 | import { useNavigation } from "@react-navigation/native"; 5 | import { HomeNavigationProp } from "../../types/navigation"; 6 | 7 | export default function ButtonOutlined() { 8 | const dark = useGetMode(); 9 | const navigate = useNavigation(); 10 | const color = dark ? "white" : "black"; 11 | return ( 12 | 13 | { 15 | navigate.navigate("EditProfile"); 16 | }} 17 | style={{ 18 | paddingHorizontal: 15, 19 | paddingVertical: 10, 20 | borderColor: "#B4B4B4D1", 21 | borderRadius: 999, 22 | borderWidth: 1, 23 | }} 24 | > 25 | Edit Profile 26 | 27 | 28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /components/profile/UploadPic.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, Pressable } from "react-native"; 2 | import React from "react"; 3 | import { CameraIcon } from "../icons"; 4 | import ImagePicker from "react-native-image-crop-picker"; 5 | import useGetMode from "../../hooks/GetMode"; 6 | export default function PickImageButton({ 7 | handleSetPhotoPost, 8 | }: { 9 | handleSetPhotoPost: (mimeType: string, uri: string, size: number) => void; 10 | }) { 11 | const dark = useGetMode(); 12 | const borderColor = dark ? "white" : "black"; 13 | 14 | const rippleColor = !dark ? "#ABABAB" : "#55555500"; 15 | return ( 16 | 32 | { 34 | ImagePicker.openPicker({ 35 | cropping: true, 36 | cropperStatusBarColor: "#000000", 37 | cropperToolbarColor: "#000000", 38 | showCropGuidelines: false, 39 | cropperTintColor: "red", 40 | width: 500, 41 | height: 500, 42 | cropperActiveWidgetColor: "red", 43 | 44 | cropperToolbarWidgetColor: "#FFFFFF", 45 | cropperCancelText: "#FFFFFF", 46 | cropperChooseColor: "#FFFFFF", 47 | compressImageQuality: 0.3, 48 | }) 49 | .then((image) => { 50 | handleSetPhotoPost(image?.mime, image?.path, image?.size); 51 | }) 52 | .catch((e) => {}); 53 | }} 54 | android_ripple={{ color: rippleColor, foreground: true }} 55 | style={{ 56 | width: 100, 57 | height: 50, 58 | justifyContent: "center", 59 | alignItems: "center", 60 | }} 61 | > 62 | 70 | 71 | Upload 72 | 73 | 74 | 75 | ); 76 | } 77 | -------------------------------------------------------------------------------- /components/profilePeople/FollowerUser.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, Pressable } from "react-native"; 2 | import React, { useState } from "react"; 3 | import useGetMode from "../../hooks/GetMode"; 4 | import { getBackgroundColorAsync } from "expo-system-ui"; 5 | import Animated, { BounceIn, BounceOut } from "react-native-reanimated"; 6 | import { useLazyFollowUserQuery } from "../../redux/api/services"; 7 | import { useAppSelector } from "../../redux/hooks/hooks"; 8 | 9 | export default function FollowUser({ 10 | id, 11 | followed, 12 | handleFollow, 13 | }: { 14 | id: string; 15 | followed: boolean; 16 | handleFollow: () => void; 17 | }) { 18 | const dark = useGetMode(); 19 | const color = !dark ? "white" : "black"; 20 | const color2 = dark ? "white" : "black"; 21 | 22 | 23 | 24 | return ( 25 | 31 | 42 | 48 | {followed ? "Following" : "Follow"} 49 | 50 | 51 | 52 | ); 53 | } 54 | -------------------------------------------------------------------------------- /components/searchUser/SearchBox.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | View, 3 | Text, 4 | TextInput, 5 | StyleProp, 6 | ViewStyle, 7 | Dimensions, 8 | } from "react-native"; 9 | import useGetMode from "../../hooks/GetMode"; 10 | import Animated, { FadeInRight } from "react-native-reanimated"; 11 | import { useCallback, useEffect, useMemo, useState } from "react"; 12 | import { useDebounce } from "../../hooks/Debounce"; 13 | import { BlurView } from "expo-blur"; 14 | 15 | const { width } = Dimensions.get("window"); 16 | export default function SearchBox({ 17 | setSearchParam, 18 | }: { 19 | setSearchParam: (text: string) => void; 20 | }) { 21 | const dark = useGetMode(); 22 | 23 | const color = dark ? "white" : "black"; 24 | const placeholderColor = !dark ? "grey" : "grey"; 25 | const borderColor = dark ? "#FFFFFF" : "#DAD9D9"; 26 | const tint = dark ? "dark" : "light"; 27 | const backgroundColor = dark ? "#383838" : "#EAEBEB"; 28 | return ( 29 | 44 | setSearchParam(text)} 48 | placeholderTextColor={placeholderColor} 49 | style={{ 50 | width: "100%", 51 | fontSize: 16, 52 | color, 53 | fontFamily: "jakara", 54 | includeFontPadding: false, 55 | }} 56 | /> 57 | 58 | ); 59 | } 60 | -------------------------------------------------------------------------------- /credentials.json: -------------------------------------------------------------------------------- 1 | { 2 | "android": { 3 | "keystore": { 4 | "keystorePath": "android/keystores/release.keystore", 5 | "keystorePassword": "IOIZIK@100", 6 | "keyAlias": "Hizik", 7 | "keyPassword": "IOIZIK@100" 8 | } 9 | } 10 | } 11 | 12 | 13 | -------------------------------------------------------------------------------- /data/murphy.ts: -------------------------------------------------------------------------------- 1 | export const murphyLaws = [ 2 | "Anything that can go wrong will go wrong.", 3 | "If there is a possibility of several things going wrong, the one that will cause the most damage will be the one to go wrong.", 4 | "Left to themselves, things tend to go from bad to worse.", 5 | ]; 6 | -------------------------------------------------------------------------------- /eas.json: -------------------------------------------------------------------------------- 1 | { 2 | "cli": { 3 | "version": ">= 3.13.3" 4 | }, 5 | "build": { 6 | "development": { 7 | "developmentClient": true, 8 | "distribution": "internal" 9 | }, 10 | "preview": { 11 | "distribution": "internal" 12 | }, 13 | "production": { 14 | "android": { 15 | "buildType": "apk" 16 | } 17 | } 18 | }, 19 | "submit": { 20 | "production": {} 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /google-services.json: -------------------------------------------------------------------------------- 1 | { 2 | "project_info": { 3 | "project_number": "365442112752", 4 | "project_id": "quiapp-698b0", 5 | "storage_bucket": "quiapp-698b0.appspot.com" 6 | }, 7 | "client": [ 8 | { 9 | "client_info": { 10 | "mobilesdk_app_id": "1:365442112752:android:f7cad07868aaef170af635", 11 | "android_client_info": { 12 | "package_name": "me.isaacojo.qui" 13 | } 14 | }, 15 | "oauth_client": [], 16 | "api_key": [ 17 | { 18 | "current_key": "AIzaSyBSquawmwCQmx9-dm4u0wD-VArumgSb0H0" 19 | } 20 | ], 21 | "services": { 22 | "appinvite_service": { 23 | "other_platform_oauth_client": [] 24 | } 25 | } 26 | } 27 | ], 28 | "configuration_version": "1" 29 | } -------------------------------------------------------------------------------- /hooks/Debounce.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from "react"; 2 | 3 | export const useDebounce = (value: string, delay: number) => { 4 | const [deBouncedValue, setDebouncedValue] = useState(value); 5 | 6 | useEffect(() => { 7 | const timeOutId = setTimeout(() => { 8 | setDebouncedValue(value); 9 | }, delay); 10 | 11 | return () => clearTimeout(timeOutId); 12 | }, [value, delay]); 13 | 14 | return deBouncedValue; 15 | }; 16 | -------------------------------------------------------------------------------- /hooks/GetMode.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, useColorScheme } from "react-native"; 2 | import React, { useEffect, useLayoutEffect, useMemo, useState } from "react"; 3 | import { useAppSelector } from "../redux/hooks/hooks"; 4 | 5 | export default function useGetMode() { 6 | const scheme = useColorScheme(); 7 | const [dark, setDark] = useState(false); 8 | const { mode } = useAppSelector((state) => state.prefs); 9 | 10 | useEffect(() => { 11 | if (mode === "system") { 12 | setDark(scheme === "dark"); 13 | } else { 14 | setDark(mode === "dark"); 15 | } 16 | }, [mode, scheme]); 17 | 18 | return dark; 19 | } 20 | -------------------------------------------------------------------------------- /hooks/Socket.tsx: -------------------------------------------------------------------------------- 1 | import { useState, useEffect, useRef, useMemo } from "react"; 2 | import io, { Socket } from "socket.io-client"; 3 | import { useAppSelector } from "../redux/hooks/hooks"; 4 | 5 | const useSocket = (): Socket | undefined => { 6 | const [socket, setSocket] = useState(null); 7 | const token = useAppSelector((state) => state.user.token); 8 | const socketRef = useRef(null); 9 | useMemo(() => { 10 | if (token) { 11 | socketRef.current = io(process.env.EXPO_PUBLIC_API_URL as string, { 12 | autoConnect: true, 13 | auth: { 14 | token, 15 | }, 16 | }); 17 | } 18 | }, [token]); 19 | 20 | return socketRef?.current; 21 | }; 22 | 23 | export default useSocket; 24 | -------------------------------------------------------------------------------- /ios/.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 | project.xcworkspace 24 | .xcode.env.local 25 | 26 | # Bundle artifacts 27 | *.jsbundle 28 | 29 | # CocoaPods 30 | /Pods/ 31 | -------------------------------------------------------------------------------- /ios/.xcode.env: -------------------------------------------------------------------------------- 1 | # This `.xcode.env` file is versioned and is used to source the environment 2 | # used when running script phases inside Xcode. 3 | # To customize your local environment, you can create an `.xcode.env.local` 4 | # file that is not versioned. 5 | 6 | # NODE_BINARY variable contains the PATH to the node executable. 7 | # 8 | # Customize the NODE_BINARY variable here. 9 | # For example, to use nvm with brew, add the following line 10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use 11 | export NODE_BINARY=$(command -v node) 12 | -------------------------------------------------------------------------------- /ios/Podfile.properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "expo.jsEngine": "hermes", 3 | "EX_DEV_CLIENT_NETWORK_INSPECTOR": "true", 4 | "newArchEnabled": "false", 5 | "apple.extraPods": "[]", 6 | "apple.ccacheEnabled": "false", 7 | "apple.privacyManifestAggregationEnabled": "true" 8 | } 9 | -------------------------------------------------------------------------------- /ios/Qui.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ios/Qui/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | @interface AppDelegate : EXAppDelegateWrapper 6 | 7 | @end 8 | -------------------------------------------------------------------------------- /ios/Qui/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/ios/Qui/Images.xcassets/AppIcon.appiconset/App-Icon-1024x1024@1x.png -------------------------------------------------------------------------------- /ios/Qui/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "filename": "App-Icon-1024x1024@1x.png", 5 | "idiom": "universal", 6 | "platform": "ios", 7 | "size": "1024x1024" 8 | } 9 | ], 10 | "info": { 11 | "version": 1, 12 | "author": "expo" 13 | } 14 | } -------------------------------------------------------------------------------- /ios/Qui/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "expo" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ios/Qui/Images.xcassets/SplashScreen.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "idiom": "universal", 5 | "filename": "image.png", 6 | "scale": "1x" 7 | }, 8 | { 9 | "idiom": "universal", 10 | "scale": "2x" 11 | }, 12 | { 13 | "idiom": "universal", 14 | "scale": "3x" 15 | } 16 | ], 17 | "info": { 18 | "version": 1, 19 | "author": "expo" 20 | } 21 | } -------------------------------------------------------------------------------- /ios/Qui/Images.xcassets/SplashScreen.imageset/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/ios/Qui/Images.xcassets/SplashScreen.imageset/image.png -------------------------------------------------------------------------------- /ios/Qui/Images.xcassets/SplashScreenBackground.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images": [ 3 | { 4 | "idiom": "universal", 5 | "filename": "image.png", 6 | "scale": "1x" 7 | }, 8 | { 9 | "idiom": "universal", 10 | "scale": "2x" 11 | }, 12 | { 13 | "idiom": "universal", 14 | "scale": "3x" 15 | } 16 | ], 17 | "info": { 18 | "version": 1, 19 | "author": "expo" 20 | } 21 | } -------------------------------------------------------------------------------- /ios/Qui/Images.xcassets/SplashScreenBackground.imageset/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/ios/Qui/Images.xcassets/SplashScreenBackground.imageset/image.png -------------------------------------------------------------------------------- /ios/Qui/PrivacyInfo.xcprivacy: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrivacyAccessedAPITypes 6 | 7 | 8 | NSPrivacyAccessedAPIType 9 | NSPrivacyAccessedAPICategoryFileTimestamp 10 | NSPrivacyAccessedAPITypeReasons 11 | 12 | C617.1 13 | 0A2A.1 14 | 3B52.1 15 | 16 | 17 | 18 | NSPrivacyAccessedAPIType 19 | NSPrivacyAccessedAPICategoryUserDefaults 20 | NSPrivacyAccessedAPITypeReasons 21 | 22 | CA92.1 23 | 24 | 25 | 26 | NSPrivacyAccessedAPIType 27 | NSPrivacyAccessedAPICategorySystemBootTime 28 | NSPrivacyAccessedAPITypeReasons 29 | 30 | 35F9.1 31 | 32 | 33 | 34 | NSPrivacyAccessedAPIType 35 | NSPrivacyAccessedAPICategoryDiskSpace 36 | NSPrivacyAccessedAPITypeReasons 37 | 38 | E174.1 39 | 85F4.1 40 | 41 | 42 | 43 | NSPrivacyCollectedDataTypes 44 | 45 | NSPrivacyTracking 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /ios/Qui/Qui-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // Use this file to import your target's public headers that you would like to expose to Swift. 3 | // 4 | -------------------------------------------------------------------------------- /ios/Qui/Qui.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | aps-environment 6 | development 7 | 8 | -------------------------------------------------------------------------------- /ios/Qui/Supporting/Expo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | EXUpdatesCheckOnLaunch 6 | ALWAYS 7 | EXUpdatesEnabled 8 | 9 | EXUpdatesLaunchWaitMs 10 | 0 11 | 12 | -------------------------------------------------------------------------------- /ios/Qui/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char * argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | 11 | -------------------------------------------------------------------------------- /ios/Qui/noop-file.swift: -------------------------------------------------------------------------------- 1 | // 2 | // @generated 3 | // A blank Swift file must be created for native modules with Swift files to work correctly. 4 | // 5 | -------------------------------------------------------------------------------- /models.json: -------------------------------------------------------------------------------- 1 | [{"analyzerName":"intellisense-members","languageName":"javascript","identity":{"modelId":"1A3F919CD5B7725108B03C349630A1C82B03","outputId":"4A84987F2428442A9EC84563BB2BC063","modifiedTimeUtc":"2020-09-28T23:11:53.754Z"},"filePath":"1A3F919CD5B7725108B03C349630A1C82B03_4A84987F2428442A9EC84563BB2BC063","lastAccessTimeUtc":"2023-09-25T02:20:44.895Z"}] -------------------------------------------------------------------------------- /redux/api/auth.ts: -------------------------------------------------------------------------------- 1 | import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"; 2 | import { UserState } from "../slice/user"; 3 | import { IUSerData } from "../../types/api"; 4 | import storage from "../storage"; 5 | 6 | interface loginResult { 7 | msg: string; 8 | token: string; 9 | data: IUSerData; 10 | } 11 | 12 | export const authApi = createApi({ 13 | reducerPath: "authApi", 14 | baseQuery: fetchBaseQuery({ 15 | baseUrl: `${process.env.EXPO_PUBLIC_API_URL}/api/auth`, 16 | }), 17 | tagTypes: ["user"], 18 | endpoints: (builder) => ({ 19 | login: builder.mutation< 20 | loginResult, 21 | { 22 | userName: string; 23 | password: string; 24 | } 25 | >({ 26 | query: (payload) => ({ 27 | url: "/login", 28 | method: "POST", 29 | body: payload, 30 | headers: { 31 | "Content-type": "application/json; charset=UTF-8", 32 | }, 33 | }), 34 | }), 35 | register: builder.mutation< 36 | loginResult, 37 | { 38 | userName: string; 39 | password: string; 40 | email: string; 41 | name: string; 42 | } 43 | >({ 44 | query: (payload) => ({ 45 | url: "/signup", 46 | method: "POST", 47 | body: payload, 48 | headers: { 49 | "Content-type": "application/json; charset=UTF-8", 50 | }, 51 | }), 52 | 53 | }), 54 | }), 55 | }); 56 | 57 | export const { useLoginMutation ,useRegisterMutation} = authApi; 58 | -------------------------------------------------------------------------------- /redux/api/chat.ts: -------------------------------------------------------------------------------- 1 | import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"; 2 | import { UserState } from "../slice/user"; 3 | import { 4 | IChatList, 5 | IComment, 6 | IPerson, 7 | IPost, 8 | IPostContent, 9 | IUSerData, 10 | } from "../../types/api"; 11 | import storage from "../storage"; 12 | import { RootState } from "../store"; 13 | 14 | interface loginResult { 15 | msg: string; 16 | token: string; 17 | data: IUSerData; 18 | } 19 | 20 | export const chatApi = createApi({ 21 | reducerPath: "chatApi", 22 | baseQuery: fetchBaseQuery({ 23 | baseUrl: `${process.env.EXPO_PUBLIC_API_URL}/api/chat`, 24 | prepareHeaders: (headers, { getState }) => { 25 | const token = (getState() as RootState).user.token; 26 | // If we have a token, set it in the header 27 | if (token) { 28 | headers.set("Authorization", `Bearer ${token}`); 29 | } 30 | return headers; 31 | }, 32 | }), 33 | tagTypes: ["chats"], 34 | endpoints: (builder) => ({ 35 | getAllChats: builder.query<{ chatList: IChatList[] }, null>({ 36 | query: () => `/get-all-chats`, 37 | 38 | extraOptions: { maxRetries: 2 }, 39 | }), 40 | getAllMessages: builder.query<{ chatList: IChatList }, { id: string }>({ 41 | query: ({id}) => `/get-all-messages?id=${id}`, 42 | extraOptions: { maxRetries: 2 }, 43 | }), 44 | }), 45 | }); 46 | 47 | export const { useGetAllChatsQuery,useLazyGetAllMessagesQuery,useLazyGetAllChatsQuery } = chatApi; 48 | -------------------------------------------------------------------------------- /redux/hooks/hooks.ts: -------------------------------------------------------------------------------- 1 | import { TypedUseSelectorHook, useDispatch, useSelector } from "react-redux"; 2 | import type { RootState, AppDispatch } from "../store"; 3 | 4 | export const useAppDispatch = () => useDispatch(); 5 | export const useAppSelector: TypedUseSelectorHook = useSelector; 6 | -------------------------------------------------------------------------------- /redux/slice/bottomSheet/index.tsx: -------------------------------------------------------------------------------- 1 | import { PayloadAction, createSlice } from "@reduxjs/toolkit"; 2 | 3 | export type BottomSheet = { 4 | isOpen: boolean; 5 | type: string | null; 6 | }; 7 | const bottomSheet = createSlice({ 8 | name: "bottomSheet", 9 | initialState: { 10 | isOpen: false, 11 | type: null, 12 | } as BottomSheet, 13 | reducers: { 14 | openSheet: (state, action: PayloadAction<{ type: string }>) => { 15 | state.isOpen = true; 16 | state.type = action.payload.type; 17 | }, 18 | closeSheet: (state) => { 19 | state.isOpen = false; 20 | state.type = null; 21 | }, 22 | }, 23 | }); 24 | 25 | export default bottomSheet.reducer; 26 | export const { openSheet, closeSheet } = bottomSheet.actions; 27 | -------------------------------------------------------------------------------- /redux/slice/chat/online.ts: -------------------------------------------------------------------------------- 1 | import { PayloadAction, createReducer, createSlice } from "@reduxjs/toolkit"; 2 | import { useState } from "react"; 3 | 4 | const onLineUserIDs = createSlice({ 5 | name: "onlineUserIds", 6 | initialState: { 7 | ids: [], 8 | } as { ids: Array }, 9 | reducers: { 10 | updateOnlineIds: (state, action: PayloadAction<{ ids: Array }>) => { 11 | console.log("🚀 ~ file: online.ts:11 ~ state:", state) 12 | state.ids = action.payload.ids; 13 | }, 14 | }, 15 | }); 16 | 17 | export default onLineUserIDs.reducer; 18 | export const { updateOnlineIds } = onLineUserIDs.actions; 19 | -------------------------------------------------------------------------------- /redux/slice/currentPage/index.ts: -------------------------------------------------------------------------------- 1 | import { PayloadAction, createSlice } from "@reduxjs/toolkit"; 2 | 3 | const currentPage = createSlice({ 4 | name: "currentPage", 5 | initialState: { 6 | page: null, 7 | } as { 8 | page: string | null; 9 | }, 10 | reducers: { 11 | setCurrentPage: (state, action: PayloadAction<{ page: string }>) => { 12 | state.page = action.payload.page; 13 | }, 14 | }, 15 | }); 16 | 17 | export default currentPage.reducer; 18 | export const { setCurrentPage } = currentPage.actions; 19 | -------------------------------------------------------------------------------- /redux/slice/modal/loading.ts: -------------------------------------------------------------------------------- 1 | import { PayloadAction, createSlice } from "@reduxjs/toolkit"; 2 | 3 | export type LoadingModal = { 4 | isOpen: boolean; 5 | }; 6 | const loadingModal = createSlice({ 7 | name: "bottomSheet", 8 | initialState: { 9 | isOpen: false, 10 | } as LoadingModal, 11 | reducers: { 12 | openLoadingModal: (state) => { 13 | state.isOpen = true; 14 | }, 15 | closeLoadingModal: (state) => { 16 | state.isOpen = false; 17 | }, 18 | }, 19 | }); 20 | 21 | export default loadingModal.reducer; 22 | export const { openLoadingModal, closeLoadingModal } = loadingModal.actions; 23 | -------------------------------------------------------------------------------- /redux/slice/people/search.ts: -------------------------------------------------------------------------------- 1 | import { IPerson, IPost } from "./../../../types/api"; 2 | import { createSlice } from "@reduxjs/toolkit"; 3 | import { postLists } from "../../../data/test"; 4 | import { servicesApi } from "../../api/services"; 5 | 6 | export type personState = { 7 | data: IPerson[]; 8 | error: any; 9 | loading: boolean; 10 | }; 11 | 12 | const searchPeople = createSlice({ 13 | name: "searchPeople", 14 | initialState: { 15 | data: [], 16 | error: null, 17 | loading: false, 18 | } as personState, 19 | reducers: { 20 | addPost: () => {}, 21 | }, 22 | extraReducers: (builder) => { 23 | builder.addMatcher( 24 | servicesApi.endpoints.getRandomPeople.matchFulfilled, 25 | (state, { payload }) => { 26 | 27 | state.data = payload.people; 28 | state.error = null; 29 | state.loading = false; 30 | } 31 | ); 32 | builder.addMatcher( 33 | servicesApi.endpoints.getRandomPeople.matchPending, 34 | (state, { payload }) => { 35 | state.data = []; 36 | state.error = null; 37 | state.loading = true; 38 | } 39 | ); 40 | builder.addMatcher( 41 | servicesApi.endpoints.getRandomPeople.matchRejected, 42 | (state, { payload, error }) => { 43 | state.data = []; 44 | state.error = error; 45 | state.loading = false; 46 | } 47 | ); 48 | 49 | builder.addMatcher( 50 | servicesApi.endpoints.searchPeople.matchFulfilled, 51 | (state, { payload }) => { 52 | 53 | state.data = payload.people; 54 | state.error = null; 55 | state.loading = false; 56 | } 57 | ); 58 | builder.addMatcher( 59 | servicesApi.endpoints.searchPeople.matchPending, 60 | (state, { payload }) => { 61 | state.data = []; 62 | state.error = null; 63 | state.loading = true; 64 | } 65 | ); 66 | builder.addMatcher( 67 | servicesApi.endpoints.searchPeople.matchRejected, 68 | (state, { payload, error }) => { 69 | state.data = []; 70 | state.error = error; 71 | state.loading = false; 72 | } 73 | ); 74 | 75 | }, 76 | }); 77 | 78 | export default searchPeople.reducer; 79 | -------------------------------------------------------------------------------- /redux/slice/post/audio.ts: -------------------------------------------------------------------------------- 1 | import { PayloadAction, createSlice } from "@reduxjs/toolkit"; 2 | 3 | const audio = createSlice({ 4 | name: "audioPlaying", 5 | initialState: { 6 | playingId: [] 7 | } as { 8 | playingId: number[] 9 | }, 10 | reducers: { 11 | setPlayingIds: (state, action: PayloadAction) => { 12 | state.playingId = action.payload; 13 | }, 14 | }, 15 | }); 16 | 17 | 18 | export default audio.reducer; 19 | export const { setPlayingIds } = audio.actions; 20 | -------------------------------------------------------------------------------- /redux/slice/post/followed.ts: -------------------------------------------------------------------------------- 1 | import { IPost } from "./../../../types/api"; 2 | import { createSlice } from "@reduxjs/toolkit"; 3 | import { postLists } from "../../../data/test"; 4 | import { servicesApi } from "../../api/services"; 5 | 6 | export type postState = { 7 | data: IPost[]; 8 | error: any; 9 | loading: boolean; 10 | }; 11 | 12 | const fPost = createSlice({ 13 | name: "fPost", 14 | initialState: { 15 | data: [], 16 | error: null, 17 | loading: false, 18 | } as postState, 19 | reducers: { 20 | addPost: () => {}, 21 | resetPost: (state) => { 22 | state.data = []; 23 | state.error = null; 24 | state.loading = false; 25 | }, 26 | }, 27 | 28 | extraReducers: (builder) => { 29 | builder.addMatcher( 30 | servicesApi.endpoints.getFollowedPosts.matchFulfilled, 31 | (state, { payload }) => { 32 | const data = [...state.data, ...payload.posts]; 33 | state.data = data; 34 | state.error = null; 35 | state.loading = false; 36 | } 37 | ); 38 | builder.addMatcher( 39 | servicesApi.endpoints.getFollowedPosts.matchPending, 40 | (state, { payload }) => { 41 | state.error = null; 42 | state.loading = true; 43 | } 44 | ); 45 | builder.addMatcher( 46 | servicesApi.endpoints.getFollowedPosts.matchRejected, 47 | (state, { payload, error }) => { 48 | state.error = error; 49 | state.loading = false; 50 | } 51 | ); 52 | }, 53 | }); 54 | 55 | export default fPost.reducer; 56 | export const { resetPost } = fPost.actions; 57 | -------------------------------------------------------------------------------- /redux/slice/post/index.ts: -------------------------------------------------------------------------------- 1 | import { IPost } from "./../../../types/api"; 2 | import { createSlice } from "@reduxjs/toolkit"; 3 | import { postLists } from "../../../data/test"; 4 | import { servicesApi } from "../../api/services"; 5 | 6 | export type postState = { 7 | data: IPost[]; 8 | error: any; 9 | loading: boolean; 10 | }; 11 | 12 | const post = createSlice({ 13 | name: "post", 14 | initialState: { 15 | data: [], 16 | error: null, 17 | loading: false, 18 | } as postState, 19 | reducers: { 20 | addPost: () => {}, 21 | resetPost: (state) => { 22 | state.data = []; 23 | state.error = null; 24 | state.loading = false; 25 | }, 26 | }, 27 | 28 | extraReducers: (builder) => { 29 | builder.addMatcher( 30 | servicesApi.endpoints.getAllPosts.matchFulfilled, 31 | (state, { payload }) => { 32 | const data = [...state.data, ...payload.posts]; 33 | state.data = data; 34 | state.error = null; 35 | state.loading = false; 36 | } 37 | ); 38 | builder.addMatcher( 39 | servicesApi.endpoints.getAllPosts.matchPending, 40 | (state, { payload }) => { 41 | state.error = null; 42 | state.loading = true; 43 | } 44 | ); 45 | builder.addMatcher( 46 | servicesApi.endpoints.getAllPosts.matchRejected, 47 | (state, { payload, error }) => { 48 | state.error = error; 49 | state.loading = false; 50 | } 51 | ); 52 | }, 53 | }); 54 | 55 | export default post.reducer; 56 | export const {resetPost} = post.actions 57 | -------------------------------------------------------------------------------- /redux/slice/post/search.ts: -------------------------------------------------------------------------------- 1 | import { IPost } from "./../../../types/api"; 2 | import { createSlice } from "@reduxjs/toolkit"; 3 | import { postLists } from "../../../data/test"; 4 | import { servicesApi } from "../../api/services"; 5 | 6 | export type postState = { 7 | data: IPost[]; 8 | error: any; 9 | loading: boolean; 10 | }; 11 | 12 | const searchPost = createSlice({ 13 | name: "searchPost", 14 | initialState: { 15 | data: [], 16 | error: null, 17 | loading: false, 18 | } as postState, 19 | reducers: { 20 | addPost: () => {}, 21 | }, 22 | extraReducers: (builder) => { 23 | builder.addMatcher( 24 | servicesApi.endpoints.getRandomPosts.matchFulfilled, 25 | (state, { payload }) => { 26 | state.data = payload.posts; 27 | state.error = null; 28 | state.loading = false; 29 | } 30 | ); 31 | builder.addMatcher( 32 | servicesApi.endpoints.getRandomPosts.matchPending, 33 | (state, { payload }) => { 34 | state.data = []; 35 | state.error = null; 36 | state.loading = true; 37 | } 38 | ); 39 | builder.addMatcher( 40 | servicesApi.endpoints.getRandomPosts.matchRejected, 41 | (state, { payload, error }) => { 42 | state.data = []; 43 | state.error = error; 44 | state.loading = false; 45 | } 46 | ); 47 | 48 | builder.addMatcher( 49 | servicesApi.endpoints.searchPosts.matchFulfilled, 50 | (state, { payload }) => { 51 | state.data = payload.posts; 52 | state.error = null; 53 | state.loading = false; 54 | } 55 | ); 56 | builder.addMatcher( 57 | servicesApi.endpoints.searchPosts.matchPending, 58 | (state, { payload }) => { 59 | state.data = []; 60 | state.error = null; 61 | state.loading = true; 62 | } 63 | ); 64 | builder.addMatcher( 65 | servicesApi.endpoints.searchPosts.matchRejected, 66 | (state, { payload, error }) => { 67 | state.data = []; 68 | state.error = error; 69 | state.loading = false; 70 | } 71 | ); 72 | }, 73 | }); 74 | 75 | export default searchPost.reducer; 76 | -------------------------------------------------------------------------------- /redux/slice/prefs/index.ts: -------------------------------------------------------------------------------- 1 | import { PayloadAction, createSlice } from "@reduxjs/toolkit"; 2 | 3 | export type Prefs = { 4 | mode: "system" | "light" | "dark"; 5 | isHighEnd: boolean; 6 | }; 7 | const prefs = createSlice({ 8 | name: "prefs", 9 | initialState: { 10 | mode: "system", 11 | } as Prefs, 12 | reducers: { 13 | setMode: ( 14 | state, 15 | action: PayloadAction<{ mode: "system" | "light" | "dark" }> 16 | ) => { 17 | state.mode = action.payload.mode; 18 | }, 19 | setHighEnd: (state, action: PayloadAction<{ isHighEnd: boolean }>) => { 20 | state.isHighEnd = action.payload.isHighEnd; 21 | }, 22 | }, 23 | }); 24 | 25 | export default prefs.reducer; 26 | export const { setMode, setHighEnd } = prefs.actions; 27 | -------------------------------------------------------------------------------- /redux/slice/routes/index.ts: -------------------------------------------------------------------------------- 1 | import { PayloadAction, createSlice } from "@reduxjs/toolkit"; 2 | 3 | export type Route = { 4 | route: "onBoard" | "Auth" | "App"; 5 | }; 6 | 7 | const routeSlice = createSlice({ 8 | name: "route", 9 | initialState: { 10 | route: "onBoard", 11 | } as Route, 12 | reducers: { 13 | setRoute: (state, action: PayloadAction) => { 14 | state.route = action.payload.route; 15 | }, 16 | }, 17 | }); 18 | 19 | export default routeSlice.reducer; 20 | export const { setRoute } = routeSlice.actions; 21 | -------------------------------------------------------------------------------- /redux/slice/toast/toast.ts: -------------------------------------------------------------------------------- 1 | import { PayloadAction, createSlice } from "@reduxjs/toolkit"; 2 | 3 | import * as Haptics from "expo-haptics"; 4 | import { Platform } from "react-native"; 5 | const ONE_SECOND_IN_MS = 1000; 6 | 7 | const PATTERN = [ 8 | 1 * ONE_SECOND_IN_MS, 9 | 2 * ONE_SECOND_IN_MS, 10 | 3 * ONE_SECOND_IN_MS, 11 | ]; 12 | const PATTERN_DESC = 13 | Platform.OS === "android" 14 | ? "wait 1s, vibrate 2s, wait 3s" 15 | : "wait 1s, vibrate, wait 2s, vibrate, wait 3s"; 16 | export type ToastState = { 17 | text: string | null; 18 | imageUri?: string; 19 | open: boolean; 20 | type: "Failed" | "Success" | "Info" | "Message" | null; 21 | }; 22 | 23 | const toastSlice = createSlice({ 24 | name: "Toast", 25 | initialState: { 26 | text: null, 27 | open: false, 28 | type: null, 29 | } as ToastState, 30 | reducers: { 31 | openToast: ( 32 | state, 33 | action: PayloadAction<{ 34 | text: string; 35 | imageUri?: string; 36 | type: "Failed" | "Success" | "Info" | "Message"; 37 | }> 38 | ) => { 39 | state.open = true; 40 | state.imageUri = action.payload.imageUri; 41 | state.text = action.payload.text; 42 | state.type = action.payload.type; 43 | }, 44 | closeToast: (state) => { 45 | state.open = false; 46 | state.text = null; 47 | state.type = null; 48 | }, 49 | }, 50 | }); 51 | 52 | export default toastSlice.reducer; 53 | export const { openToast, closeToast } = toastSlice.actions; 54 | -------------------------------------------------------------------------------- /redux/slice/user/followers.ts: -------------------------------------------------------------------------------- 1 | import { PayloadAction, createSlice } from "@reduxjs/toolkit"; 2 | 3 | import { userApi } from "../../api/user"; 4 | 5 | export interface FollowerState { 6 | following: number | null; 7 | followers: number | null; 8 | } 9 | const followsCount = createSlice({ 10 | name: "followsCount", 11 | initialState: { 12 | followers: 0, 13 | following: 0, 14 | } as FollowerState, 15 | reducers: { 16 | resetFollowers: (state) => { 17 | state.following = 0; 18 | state.followers = 0; 19 | }, 20 | updateFollowing: (state, action: PayloadAction<{ following: number }>) => { 21 | state.following = action.payload.following; 22 | }, 23 | updateFollowers: (state, action: PayloadAction<{ followers: number }>) => { 24 | state.followers = action.payload.followers; 25 | }, 26 | }, 27 | extraReducers: (builder) => { 28 | builder.addMatcher( 29 | userApi.endpoints.getFollowDetails.matchFulfilled, 30 | (state, { payload }) => { 31 | state.followers = Number(payload.followers); 32 | state.following = Number(payload.following); 33 | } 34 | ); 35 | }, 36 | }); 37 | 38 | export default followsCount.reducer; 39 | export const { resetFollowers, updateFollowers, updateFollowing } = 40 | followsCount.actions; 41 | -------------------------------------------------------------------------------- /redux/slice/user/index.ts: -------------------------------------------------------------------------------- 1 | import { PayloadAction, createSlice } from "@reduxjs/toolkit"; 2 | import { authApi } from "../../api/auth"; 3 | import { IUSerData } from "../../../types/api"; 4 | import { userApi } from "../../api/user"; 5 | import socket from "../../../util/socket"; 6 | 7 | export interface UserState { 8 | data: IUSerData | null; 9 | error: any; 10 | token: string | null; 11 | loading: boolean; 12 | } 13 | const user = createSlice({ 14 | name: "user", 15 | initialState: { 16 | data: null, 17 | error: null, 18 | loading: false, 19 | token: null, 20 | } as UserState, 21 | reducers: { 22 | signOut: (state) => { 23 | state.error = null; 24 | state.loading = false; 25 | state.token = null; 26 | socket.disconnect(); 27 | }, 28 | clearUserData: (state) => { 29 | state.data = null; 30 | state.error = null; 31 | state.loading = false; 32 | state.token = null; 33 | }, 34 | }, 35 | extraReducers: (builder) => { 36 | builder.addMatcher( 37 | userApi.endpoints.getUser.matchFulfilled, 38 | (state, { payload }) => { 39 | state.data = payload.data; 40 | state.error = null; 41 | state.loading = false; 42 | } 43 | ); 44 | builder.addMatcher(userApi.endpoints.getUser.matchPending, (state) => { 45 | state.error = null; 46 | state.loading = true; 47 | }); 48 | builder.addMatcher( 49 | userApi.endpoints.getUser.matchRejected, 50 | (state, { error }) => { 51 | state.data = null; 52 | state.error = error; 53 | state.loading = true; 54 | } 55 | ); 56 | builder.addMatcher( 57 | authApi.endpoints.login.matchFulfilled, 58 | (state, { payload }) => { 59 | state.data = payload.data; 60 | state.error = null; 61 | state.loading = false; 62 | state.token = payload.token; 63 | } 64 | ); 65 | builder.addMatcher(authApi.endpoints.login.matchPending, (state) => { 66 | state.data = null; 67 | state.error = null; 68 | state.loading = true; 69 | state.token = null; 70 | }); 71 | builder.addMatcher( 72 | authApi.endpoints.login.matchRejected, 73 | (state, { error }) => { 74 | state.data = null; 75 | state.error = error; 76 | state.loading = true; 77 | state.token = null; 78 | } 79 | ); 80 | }, 81 | }); 82 | 83 | export default user.reducer; 84 | 85 | export const { signOut, clearUserData } = user.actions; 86 | -------------------------------------------------------------------------------- /redux/storage.ts: -------------------------------------------------------------------------------- 1 | import { Storage } from "redux-persist"; 2 | import { MMKV } from "react-native-mmkv"; 3 | 4 | const storage = new MMKV(); 5 | 6 | export const reduxStorage: Storage = { 7 | setItem: (key, value) => { 8 | storage.set(key, value); 9 | return Promise.resolve(true); 10 | }, 11 | getItem: (key) => { 12 | const value = storage.getString(key); 13 | return Promise.resolve(value); 14 | }, 15 | removeItem: (key) => { 16 | storage.delete(key); 17 | return Promise.resolve(); 18 | }, 19 | }; 20 | 21 | export default storage -------------------------------------------------------------------------------- /routes/Auth.tsx: -------------------------------------------------------------------------------- 1 | import { createNativeStackNavigator } from "@react-navigation/native-stack"; 2 | 3 | import Login from "../screen/Auth/Login"; 4 | import useGetMode from "../hooks/GetMode"; 5 | import Register from "../screen/Auth/Register"; 6 | import { AuthRootStackParamList } from "../types/navigation"; 7 | 8 | const Stack = createNativeStackNavigator(); 9 | 10 | export default function Auth() { 11 | const dark = useGetMode(); 12 | const isDark = dark; 13 | 14 | const backgroundColor= isDark ? "black" : "white" 15 | return ( 16 | 17 | 18 | 19 | 20 | ); 21 | } 22 | -------------------------------------------------------------------------------- /routes/OnBoard.tsx: -------------------------------------------------------------------------------- 1 | import { createNativeStackNavigator } from "@react-navigation/native-stack"; 2 | 3 | import Onboard from "../screen/Onboard"; 4 | import useGetMode from "../hooks/GetMode"; 5 | 6 | const Stack = createNativeStackNavigator(); 7 | export default function OnboardNavigation() { 8 | const dark = useGetMode(); 9 | const isDark = dark; 10 | const backgroundColor = isDark ? "black" : "white"; 11 | return ( 12 | 15 | 16 | 17 | ); 18 | } 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /screen/App/ChangeData.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text } from "react-native"; 2 | import React from "react"; 3 | import { ChangeDataProp } from "../../types/navigation"; 4 | import AnimatedScreen from "../../components/global/AnimatedScreen"; 5 | import ChangeName from "./ChangeData/ChangeName"; 6 | import ChangePassword from "./ChangeData/ChangePassword"; 7 | import ChangeUserName from "./ChangeData/ChangeUserName"; 8 | 9 | export default function ChangeData({ navigation, route }: ChangeDataProp) { 10 | const { change } = route.params; 11 | function getRoute() { 12 | switch (change) { 13 | case "name": 14 | return ; 15 | case "password": 16 | return ; 17 | default: 18 | return ; 19 | } 20 | } 21 | return {getRoute()}; 22 | } 23 | -------------------------------------------------------------------------------- /screen/App/FollowingFollowerScreens/Followers.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text } from "react-native"; 2 | import React, { useEffect, useState } from "react"; 3 | import { FlatList } from "react-native-gesture-handler"; 4 | import { useLazyGetFollowersListQuery } from "../../../redux/api/user"; 5 | import { FollowData } from "../../../types/api"; 6 | import FFContainer from "../../../components/followingFollowers/FollowingFollowerContainer"; 7 | import { ActivityIndicator } from "react-native-paper"; 8 | import useGetMode from "../../../hooks/GetMode"; 9 | 10 | export default function Followers() { 11 | const dark = useGetMode(); 12 | const color = dark ? "white" : "black"; 13 | const [getLazyFollowers, followersResponse] = useLazyGetFollowersListQuery(); 14 | const [data, setData] = useState([]); 15 | 16 | const [skip, setSkip] = useState(0); 17 | const [noMore, setNoMore] = useState(false); 18 | useEffect(() => { 19 | getLazyFollowers({ take: 20, skip }) 20 | .unwrap() 21 | .then((e) => { 22 | setData(e); 23 | setSkip(e.length); 24 | }) 25 | .catch((e) => {}); 26 | }, []); 27 | 28 | const renderItem = ({ item }: { item: FollowData }) => { 29 | return ( 30 | 37 | ); 38 | }; 39 | 40 | const fetchMoreData = () => { 41 | if (!noMore && !followersResponse.isError && skip > 0) 42 | getLazyFollowers({ take: 10, skip }) 43 | .unwrap() 44 | .then((r) => { 45 | setSkip(skip + r.length); 46 | setData((prev) => [...prev, ...r]); 47 | 48 | if (r.length < 10) { 49 | setNoMore(true); 50 | } 51 | }); 52 | }; 53 | 54 | return ( 55 | 56 | 62 | 63 | 64 | ) : ( 65 | Such Empty 66 | ) 67 | } 68 | data={data} 69 | onEndReachedThreshold={0.3} 70 | onEndReached={fetchMoreData} 71 | renderItem={renderItem} 72 | /> 73 | 74 | ); 75 | } 76 | -------------------------------------------------------------------------------- /screen/App/FollowingFollowerScreens/Following.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, ActivityIndicator } from "react-native"; 2 | import React, { useEffect, useState } from "react"; 3 | import { FlatList } from "react-native-gesture-handler"; 4 | import { 5 | useLazyGetFollowersListQuery, 6 | useLazyGetFollowingListQuery, 7 | } from "../../../redux/api/user"; 8 | import { FollowData, FollowingData } from "../../../types/api"; 9 | import FFContainer from "../../../components/followingFollowers/FollowingFollowerContainer"; 10 | import useGetMode from "../../../hooks/GetMode"; 11 | 12 | export default function Followers() { 13 | const dark = useGetMode(); 14 | const [getLazyFollowers, followersResponse] = useLazyGetFollowingListQuery(); 15 | const [data, setData] = useState([]); 16 | const color = dark ? "white" : "black"; 17 | const [skip, setSkip] = useState(0); 18 | const [noMore, setNoMore] = useState(false); 19 | useEffect(() => { 20 | getLazyFollowers({ take: 20, skip }) 21 | .unwrap() 22 | .then((e) => { 23 | setData(e); 24 | setSkip(e.length); 25 | }) 26 | .catch((e) => {}); 27 | }, []); 28 | 29 | const renderItem = ({ item }: { item: FollowingData }) => { 30 | return ( 31 | 38 | ); 39 | }; 40 | 41 | const fetchMoreData = () => { 42 | if (!noMore && !followersResponse.isError && skip > 0) 43 | getLazyFollowers({ take: 10, skip }) 44 | .unwrap() 45 | .then((r) => { 46 | setSkip(skip + r.length); 47 | setData((prev) => [...prev, ...r]); 48 | 49 | if (r.length < 10) { 50 | setNoMore(true); 51 | } 52 | }); 53 | }; 54 | 55 | return ( 56 | 57 | 64 | 65 | 66 | ) : ( 67 | Such Empty 68 | ) 69 | } 70 | onEndReachedThreshold={0.3} 71 | onEndReached={fetchMoreData} 72 | renderItem={renderItem} 73 | /> 74 | 75 | ); 76 | } 77 | -------------------------------------------------------------------------------- /screen/App/Messages.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, Animated } from "react-native"; 2 | import React, { useCallback, useEffect, useRef, useState } from "react"; 3 | import { 4 | useFocusEffect, 5 | useIsFocused, 6 | useNavigationState, 7 | } from "@react-navigation/native"; 8 | import AnimatedScreen from "../../components/global/AnimatedScreen"; 9 | import Recent from "../../components/messages/Recent"; 10 | import ChatList from "../../components/messages/ChatList"; 11 | import Fab from "../../components/messages/ChatList/Fab"; 12 | import { AddMessage, MessagesIcon } from "../../components/icons"; 13 | import useGetMode from "../../hooks/GetMode"; 14 | import { useAppDispatch, useAppSelector } from "../../redux/hooks/hooks"; 15 | import { clearNewFromChatList } from "../../redux/slice/chat/chatlist"; 16 | import { useLazyGetAllChatsQuery } from "../../redux/api/chat"; 17 | import { useAnimatedScrollHandler, useSharedValue } from "react-native-reanimated"; 18 | 19 | export default function Messages() { 20 | 21 | const dark = useGetMode(); 22 | const color = dark ? "#FFFFFF" : "#000000"; 23 | const dispatch = useAppDispatch(); 24 | const offset = useSharedValue(0); 25 | console.log("🚀 ~ file: Profile.tsx:16 ~ Profile ~ offset:", offset); 26 | const scrollHandler = useAnimatedScrollHandler((event) => { 27 | console.log("🚀 ~ file: Profile.tsx:22 ~ scrollHandler ~ event:", event) 28 | 29 | offset.value = event.contentOffset.y; 30 | }); 31 | 32 | const [chatlist, chatlistRes] = useLazyGetAllChatsQuery(); 33 | 34 | 35 | useFocusEffect( 36 | useCallback(() => { 37 | chatlist(null).refetch() 38 | dispatch(clearNewFromChatList()); 39 | }, []) 40 | ); 41 | return ( 42 | 43 | 44 | 45 | } /> 46 | 47 | ); 48 | } 49 | -------------------------------------------------------------------------------- /screen/App/Post.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text } from 'react-native' 2 | import React from 'react' 3 | 4 | export default function Post() { 5 | return ( 6 | 7 | 8 | 9 | ) 10 | } -------------------------------------------------------------------------------- /screen/App/Profile.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, Animated, ScrollView } from "react-native"; 2 | import React, { useEffect, useRef } from "react"; 3 | 4 | import AnimatedScreen from "../../components/global/AnimatedScreen"; 5 | import Header from "../../components/profile/Header"; 6 | import { StatusBar as ExpoStatusBar } from "expo-status-bar"; 7 | import Bio from "../../components/profile/Bio"; 8 | import MyPosts from "./ProfileScreens/MyPosts"; 9 | import { useGetFollowDetailsQuery } from "../../redux/api/user"; 10 | import { 11 | useAnimatedRef, 12 | useAnimatedScrollHandler, 13 | useScrollViewOffset, 14 | useSharedValue, 15 | } from "react-native-reanimated"; 16 | 17 | export default function Profile() { 18 | const getFollowData = useGetFollowDetailsQuery(null); 19 | const offset = useSharedValue(0); 20 | console.log("🚀 ~ file: Profile.tsx:16 ~ Profile ~ offset:", offset); 21 | const scrollHandler = useAnimatedScrollHandler((event) => { 22 | console.log("🚀 ~ file: Profile.tsx:22 ~ scrollHandler ~ event:", event) 23 | 24 | offset.value = event.contentOffset.y; 25 | }); 26 | useEffect(() => { 27 | console.log(getFollowData.data); 28 | getFollowData.refetch(); 29 | }, []); 30 | 31 | return ( 32 | 33 | 34 | 35 |
36 | 37 | 38 | 39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /screen/App/ProfilePeople.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, Animated, ScrollView } from "react-native"; 2 | import React, { useRef } from "react"; 3 | 4 | import AnimatedScreen from "../../components/global/AnimatedScreen"; 5 | import Header from "../../components/profilePeople/Header"; 6 | import { StatusBar as ExpoStatusBar } from "expo-status-bar"; 7 | import Bio from "../../components/profile/Bio"; 8 | import MyPosts from "./ProfileScreens/MyPosts"; 9 | import { ProfilePeopleProp } from "../../types/navigation"; 10 | import PeoplePosts from "./ProfileScreens/PeoplePosts"; 11 | 12 | export default function ProfilePeople({ 13 | navigation, 14 | route, 15 | }: ProfilePeopleProp) { 16 | const offset = useRef(new Animated.Value(0)).current; 17 | const { id } = route.params; 18 | return ( 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /screen/Auth/components/InputPassword.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | View, 3 | Text, 4 | TextInput, 5 | useColorScheme, 6 | Pressable, 7 | StyleProp, 8 | ViewStyle, 9 | } from "react-native"; 10 | import React, { useState } from "react"; 11 | import { Eye, EyeSlash } from "../../../components/icons"; 12 | import useGetMode from "../../../hooks/GetMode"; 13 | import { TextInputProps } from "react-native-paper"; 14 | import Animated, { FadeIn, FadeOut } from "react-native-reanimated"; 15 | 16 | export default function InputPassword({ 17 | props, 18 | style, 19 | }: { 20 | props: TextInputProps; 21 | style?: StyleProp; 22 | }) { 23 | const dark = useGetMode(); 24 | const isDark = dark; 25 | const backgroundColor = isDark ? "#292828" : "#f1f1f1"; 26 | const color = isDark ? "white" : "black"; 27 | const [show, setShow] = useState(false); 28 | const placeholderColor = isDark ? "#959595" : "#393939"; 29 | return ( 30 | 44 | 59 | 69 | { 71 | setShow(!show); 72 | }} 73 | style={{ 74 | height: "100%", 75 | width: "100%", 76 | borderRadius: 999, 77 | alignItems: "center", 78 | 79 | justifyContent: "center", 80 | }} 81 | android_ripple={{ color: "#FFFFFF" }} 82 | > 83 | {!show ? ( 84 | 85 | 86 | 87 | ) : ( 88 | 89 | )} 90 | 91 | 92 | 93 | ); 94 | } 95 | -------------------------------------------------------------------------------- /screen/Auth/components/InputText.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | View, 3 | Text, 4 | TextInput, 5 | useColorScheme, 6 | TextInputProps, 7 | StyleProp, 8 | RegisteredStyle, 9 | ViewStyle, 10 | } from "react-native"; 11 | import React from "react"; 12 | import useGetMode from "../../../hooks/GetMode"; 13 | 14 | export default function InputText({ 15 | props, 16 | style, 17 | }: { 18 | props: TextInputProps; 19 | style?: StyleProp; 20 | }) { 21 | const dark = useGetMode(); 22 | const isDark = dark; 23 | const backgroundColor = isDark ? "#292828" : "#f1f1f1"; 24 | const color = isDark ? "white" : "black"; 25 | const placeholderColor = isDark ? "#959595" : "#393939"; 26 | return ( 27 | 42 | 58 | 68 | 76 | @ 77 | 78 | 79 | 80 | ); 81 | } 82 | -------------------------------------------------------------------------------- /screen/Onboard/components/OnboardBuilder.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, Dimensions, useColorScheme } from "react-native"; 2 | import { Image, ImageSource, } from "expo-image"; 3 | 4 | import Animated, { FadeInLeft } from "react-native-reanimated"; 5 | import useGetMode from "../../../hooks/GetMode"; 6 | 7 | 8 | const height = Dimensions.get("window").height; 9 | const width = Dimensions.get("window").width; 10 | console.log("🚀 ~ file: OnboardBuilder.tsx:10 ~ width:", width) 11 | export default function OnboardBuilder({ 12 | header, 13 | subText, 14 | imageUri, 15 | quote, 16 | }: { 17 | header: string; 18 | subText: string; 19 | imageUri: ImageSource; 20 | quote: string; 21 | }) { 22 | const dark = useGetMode(); 23 | const color = !dark ? "black" : "white"; 24 | 25 | return ( 26 | 27 | 35 | 36 | 37 | 40 | {header} 41 | 42 | 43 | {subText} 44 | 45 | 53 | {quote} 54 | 55 | 56 | ); 57 | } 58 | -------------------------------------------------------------------------------- /screen/Onboard/components/TrackerTag.tsx: -------------------------------------------------------------------------------- 1 | import { View, Text, useColorScheme } from "react-native"; 2 | import React from "react"; 3 | import Animated, { 4 | FadeIn, 5 | FadeInLeft, 6 | FadeInRight, 7 | FadeOut, 8 | FadeOutLeft, 9 | FadeOutRight, 10 | } from "react-native-reanimated"; 11 | import useGetMode from "../../../hooks/GetMode"; 12 | 13 | export default function TrackerTag({ color }: { color?: string }) { 14 | const dark = useGetMode(); 15 | const isDark = dark; 16 | const backgroundColor = !isDark ? "black" : "white"; 17 | 18 | return ( 19 | 29 | ); 30 | } 31 | -------------------------------------------------------------------------------- /screenshot/qui.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElSierra/Social-app-React-Native/81f4784e9fe4b45d4130c4b8d37d82e2ee6a7d57/screenshot/qui.gif -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "expo/tsconfig.base", 3 | "compilerOptions": { 4 | "strict": true 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /types/app.ts: -------------------------------------------------------------------------------- 1 | import { Audio } from "expo-av"; 2 | 3 | export type ArrElement = ArrType extends readonly (infer ElementType)[] 4 | ? ElementType 5 | : never; 6 | 7 | export type IPostBuilder = { 8 | imageUri: string; 9 | deletePost?: (id: string) => void; 10 | photo?: { uri: string; height: number; width: number }; 11 | name: string; 12 | userId?: string; 13 | date: Date; 14 | myPost?: boolean; 15 | userTag: string; 16 | comments?: number; 17 | isLiked: boolean; 18 | isReposted: boolean; 19 | verified: boolean; 20 | photoUri: string[]; 21 | videoUri?: string; 22 | videoTitle?: string; 23 | postText: string; 24 | videoViews?: string; 25 | repost?: string; 26 | title?: string; 27 | link: { 28 | id: string; 29 | imageHeight?: number; 30 | imageUri?: string; 31 | imageWidth?: number; 32 | title: string; 33 | } | null; 34 | thumbNail: string | null; 35 | like: number; 36 | id: string; 37 | audioUri?: string; 38 | postId?: string; 39 | inView?: boolean; 40 | idx:number; 41 | 42 | }; 43 | 44 | export type SearchPostBuilder = { 45 | imageUri: string; 46 | userTag: string; 47 | verified: boolean; 48 | photoUri: string[]; 49 | videoUri?: string; 50 | postText: string; 51 | title?: string; 52 | id: string; 53 | audioUri?: string; 54 | }; 55 | 56 | export type ICommentBuilder = { 57 | imageUri: string; 58 | name: string; 59 | comment: string; 60 | date: string; 61 | userTag: string; 62 | verified: boolean; 63 | photoUri: string[]; 64 | id: string; 65 | }; 66 | 67 | export type ICommentContent = { 68 | name: string; 69 | id: string; 70 | comment: string; 71 | }; 72 | 73 | export type ChatType = { 74 | id: string | number; 75 | user: { 76 | id: string | number; 77 | imageUri: string; 78 | name: string; 79 | userName: string; 80 | }; 81 | messages: { 82 | id: string | number; 83 | text: string; 84 | createdAt: string; 85 | sender: { 86 | id: string; 87 | userName: string; 88 | }; 89 | }[]; 90 | }; 91 | -------------------------------------------------------------------------------- /types/socket.ts: -------------------------------------------------------------------------------- 1 | export interface IMessageSocket { 2 | message: { 3 | sender: { userName: string; id: string }; 4 | text: string; 5 | id: string; 6 | createdAt: string; 7 | }; 8 | imageUri :string; 9 | chatId: string; 10 | } 11 | -------------------------------------------------------------------------------- /util/chatSearch.ts: -------------------------------------------------------------------------------- 1 | async function asyncFind(array: Array, predicate: any) { 2 | for (const item of array) { 3 | if (await predicate(item)) { 4 | return item; 5 | } 6 | } 7 | return undefined; 8 | } 9 | 10 | export async function findChatById(id: string, list: Array) { 11 | return asyncFind(list, async (chat: any) => chat.id === id); 12 | } 13 | -------------------------------------------------------------------------------- /util/convert.ts: -------------------------------------------------------------------------------- 1 | export default function convertMsToHMS(ms: number) { 2 | const seconds = Math.floor((ms / 1000) % 60); 3 | const minutes = Math.floor((ms / (1000 * 60)) % 60); 4 | const hours = Math.floor(ms / (1000 * 60 * 60)); 5 | 6 | if (hours === 0) { 7 | return `${minutes < 10 ? `0${minutes}` : minutes}:${ 8 | seconds < 10 ? `0${seconds}` : seconds 9 | }`; 10 | } 11 | return `${hours}:${minutes.toString()}:${seconds}`; 12 | } 13 | 14 | -------------------------------------------------------------------------------- /util/date.ts: -------------------------------------------------------------------------------- 1 | export const dateAgo = (date: Date) => { 2 | const currentDatetime = new Date(); 3 | 4 | const timeDifference = currentDatetime.getTime() - date.getTime(); 5 | 6 | const minutesAgo = Math.floor(timeDifference / (1000 * 60)); 7 | const hoursAgo = Math.floor(timeDifference / (1000 * 60 * 60)); 8 | const daysAgo = Math.floor(timeDifference / (1000 * 60 * 60 * 24)); 9 | const secondsAgo = Math.floor(timeDifference / 1000); 10 | let result; 11 | 12 | if (secondsAgo < 60) { 13 | result = `${secondsAgo}s`; 14 | } else if (minutesAgo < 60) { 15 | result = `${minutesAgo}m`; 16 | } else if (hoursAgo < 24) { 17 | result = `${hoursAgo}h`; 18 | } else { 19 | result = `${daysAgo}d`; 20 | } 21 | 22 | return result; 23 | }; 24 | 25 | export const dateFormatted = (date: Date) => { 26 | const months = [ 27 | "Jan", 28 | "Feb", 29 | "Mar", 30 | "Apr", 31 | "May", 32 | "Jun", 33 | "Jul", 34 | "Aug", 35 | "Sep", 36 | "Oct", 37 | "Nov", 38 | "Dec", 39 | ]; 40 | const formattedDate = `${date.getDate()} ${months[date.getMonth()]} ${date 41 | .getFullYear() 42 | .toString() 43 | .slice(-2)}, ${formatAMPM()}`; 44 | 45 | return formattedDate; 46 | 47 | function formatAMPM() { 48 | let hours = date.getHours(); 49 | let minutes = date.getMinutes(); 50 | const ampm = hours >= 12 ? "PM" : "AM"; 51 | hours %= 12; 52 | hours = hours || 12; 53 | const minutesStr = minutes < 10 ? `0${minutes}` : minutes.toString(); 54 | return `${hours}:${minutesStr} ${ampm}`; 55 | } 56 | }; 57 | 58 | export function formatDateForChat(inputDateStr: string) { 59 | const inputDate = new Date(inputDateStr); 60 | const currentDate = new Date(); 61 | 62 | // Check if the input date is today 63 | if ( 64 | inputDate.getDate() === currentDate.getDate() && 65 | inputDate.getMonth() === currentDate.getMonth() && 66 | inputDate.getFullYear() === currentDate.getFullYear() 67 | ) { 68 | // If it's today, format as HH:mm 69 | const hours = String(inputDate.getHours()).padStart(2, "0"); 70 | const minutes = String(inputDate.getMinutes()).padStart(2, "0"); 71 | return `${hours}:${minutes}`; 72 | } else { 73 | // If it's not today, format as dd/mm HH:mm 74 | const day = String(inputDate.getDate()).padStart(2, "0"); 75 | const month = String(inputDate.getMonth() + 1).padStart(2, "0"); // Month is zero-based 76 | const hours = String(inputDate.getHours()).padStart(2, "0"); 77 | const minutes = String(inputDate.getMinutes()).padStart(2, "0"); 78 | return `${day}/${month} ${hours}:${minutes}`; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /util/emoji.ts: -------------------------------------------------------------------------------- 1 | export function isEmoji(str: string): boolean { 2 | 3 | 4 | const emojiPattern = /\p{Emoji}/u; 5 | 6 | return emojiPattern.test(str) && str?.length <= 5; 7 | } 8 | -------------------------------------------------------------------------------- /util/notification.ts: -------------------------------------------------------------------------------- 1 | import * as Notifications from "expo-notifications"; 2 | import { Platform } from "react-native"; 3 | 4 | Notifications.setNotificationHandler({ 5 | handleNotification: async () => ({ 6 | shouldShowAlert: true, 7 | shouldPlaySound: false, 8 | shouldSetBadge: true, 9 | }), 10 | }); 11 | 12 | export default Notifications; 13 | -------------------------------------------------------------------------------- /util/socket.ts: -------------------------------------------------------------------------------- 1 | import { io } from "socket.io-client"; 2 | import storage from "../redux/storage"; 3 | import { store } from "../redux/store"; 4 | 5 | 6 | const persistRoot = storage.getString("persist:root"); 7 | const userId = (): string | undefined => { 8 | if (persistRoot) { 9 | const routes = JSON.parse(persistRoot); 10 | if (routes) { 11 | const user = JSON.parse(routes.user); 12 | 13 | return user.token; 14 | } 15 | return undefined; 16 | } 17 | return undefined; 18 | }; 19 | userId(); 20 | 21 | const socket = io(process.env.EXPO_PUBLIC_API_URL as string, { 22 | autoConnect: true, 23 | auth: { 24 | token: userId(), 25 | }, 26 | }); 27 | export default socket; 28 | --------------------------------------------------------------------------------