diff --git a/App.js b/App.js
index b49840a..e09fae4 100644
--- a/App.js
+++ b/App.js
@@ -6,6 +6,7 @@ import { ExploreScreen } from "./src/screens/ExploreScreen.js";
import { MutualScreen } from "./src/screens/MutualScreen.js";
import { CreatePost } from "./src/screens/CreatePost.js";
import { CalendarScreen } from "./src/screens/CalendarScreen.js";
+import { WorkoutsScreen } from "./src/screens/WorkoutsScreen.js";
import { GoalsScreen } from "./src/screens/GoalsScreen.js";
import { ProfileScreen } from "./src/screens/ProfileScreen.js";
import { FollowerScreen } from "./src/screens/FollowerScreen.js";
@@ -18,6 +19,8 @@ import { withAuthenticator, AmplifyTheme } from "aws-amplify-react-native";
import { StyleSheet, View, TitleText } from "react-native";
import { Storage } from "@aws-amplify/storage";
import * as clients3 from "@aws-sdk/client-s3";
+import { useState } from "react";
+import { Toast } from "react-native-toast-message/lib/src/Toast.js";
import { blueThemeColor } from "./src/library/constants.js";
Amplify.configure({
@@ -49,42 +52,43 @@ Amplify.configure({
const Stack = createMaterialTopTabNavigator();
const app = () => {
+ const [refresh, setRefresh] = useState(false);
return (
-
-
-
- {/* */}
-
-
- {/* */}
- {/* */}
-
-
-
- {/* */}
-
-
+ <>
+
+
+
+ {/* */}
+ {(props) => }
+ {(props) => }
+ {/* */}
+ {/* */}
+
+
+
+
+ {/* */}
+
+
+
+ >
);
};
diff --git a/assets/loading.gif b/assets/loading.gif
new file mode 100644
index 0000000..9590093
Binary files /dev/null and b/assets/loading.gif differ
diff --git a/ios/.gitignore b/ios/.gitignore
new file mode 100644
index 0000000..8beb344
--- /dev/null
+++ b/ios/.gitignore
@@ -0,0 +1,30 @@
+# OSX
+#
+.DS_Store
+
+# Xcode
+#
+build/
+*.pbxuser
+!default.pbxuser
+*.mode1v3
+!default.mode1v3
+*.mode2v3
+!default.mode2v3
+*.perspectivev3
+!default.perspectivev3
+xcuserdata
+*.xccheckout
+*.moved-aside
+DerivedData
+*.hmap
+*.ipa
+*.xcuserstate
+project.xcworkspace
+.xcode.env.local
+
+# Bundle artifacts
+*.jsbundle
+
+# CocoaPods
+/Pods/
diff --git a/ios/.xcode.env b/ios/.xcode.env
new file mode 100644
index 0000000..3d5782c
--- /dev/null
+++ b/ios/.xcode.env
@@ -0,0 +1,11 @@
+# This `.xcode.env` file is versioned and is used to source the environment
+# used when running script phases inside Xcode.
+# To customize your local environment, you can create an `.xcode.env.local`
+# file that is not versioned.
+
+# NODE_BINARY variable contains the PATH to the node executable.
+#
+# Customize the NODE_BINARY variable here.
+# For example, to use nvm with brew, add the following line
+# . "$(brew --prefix nvm)/nvm.sh" --no-use
+export NODE_BINARY=$(command -v node)
diff --git a/ios/NunchuckDucks.xcodeproj/project.pbxproj b/ios/NunchuckDucks.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..259f0ec
--- /dev/null
+++ b/ios/NunchuckDucks.xcodeproj/project.pbxproj
@@ -0,0 +1,493 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 102A44CA1A0940D383E99876 /* noop-file.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD52004E5FCE45C49FE9A449 /* noop-file.swift */; };
+ 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.mm */; };
+ 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
+ 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
+ 3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */; };
+ 96905EF65AED1B983A6B3ABC /* libPods-NunchuckDucks.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-NunchuckDucks.a */; };
+ B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */; };
+ BB2F792D24A3F905000567C9 /* Expo.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB2F792C24A3F905000567C9 /* Expo.plist */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+ 008F07F21AC5B25A0029DE68 /* main.jsbundle */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = main.jsbundle; sourceTree = ""; };
+ 13B07F961A680F5B00A75B9A /* NunchuckDucks.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NunchuckDucks.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = NunchuckDucks/AppDelegate.h; sourceTree = ""; };
+ 13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = NunchuckDucks/AppDelegate.mm; sourceTree = ""; };
+ 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = NunchuckDucks/Images.xcassets; sourceTree = ""; };
+ 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = NunchuckDucks/Info.plist; sourceTree = ""; };
+ 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = NunchuckDucks/main.m; sourceTree = ""; };
+ 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-NunchuckDucks.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-NunchuckDucks.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+ 6C2E3173556A471DD304B334 /* Pods-NunchuckDucks.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NunchuckDucks.debug.xcconfig"; path = "Target Support Files/Pods-NunchuckDucks/Pods-NunchuckDucks.debug.xcconfig"; sourceTree = ""; };
+ 7A4D352CD337FB3A3BF06240 /* Pods-NunchuckDucks.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NunchuckDucks.release.xcconfig"; path = "Target Support Files/Pods-NunchuckDucks/Pods-NunchuckDucks.release.xcconfig"; sourceTree = ""; };
+ AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = NunchuckDucks/SplashScreen.storyboard; sourceTree = ""; };
+ BB2F792C24A3F905000567C9 /* Expo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Expo.plist; sourceTree = ""; };
+ ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
+ FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-NunchuckDucks/ExpoModulesProvider.swift"; sourceTree = ""; };
+ FD52004E5FCE45C49FE9A449 /* noop-file.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = "noop-file.swift"; path = "NunchuckDucks/noop-file.swift"; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 13B07F8C1A680F5B00A75B9A /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 96905EF65AED1B983A6B3ABC /* libPods-NunchuckDucks.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 13B07FAE1A68108700A75B9A /* NunchuckDucks */ = {
+ isa = PBXGroup;
+ children = (
+ BB2F792B24A3F905000567C9 /* Supporting */,
+ 008F07F21AC5B25A0029DE68 /* main.jsbundle */,
+ 13B07FAF1A68108700A75B9A /* AppDelegate.h */,
+ 13B07FB01A68108700A75B9A /* AppDelegate.mm */,
+ 13B07FB51A68108700A75B9A /* Images.xcassets */,
+ 13B07FB61A68108700A75B9A /* Info.plist */,
+ 13B07FB71A68108700A75B9A /* main.m */,
+ AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */,
+ FD52004E5FCE45C49FE9A449 /* noop-file.swift */,
+ );
+ name = NunchuckDucks;
+ sourceTree = "";
+ };
+ 2D16E6871FA4F8E400B85C8A /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ ED297162215061F000B7C4FE /* JavaScriptCore.framework */,
+ 58EEBF8E8E6FB1BC6CAF49B5 /* libPods-NunchuckDucks.a */,
+ );
+ name = Frameworks;
+ sourceTree = "";
+ };
+ 832341AE1AAA6A7D00B99B32 /* Libraries */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Libraries;
+ sourceTree = "";
+ };
+ 83CBB9F61A601CBA00E9B192 = {
+ isa = PBXGroup;
+ children = (
+ 13B07FAE1A68108700A75B9A /* NunchuckDucks */,
+ 832341AE1AAA6A7D00B99B32 /* Libraries */,
+ 83CBBA001A601CBA00E9B192 /* Products */,
+ 2D16E6871FA4F8E400B85C8A /* Frameworks */,
+ D65327D7A22EEC0BE12398D9 /* Pods */,
+ D7E4C46ADA2E9064B798F356 /* ExpoModulesProviders */,
+ );
+ indentWidth = 2;
+ sourceTree = "";
+ tabWidth = 2;
+ usesTabs = 0;
+ };
+ 83CBBA001A601CBA00E9B192 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 13B07F961A680F5B00A75B9A /* NunchuckDucks.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 92DBD88DE9BF7D494EA9DA96 /* NunchuckDucks */ = {
+ isa = PBXGroup;
+ children = (
+ FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */,
+ );
+ name = NunchuckDucks;
+ sourceTree = "";
+ };
+ BB2F792B24A3F905000567C9 /* Supporting */ = {
+ isa = PBXGroup;
+ children = (
+ BB2F792C24A3F905000567C9 /* Expo.plist */,
+ );
+ name = Supporting;
+ path = NunchuckDucks/Supporting;
+ sourceTree = "";
+ };
+ D65327D7A22EEC0BE12398D9 /* Pods */ = {
+ isa = PBXGroup;
+ children = (
+ 6C2E3173556A471DD304B334 /* Pods-NunchuckDucks.debug.xcconfig */,
+ 7A4D352CD337FB3A3BF06240 /* Pods-NunchuckDucks.release.xcconfig */,
+ );
+ path = Pods;
+ sourceTree = "";
+ };
+ D7E4C46ADA2E9064B798F356 /* ExpoModulesProviders */ = {
+ isa = PBXGroup;
+ children = (
+ 92DBD88DE9BF7D494EA9DA96 /* NunchuckDucks */,
+ );
+ name = ExpoModulesProviders;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 13B07F861A680F5B00A75B9A /* NunchuckDucks */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "NunchuckDucks" */;
+ buildPhases = (
+ 08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */,
+ FD10A7F022414F080027D42C /* Start Packager */,
+ 13B07F871A680F5B00A75B9A /* Sources */,
+ 13B07F8C1A680F5B00A75B9A /* Frameworks */,
+ 13B07F8E1A680F5B00A75B9A /* Resources */,
+ 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
+ 800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = NunchuckDucks;
+ productName = NunchuckDucks;
+ productReference = 13B07F961A680F5B00A75B9A /* NunchuckDucks.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 83CBB9F71A601CBA00E9B192 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 1130;
+ TargetAttributes = {
+ 13B07F861A680F5B00A75B9A = {
+ LastSwiftMigration = 1250;
+ };
+ };
+ };
+ buildConfigurationList = 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "NunchuckDucks" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 83CBB9F61A601CBA00E9B192;
+ productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 13B07F861A680F5B00A75B9A /* NunchuckDucks */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 13B07F8E1A680F5B00A75B9A /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ BB2F792D24A3F905000567C9 /* Expo.plist in Resources */,
+ 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
+ 3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "Bundle React Native code and images";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "if [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\n source \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n# The project root by default is one level up from the ios directory\nexport PROJECT_ROOT=\"$PROJECT_DIR\"/..\n\nif [[ \"$CONFIGURATION\" = *Debug* ]]; then\n export SKIP_BUNDLING=1\nfi\nif [[ -z \"$ENTRY_FILE\" ]]; then\n # Set the entry JS file using the bundler's entry resolution.\n export ENTRY_FILE=\"$(\"$NODE_BINARY\" -e \"require('expo/scripts/resolveAppEntry')\" $PROJECT_ROOT ios relative | tail -n 1)\"\nfi\n\n`\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\"`\n\n";
+ };
+ 08A4A3CD28434E44B6B9DE2E /* [CP] Check Pods Manifest.lock */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ "${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+ "${PODS_ROOT}/Manifest.lock",
+ );
+ name = "[CP] Check Pods Manifest.lock";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ "$(DERIVED_FILE_DIR)/Pods-NunchuckDucks-checkManifestLockResult.txt",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+ showEnvVarsInLog = 0;
+ };
+ 800E24972A6A228C8D4807E9 /* [CP] Copy Pods Resources */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "${PODS_ROOT}/Target Support Files/Pods-NunchuckDucks/Pods-NunchuckDucks-resources.sh",
+ "${PODS_CONFIGURATION_BUILD_DIR}/EXConstants/EXConstants.bundle",
+ "${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle",
+ "${PODS_CONFIGURATION_BUILD_DIR}/expo-dev-launcher/EXDevLauncher.bundle",
+ "${PODS_CONFIGURATION_BUILD_DIR}/expo-dev-menu/EXDevMenu.bundle",
+ );
+ name = "[CP] Copy Pods Resources";
+ outputPaths = (
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXConstants.bundle",
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle",
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXDevLauncher.bundle",
+ "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/EXDevMenu.bundle",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NunchuckDucks/Pods-NunchuckDucks-resources.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
+ FD10A7F022414F080027D42C /* Start Packager */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputFileListPaths = (
+ );
+ inputPaths = (
+ );
+ name = "Start Packager";
+ outputFileListPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "if [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\n source \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\nexport RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > `$NODE_BINARY --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/.packager.env'\"`\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n exit 2\n fi\n else\n open `$NODE_BINARY --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/launchPackager.command'\"` || echo \"Can't start packager automatically\"\n fi\nfi\n";
+ showEnvVarsInLog = 0;
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 13B07F871A680F5B00A75B9A /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */,
+ 13B07FC11A68108700A75B9A /* main.m in Sources */,
+ B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */,
+ 102A44CA1A0940D383E99876 /* noop-file.swift in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+ 13B07F941A680F5B00A75B9A /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 6C2E3173556A471DD304B334 /* Pods-NunchuckDucks.debug.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = NunchuckDucks/NunchuckDucks.entitlements;
+ CURRENT_PROJECT_VERSION = 1;
+ ENABLE_BITCODE = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "$(inherited)",
+ "FB_SONARKIT_ENABLED=1",
+ );
+ INFOPLIST_FILE = NunchuckDucks/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ OTHER_LDFLAGS = (
+ "$(inherited)",
+ "-ObjC",
+ "-lc++",
+ );
+ OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
+ PRODUCT_BUNDLE_IDENTIFIER = com.jewzydee.gymbit;
+ PRODUCT_NAME = NunchuckDucks;
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Debug;
+ };
+ 13B07F951A680F5B00A75B9A /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7A4D352CD337FB3A3BF06240 /* Pods-NunchuckDucks.release.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CODE_SIGN_ENTITLEMENTS = NunchuckDucks/NunchuckDucks.entitlements;
+ CURRENT_PROJECT_VERSION = 1;
+ INFOPLIST_FILE = NunchuckDucks/Info.plist;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
+ OTHER_LDFLAGS = (
+ "$(inherited)",
+ "-ObjC",
+ "-lc++",
+ );
+ OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
+ PRODUCT_BUNDLE_IDENTIFIER = com.jewzydee.gymbit;
+ PRODUCT_NAME = NunchuckDucks;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Release;
+ };
+ 83CBBA201A601CBA00E9B192 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+ LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)";
+ LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\"";
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
+ SDKROOT = iphoneos;
+ };
+ name = Debug;
+ };
+ 83CBBA211A601CBA00E9B192 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "c++17";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = YES;
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "";
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
+ LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)";
+ LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\"";
+ MTL_ENABLE_DEBUG_INFO = NO;
+ REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
+ SDKROOT = iphoneos;
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "NunchuckDucks" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 13B07F941A680F5B00A75B9A /* Debug */,
+ 13B07F951A680F5B00A75B9A /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 83CBB9FA1A601CBA00E9B192 /* Build configuration list for PBXProject "NunchuckDucks" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 83CBBA201A601CBA00E9B192 /* Debug */,
+ 83CBBA211A601CBA00E9B192 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 83CBB9F71A601CBA00E9B192 /* Project object */;
+}
diff --git a/ios/NunchuckDucks.xcodeproj/xcshareddata/xcschemes/NunchuckDucks.xcscheme b/ios/NunchuckDucks.xcodeproj/xcshareddata/xcschemes/NunchuckDucks.xcscheme
new file mode 100644
index 0000000..7b01acd
--- /dev/null
+++ b/ios/NunchuckDucks.xcodeproj/xcshareddata/xcschemes/NunchuckDucks.xcscheme
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ios/NunchuckDucks.xcworkspace/contents.xcworkspacedata b/ios/NunchuckDucks.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 0000000..23fb1c9
--- /dev/null
+++ b/ios/NunchuckDucks.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
diff --git a/ios/NunchuckDucks/AppDelegate.h b/ios/NunchuckDucks/AppDelegate.h
new file mode 100644
index 0000000..f7d2972
--- /dev/null
+++ b/ios/NunchuckDucks/AppDelegate.h
@@ -0,0 +1,9 @@
+#import
+#import
+#import
+
+#import
+
+@interface AppDelegate : EXAppDelegateWrapper
+
+@end
diff --git a/ios/NunchuckDucks/AppDelegate.mm b/ios/NunchuckDucks/AppDelegate.mm
new file mode 100644
index 0000000..a6e13e1
--- /dev/null
+++ b/ios/NunchuckDucks/AppDelegate.mm
@@ -0,0 +1,166 @@
+#import "AppDelegate.h"
+
+#import
+#import
+#import
+#import
+#import
+
+#import
+
+#if RCT_NEW_ARCH_ENABLED
+#import
+#import
+#import
+#import
+#import
+#import
+
+#import
+
+static NSString *const kRNConcurrentRoot = @"concurrentRoot";
+
+@interface AppDelegate () {
+ RCTTurboModuleManager *_turboModuleManager;
+ RCTSurfacePresenterBridgeAdapter *_bridgeAdapter;
+ std::shared_ptr _reactNativeConfig;
+ facebook::react::ContextContainer::Shared _contextContainer;
+}
+@end
+#endif
+
+@implementation AppDelegate
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+{
+ RCTAppSetupPrepareApp(application);
+
+ RCTBridge *bridge = [self.reactDelegate createBridgeWithDelegate:self launchOptions:launchOptions];
+
+#if RCT_NEW_ARCH_ENABLED
+ _contextContainer = std::make_shared();
+ _reactNativeConfig = std::make_shared();
+ _contextContainer->insert("ReactNativeConfig", _reactNativeConfig);
+ _bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc] initWithBridge:bridge contextContainer:_contextContainer];
+ bridge.surfacePresenter = _bridgeAdapter.surfacePresenter;
+#endif
+
+ NSDictionary *initProps = [self prepareInitialProps];
+ UIView *rootView = [self.reactDelegate createRootViewWithBridge:bridge moduleName:@"main" initialProperties:initProps];
+
+ rootView.backgroundColor = [UIColor whiteColor];
+ self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
+ UIViewController *rootViewController = [self.reactDelegate createRootViewController];
+ rootViewController.view = rootView;
+ self.window.rootViewController = rootViewController;
+ [self.window makeKeyAndVisible];
+
+ [super application:application didFinishLaunchingWithOptions:launchOptions];
+
+ return YES;
+}
+
+- (NSArray> *)extraModulesForBridge:(RCTBridge *)bridge
+{
+ // If you'd like to export some custom RCTBridgeModules, add them here!
+ return @[];
+}
+
+/// This method controls whether the `concurrentRoot`feature of React18 is turned on or off.
+///
+/// @see: https://reactjs.org/blog/2022/03/29/react-v18.html
+/// @note: This requires to be rendering on Fabric (i.e. on the New Architecture).
+/// @return: `true` if the `concurrentRoot` feture is enabled. Otherwise, it returns `false`.
+- (BOOL)concurrentRootEnabled
+{
+ // Switch this bool to turn on and off the concurrent root
+ return true;
+}
+
+- (NSDictionary *)prepareInitialProps
+{
+ NSMutableDictionary *initProps = [NSMutableDictionary new];
+#if RCT_NEW_ARCH_ENABLED
+ initProps[kRNConcurrentRoot] = @([self concurrentRootEnabled]);
+#endif
+ return initProps;
+}
+
+- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
+{
+#if DEBUG
+ return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
+#else
+ return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
+#endif
+}
+
+// Linking API
+- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary *)options {
+ return [super application:application openURL:url options:options] || [RCTLinkingManager application:application openURL:url options:options];
+}
+
+// Universal Links
+- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity restorationHandler:(nonnull void (^)(NSArray> * _Nullable))restorationHandler {
+ BOOL result = [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
+ return [super application:application continueUserActivity:userActivity restorationHandler:restorationHandler] || result;
+}
+
+// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries
+- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
+{
+ return [super application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
+}
+
+// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries
+- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
+{
+ return [super application:application didFailToRegisterForRemoteNotificationsWithError:error];
+}
+
+// Explicitly define remote notification delegates to ensure compatibility with some third-party libraries
+- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
+{
+ return [super application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler];
+}
+
+#if RCT_NEW_ARCH_ENABLED
+
+#pragma mark - RCTCxxBridgeDelegate
+
+- (std::unique_ptr)jsExecutorFactoryForBridge:(RCTBridge *)bridge
+{
+ _turboModuleManager = [[RCTTurboModuleManager alloc] initWithBridge:bridge
+ delegate:self
+ jsInvoker:bridge.jsCallInvoker];
+ return RCTAppSetupDefaultJsExecutorFactory(bridge, _turboModuleManager);
+}
+
+#pragma mark RCTTurboModuleManagerDelegate
+
+- (Class)getModuleClassFromName:(const char *)name
+{
+ return RCTCoreModulesClassProvider(name);
+}
+
+- (std::shared_ptr)getTurboModule:(const std::string &)name
+ jsInvoker:(std::shared_ptr)jsInvoker
+{
+ return nullptr;
+}
+
+- (std::shared_ptr)getTurboModule:(const std::string &)name
+ initParams:
+ (const facebook::react::ObjCTurboModule::InitParams &)params
+{
+ return nullptr;
+}
+
+- (id)getModuleInstanceFromClass:(Class)moduleClass
+{
+ return RCTAppSetupDefaultModuleFromClass(moduleClass);
+}
+
+#endif
+
+@end
diff --git a/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-20x20@1x.png b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-20x20@1x.png
new file mode 100644
index 0000000..ae59862
Binary files /dev/null and b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-20x20@1x.png differ
diff --git a/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-20x20@2x.png b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-20x20@2x.png
new file mode 100644
index 0000000..ff9d541
Binary files /dev/null and b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-20x20@2x.png differ
diff --git a/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-20x20@3x.png b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-20x20@3x.png
new file mode 100644
index 0000000..ba79135
Binary files /dev/null and b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-20x20@3x.png differ
diff --git a/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-29x29@1x.png b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-29x29@1x.png
new file mode 100644
index 0000000..d2b59a9
Binary files /dev/null and b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-29x29@1x.png differ
diff --git a/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-29x29@2x.png b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-29x29@2x.png
new file mode 100644
index 0000000..597bdb4
Binary files /dev/null and b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-29x29@2x.png differ
diff --git a/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-29x29@3x.png b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-29x29@3x.png
new file mode 100644
index 0000000..2f0e2b6
Binary files /dev/null and b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-29x29@3x.png differ
diff --git a/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-40x40@1x.png b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-40x40@1x.png
new file mode 100644
index 0000000..ff9d541
Binary files /dev/null and b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-40x40@1x.png differ
diff --git a/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-40x40@2x.png b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-40x40@2x.png
new file mode 100644
index 0000000..3b83139
Binary files /dev/null and b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-40x40@2x.png differ
diff --git a/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-40x40@3x.png b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-40x40@3x.png
new file mode 100644
index 0000000..6cd063f
Binary files /dev/null and b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-40x40@3x.png differ
diff --git a/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-60x60@2x.png b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-60x60@2x.png
new file mode 100644
index 0000000..6cd063f
Binary files /dev/null and b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-60x60@2x.png differ
diff --git a/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-60x60@3x.png b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-60x60@3x.png
new file mode 100644
index 0000000..5239009
Binary files /dev/null and b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-60x60@3x.png differ
diff --git a/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-76x76@1x.png b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-76x76@1x.png
new file mode 100644
index 0000000..69908ae
Binary files /dev/null and b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-76x76@1x.png differ
diff --git a/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-76x76@2x.png b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-76x76@2x.png
new file mode 100644
index 0000000..04580c4
Binary files /dev/null and b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-76x76@2x.png differ
diff --git a/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-83.5x83.5@2x.png b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-83.5x83.5@2x.png
new file mode 100644
index 0000000..74e8e26
Binary files /dev/null and b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/App-Icon-83.5x83.5@2x.png differ
diff --git a/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/Contents.json b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 0000000..f920cb0
--- /dev/null
+++ b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,122 @@
+{
+ "images": [
+ {
+ "idiom": "iphone",
+ "size": "20x20",
+ "scale": "2x",
+ "filename": "App-Icon-20x20@2x.png"
+ },
+ {
+ "idiom": "iphone",
+ "size": "20x20",
+ "scale": "3x",
+ "filename": "App-Icon-20x20@3x.png"
+ },
+ {
+ "idiom": "iphone",
+ "size": "29x29",
+ "scale": "1x",
+ "filename": "App-Icon-29x29@1x.png"
+ },
+ {
+ "idiom": "iphone",
+ "size": "29x29",
+ "scale": "2x",
+ "filename": "App-Icon-29x29@2x.png"
+ },
+ {
+ "idiom": "iphone",
+ "size": "29x29",
+ "scale": "3x",
+ "filename": "App-Icon-29x29@3x.png"
+ },
+ {
+ "idiom": "iphone",
+ "size": "40x40",
+ "scale": "2x",
+ "filename": "App-Icon-40x40@2x.png"
+ },
+ {
+ "idiom": "iphone",
+ "size": "40x40",
+ "scale": "3x",
+ "filename": "App-Icon-40x40@3x.png"
+ },
+ {
+ "idiom": "iphone",
+ "size": "60x60",
+ "scale": "2x",
+ "filename": "App-Icon-60x60@2x.png"
+ },
+ {
+ "idiom": "iphone",
+ "size": "60x60",
+ "scale": "3x",
+ "filename": "App-Icon-60x60@3x.png"
+ },
+ {
+ "idiom": "ipad",
+ "size": "20x20",
+ "scale": "1x",
+ "filename": "App-Icon-20x20@1x.png"
+ },
+ {
+ "idiom": "ipad",
+ "size": "20x20",
+ "scale": "2x",
+ "filename": "App-Icon-20x20@2x.png"
+ },
+ {
+ "idiom": "ipad",
+ "size": "29x29",
+ "scale": "1x",
+ "filename": "App-Icon-29x29@1x.png"
+ },
+ {
+ "idiom": "ipad",
+ "size": "29x29",
+ "scale": "2x",
+ "filename": "App-Icon-29x29@2x.png"
+ },
+ {
+ "idiom": "ipad",
+ "size": "40x40",
+ "scale": "1x",
+ "filename": "App-Icon-40x40@1x.png"
+ },
+ {
+ "idiom": "ipad",
+ "size": "40x40",
+ "scale": "2x",
+ "filename": "App-Icon-40x40@2x.png"
+ },
+ {
+ "idiom": "ipad",
+ "size": "76x76",
+ "scale": "1x",
+ "filename": "App-Icon-76x76@1x.png"
+ },
+ {
+ "idiom": "ipad",
+ "size": "76x76",
+ "scale": "2x",
+ "filename": "App-Icon-76x76@2x.png"
+ },
+ {
+ "idiom": "ipad",
+ "size": "83.5x83.5",
+ "scale": "2x",
+ "filename": "App-Icon-83.5x83.5@2x.png"
+ },
+ {
+ "idiom": "ios-marketing",
+ "size": "1024x1024",
+ "scale": "1x",
+ "filename": "ItunesArtwork@2x.png"
+ }
+ ],
+ "info": {
+ "version": 1,
+ "author": "expo"
+ }
+}
\ No newline at end of file
diff --git a/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png
new file mode 100644
index 0000000..2732229
Binary files /dev/null and b/ios/NunchuckDucks/Images.xcassets/AppIcon.appiconset/ItunesArtwork@2x.png differ
diff --git a/ios/NunchuckDucks/Images.xcassets/Contents.json b/ios/NunchuckDucks/Images.xcassets/Contents.json
new file mode 100644
index 0000000..ed285c2
--- /dev/null
+++ b/ios/NunchuckDucks/Images.xcassets/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "expo"
+ }
+}
diff --git a/ios/NunchuckDucks/Images.xcassets/SplashScreen.imageset/Contents.json b/ios/NunchuckDucks/Images.xcassets/SplashScreen.imageset/Contents.json
new file mode 100644
index 0000000..3cf8489
--- /dev/null
+++ b/ios/NunchuckDucks/Images.xcassets/SplashScreen.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images": [
+ {
+ "idiom": "universal",
+ "filename": "image.png",
+ "scale": "1x"
+ },
+ {
+ "idiom": "universal",
+ "scale": "2x"
+ },
+ {
+ "idiom": "universal",
+ "scale": "3x"
+ }
+ ],
+ "info": {
+ "version": 1,
+ "author": "expo"
+ }
+}
\ No newline at end of file
diff --git a/ios/NunchuckDucks/Images.xcassets/SplashScreen.imageset/image.png b/ios/NunchuckDucks/Images.xcassets/SplashScreen.imageset/image.png
new file mode 100644
index 0000000..c52c2c6
Binary files /dev/null and b/ios/NunchuckDucks/Images.xcassets/SplashScreen.imageset/image.png differ
diff --git a/ios/NunchuckDucks/Images.xcassets/SplashScreenBackground.imageset/Contents.json b/ios/NunchuckDucks/Images.xcassets/SplashScreenBackground.imageset/Contents.json
new file mode 100644
index 0000000..3cf8489
--- /dev/null
+++ b/ios/NunchuckDucks/Images.xcassets/SplashScreenBackground.imageset/Contents.json
@@ -0,0 +1,21 @@
+{
+ "images": [
+ {
+ "idiom": "universal",
+ "filename": "image.png",
+ "scale": "1x"
+ },
+ {
+ "idiom": "universal",
+ "scale": "2x"
+ },
+ {
+ "idiom": "universal",
+ "scale": "3x"
+ }
+ ],
+ "info": {
+ "version": 1,
+ "author": "expo"
+ }
+}
\ No newline at end of file
diff --git a/ios/NunchuckDucks/Images.xcassets/SplashScreenBackground.imageset/image.png b/ios/NunchuckDucks/Images.xcassets/SplashScreenBackground.imageset/image.png
new file mode 100644
index 0000000..33ddf20
Binary files /dev/null and b/ios/NunchuckDucks/Images.xcassets/SplashScreenBackground.imageset/image.png differ
diff --git a/ios/NunchuckDucks/Info.plist b/ios/NunchuckDucks/Info.plist
new file mode 100644
index 0000000..a9c0616
--- /dev/null
+++ b/ios/NunchuckDucks/Info.plist
@@ -0,0 +1,88 @@
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleDisplayName
+ NunchuckDucks
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ $(PRODUCT_NAME)
+ CFBundlePackageType
+ $(PRODUCT_BUNDLE_PACKAGE_TYPE)
+ CFBundleShortVersionString
+ 1.0.0
+ CFBundleSignature
+ ????
+ CFBundleURLTypes
+
+
+ CFBundleURLSchemes
+
+ com.jewzydee.gymbit
+
+
+
+ CFBundleURLSchemes
+
+ exp+gymbit
+
+
+
+ CFBundleVersion
+ 1
+ LSRequiresIPhoneOS
+
+ NSAppTransportSecurity
+
+ NSAllowsArbitraryLoads
+
+ NSExceptionDomains
+
+ localhost
+
+ NSExceptionAllowsInsecureHTTPLoads
+
+
+
+
+ NSCameraUsageDescription
+ Allow $(PRODUCT_NAME) to access your camera
+ NSMicrophoneUsageDescription
+ Allow $(PRODUCT_NAME) to access your microphone
+ NSPhotoLibraryUsageDescription
+ Allow $(PRODUCT_NAME) to access your photos
+ UILaunchStoryboardName
+ SplashScreen
+ UIRequiredDeviceCapabilities
+
+ armv7
+
+ UIRequiresFullScreen
+
+ UIStatusBarStyle
+ UIStatusBarStyleDefault
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UIUserInterfaceStyle
+ Light
+ UIViewControllerBasedStatusBarAppearance
+
+
+
\ No newline at end of file
diff --git a/ios/NunchuckDucks/NunchuckDucks.entitlements b/ios/NunchuckDucks/NunchuckDucks.entitlements
new file mode 100644
index 0000000..018a6e2
--- /dev/null
+++ b/ios/NunchuckDucks/NunchuckDucks.entitlements
@@ -0,0 +1,8 @@
+
+
+
+
+ aps-environment
+ development
+
+
\ No newline at end of file
diff --git a/ios/NunchuckDucks/SplashScreen.storyboard b/ios/NunchuckDucks/SplashScreen.storyboard
new file mode 100644
index 0000000..ed03a52
--- /dev/null
+++ b/ios/NunchuckDucks/SplashScreen.storyboard
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ios/NunchuckDucks/Supporting/Expo.plist b/ios/NunchuckDucks/Supporting/Expo.plist
new file mode 100644
index 0000000..6055895
--- /dev/null
+++ b/ios/NunchuckDucks/Supporting/Expo.plist
@@ -0,0 +1,16 @@
+
+
+
+
+ EXUpdatesCheckOnLaunch
+ ALWAYS
+ EXUpdatesEnabled
+
+ EXUpdatesLaunchWaitMs
+ 0
+ EXUpdatesSDKVersion
+ 47.0.0
+ EXUpdatesURL
+ https://exp.host/@jewzydee/gymbit
+
+
\ No newline at end of file
diff --git a/ios/NunchuckDucks/main.m b/ios/NunchuckDucks/main.m
new file mode 100644
index 0000000..25181b6
--- /dev/null
+++ b/ios/NunchuckDucks/main.m
@@ -0,0 +1,10 @@
+#import
+
+#import "AppDelegate.h"
+
+int main(int argc, char * argv[]) {
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+ }
+}
+
diff --git a/ios/NunchuckDucks/noop-file.swift b/ios/NunchuckDucks/noop-file.swift
new file mode 100644
index 0000000..b2ffafb
--- /dev/null
+++ b/ios/NunchuckDucks/noop-file.swift
@@ -0,0 +1,4 @@
+//
+// @generated
+// A blank Swift file must be created for native modules with Swift files to work correctly.
+//
diff --git a/ios/Podfile b/ios/Podfile
new file mode 100644
index 0000000..6e218c6
--- /dev/null
+++ b/ios/Podfile
@@ -0,0 +1,61 @@
+require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking")
+require File.join(File.dirname(`node --print "require.resolve('react-native/package.json')"`), "scripts/react_native_pods")
+require File.join(File.dirname(`node --print "require.resolve('@react-native-community/cli-platform-ios/package.json')"`), "native_modules")
+
+require 'json'
+podfile_properties = JSON.parse(File.read(File.join(__dir__, 'Podfile.properties.json'))) rescue {}
+
+platform :ios, podfile_properties['ios.deploymentTarget'] || '13.0'
+install! 'cocoapods',
+ :deterministic_uuids => false
+
+target 'NunchuckDucks' do
+ use_expo_modules!
+ config = use_native_modules!
+
+ use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks']
+
+ # Flags change depending on the env values.
+ flags = get_default_flags()
+
+ use_react_native!(
+ :path => config[:reactNativePath],
+ :hermes_enabled => podfile_properties['expo.jsEngine'] == 'hermes',
+ :fabric_enabled => flags[:fabric_enabled],
+ # An absolute path to your application root.
+ :app_path => "#{Pod::Config.instance.installation_root}/..",
+ #
+ # Uncomment to opt-in to using Flipper
+ # Note that if you have use_frameworks! enabled, Flipper will not work
+ # :flipper_configuration => !ENV['CI'] ? FlipperConfiguration.enabled : FlipperConfiguration.disabled,
+ )
+
+ post_install do |installer|
+ react_native_post_install(
+ installer,
+ # Set `mac_catalyst_enabled` to `true` in order to apply patches
+ # necessary for Mac Catalyst builds
+ :mac_catalyst_enabled => false
+ )
+ __apply_Xcode_12_5_M1_post_install_workaround(installer)
+
+ # This is necessary for Xcode 14, because it signs resource bundles by default
+ # when building for devices.
+ installer.target_installation_results.pod_target_installation_results
+ .each do |pod_name, target_installation_result|
+ target_installation_result.resource_bundle_targets.each do |resource_bundle_target|
+ resource_bundle_target.build_configurations.each do |config|
+ config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
+ end
+ end
+ end
+ end
+
+ post_integrate do |installer|
+ begin
+ expo_patch_react_imports!(installer)
+ rescue => e
+ Pod::UI.warn e
+ end
+ end
+end
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
new file mode 100644
index 0000000..8972d4a
--- /dev/null
+++ b/ios/Podfile.lock
@@ -0,0 +1,688 @@
+PODS:
+ - boost (1.76.0)
+ - DoubleConversion (1.1.6)
+ - EXApplication (5.0.1):
+ - ExpoModulesCore
+ - EXConstants (14.0.2):
+ - ExpoModulesCore
+ - EXFileSystem (15.1.1):
+ - ExpoModulesCore
+ - EXFont (11.0.1):
+ - ExpoModulesCore
+ - EXImageLoader (4.0.0):
+ - ExpoModulesCore
+ - React-Core
+ - EXJSONUtils (0.4.0)
+ - EXManifests (0.4.0):
+ - EXJSONUtils
+ - Expo (47.0.13):
+ - ExpoModulesCore
+ - expo-dev-client (2.0.1):
+ - EXManifests
+ - expo-dev-launcher
+ - expo-dev-menu
+ - expo-dev-menu-interface
+ - EXUpdatesInterface
+ - expo-dev-launcher (2.0.2):
+ - EXManifests
+ - expo-dev-launcher/Main (= 2.0.2)
+ - expo-dev-menu
+ - expo-dev-menu-interface
+ - ExpoModulesCore
+ - EXUpdatesInterface
+ - React-Core
+ - expo-dev-launcher/Main (2.0.2):
+ - EXManifests
+ - expo-dev-launcher/Unsafe
+ - expo-dev-menu
+ - expo-dev-menu-interface
+ - ExpoModulesCore
+ - EXUpdatesInterface
+ - React-Core
+ - expo-dev-launcher/Unsafe (2.0.2):
+ - EXManifests
+ - expo-dev-menu
+ - expo-dev-menu-interface
+ - ExpoModulesCore
+ - EXUpdatesInterface
+ - React-Core
+ - expo-dev-menu (2.0.2):
+ - expo-dev-menu/Main (= 2.0.2)
+ - expo-dev-menu-interface (1.0.0)
+ - expo-dev-menu/GestureHandler (2.0.2)
+ - expo-dev-menu/Main (2.0.2):
+ - EXManifests
+ - expo-dev-menu-interface
+ - expo-dev-menu/Vendored
+ - ExpoModulesCore
+ - React-Core
+ - expo-dev-menu/Reanimated (2.0.2):
+ - DoubleConversion
+ - FBLazyVector
+ - FBReactNativeSpec
+ - glog
+ - RCT-Folly
+ - RCTRequired
+ - RCTTypeSafety
+ - React-callinvoker
+ - React-Core
+ - React-Core/DevSupport
+ - React-Core/RCTWebSocket
+ - React-CoreModules
+ - React-cxxreact
+ - React-jsi
+ - React-jsiexecutor
+ - React-jsinspector
+ - React-RCTActionSheet
+ - React-RCTAnimation
+ - React-RCTBlob
+ - React-RCTImage
+ - React-RCTLinking
+ - React-RCTNetwork
+ - React-RCTSettings
+ - React-RCTText
+ - React-RCTVibration
+ - ReactCommon/turbomodule/core
+ - Yoga
+ - expo-dev-menu/SafeAreaView (2.0.2)
+ - expo-dev-menu/Vendored (2.0.2):
+ - expo-dev-menu/GestureHandler
+ - expo-dev-menu/Reanimated
+ - expo-dev-menu/SafeAreaView
+ - ExpoImagePicker (14.0.3):
+ - ExpoModulesCore
+ - ExpoKeepAwake (11.0.1):
+ - ExpoModulesCore
+ - ExpoModulesCore (1.1.1):
+ - React-Core
+ - ReactCommon/turbomodule/core
+ - EXSplashScreen (0.17.5):
+ - ExpoModulesCore
+ - React-Core
+ - EXUpdatesInterface (0.8.1)
+ - FBLazyVector (0.70.5)
+ - FBReactNativeSpec (0.70.5):
+ - RCT-Folly (= 2021.07.22.00)
+ - RCTRequired (= 0.70.5)
+ - RCTTypeSafety (= 0.70.5)
+ - React-Core (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - ReactCommon/turbomodule/core (= 0.70.5)
+ - fmt (6.2.1)
+ - glog (0.3.5)
+ - libwebp (1.2.4):
+ - libwebp/demux (= 1.2.4)
+ - libwebp/mux (= 1.2.4)
+ - libwebp/webp (= 1.2.4)
+ - libwebp/demux (1.2.4):
+ - libwebp/webp
+ - libwebp/mux (1.2.4):
+ - libwebp/demux
+ - libwebp/webp (1.2.4)
+ - RCT-Folly (2021.07.22.00):
+ - boost
+ - DoubleConversion
+ - fmt (~> 6.2.1)
+ - glog
+ - RCT-Folly/Default (= 2021.07.22.00)
+ - RCT-Folly/Default (2021.07.22.00):
+ - boost
+ - DoubleConversion
+ - fmt (~> 6.2.1)
+ - glog
+ - RCTRequired (0.70.5)
+ - RCTTypeSafety (0.70.5):
+ - FBLazyVector (= 0.70.5)
+ - RCTRequired (= 0.70.5)
+ - React-Core (= 0.70.5)
+ - React (0.70.5):
+ - React-Core (= 0.70.5)
+ - React-Core/DevSupport (= 0.70.5)
+ - React-Core/RCTWebSocket (= 0.70.5)
+ - React-RCTActionSheet (= 0.70.5)
+ - React-RCTAnimation (= 0.70.5)
+ - React-RCTBlob (= 0.70.5)
+ - React-RCTImage (= 0.70.5)
+ - React-RCTLinking (= 0.70.5)
+ - React-RCTNetwork (= 0.70.5)
+ - React-RCTSettings (= 0.70.5)
+ - React-RCTText (= 0.70.5)
+ - React-RCTVibration (= 0.70.5)
+ - React-bridging (0.70.5):
+ - RCT-Folly (= 2021.07.22.00)
+ - React-jsi (= 0.70.5)
+ - React-callinvoker (0.70.5)
+ - React-Codegen (0.70.5):
+ - FBReactNativeSpec (= 0.70.5)
+ - RCT-Folly (= 2021.07.22.00)
+ - RCTRequired (= 0.70.5)
+ - RCTTypeSafety (= 0.70.5)
+ - React-Core (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - React-jsiexecutor (= 0.70.5)
+ - ReactCommon/turbomodule/core (= 0.70.5)
+ - React-Core (0.70.5):
+ - glog
+ - RCT-Folly (= 2021.07.22.00)
+ - React-Core/Default (= 0.70.5)
+ - React-cxxreact (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - React-jsiexecutor (= 0.70.5)
+ - React-perflogger (= 0.70.5)
+ - Yoga
+ - React-Core/CoreModulesHeaders (0.70.5):
+ - glog
+ - RCT-Folly (= 2021.07.22.00)
+ - React-Core/Default
+ - React-cxxreact (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - React-jsiexecutor (= 0.70.5)
+ - React-perflogger (= 0.70.5)
+ - Yoga
+ - React-Core/Default (0.70.5):
+ - glog
+ - RCT-Folly (= 2021.07.22.00)
+ - React-cxxreact (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - React-jsiexecutor (= 0.70.5)
+ - React-perflogger (= 0.70.5)
+ - Yoga
+ - React-Core/DevSupport (0.70.5):
+ - glog
+ - RCT-Folly (= 2021.07.22.00)
+ - React-Core/Default (= 0.70.5)
+ - React-Core/RCTWebSocket (= 0.70.5)
+ - React-cxxreact (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - React-jsiexecutor (= 0.70.5)
+ - React-jsinspector (= 0.70.5)
+ - React-perflogger (= 0.70.5)
+ - Yoga
+ - React-Core/RCTActionSheetHeaders (0.70.5):
+ - glog
+ - RCT-Folly (= 2021.07.22.00)
+ - React-Core/Default
+ - React-cxxreact (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - React-jsiexecutor (= 0.70.5)
+ - React-perflogger (= 0.70.5)
+ - Yoga
+ - React-Core/RCTAnimationHeaders (0.70.5):
+ - glog
+ - RCT-Folly (= 2021.07.22.00)
+ - React-Core/Default
+ - React-cxxreact (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - React-jsiexecutor (= 0.70.5)
+ - React-perflogger (= 0.70.5)
+ - Yoga
+ - React-Core/RCTBlobHeaders (0.70.5):
+ - glog
+ - RCT-Folly (= 2021.07.22.00)
+ - React-Core/Default
+ - React-cxxreact (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - React-jsiexecutor (= 0.70.5)
+ - React-perflogger (= 0.70.5)
+ - Yoga
+ - React-Core/RCTImageHeaders (0.70.5):
+ - glog
+ - RCT-Folly (= 2021.07.22.00)
+ - React-Core/Default
+ - React-cxxreact (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - React-jsiexecutor (= 0.70.5)
+ - React-perflogger (= 0.70.5)
+ - Yoga
+ - React-Core/RCTLinkingHeaders (0.70.5):
+ - glog
+ - RCT-Folly (= 2021.07.22.00)
+ - React-Core/Default
+ - React-cxxreact (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - React-jsiexecutor (= 0.70.5)
+ - React-perflogger (= 0.70.5)
+ - Yoga
+ - React-Core/RCTNetworkHeaders (0.70.5):
+ - glog
+ - RCT-Folly (= 2021.07.22.00)
+ - React-Core/Default
+ - React-cxxreact (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - React-jsiexecutor (= 0.70.5)
+ - React-perflogger (= 0.70.5)
+ - Yoga
+ - React-Core/RCTSettingsHeaders (0.70.5):
+ - glog
+ - RCT-Folly (= 2021.07.22.00)
+ - React-Core/Default
+ - React-cxxreact (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - React-jsiexecutor (= 0.70.5)
+ - React-perflogger (= 0.70.5)
+ - Yoga
+ - React-Core/RCTTextHeaders (0.70.5):
+ - glog
+ - RCT-Folly (= 2021.07.22.00)
+ - React-Core/Default
+ - React-cxxreact (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - React-jsiexecutor (= 0.70.5)
+ - React-perflogger (= 0.70.5)
+ - Yoga
+ - React-Core/RCTVibrationHeaders (0.70.5):
+ - glog
+ - RCT-Folly (= 2021.07.22.00)
+ - React-Core/Default
+ - React-cxxreact (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - React-jsiexecutor (= 0.70.5)
+ - React-perflogger (= 0.70.5)
+ - Yoga
+ - React-Core/RCTWebSocket (0.70.5):
+ - glog
+ - RCT-Folly (= 2021.07.22.00)
+ - React-Core/Default (= 0.70.5)
+ - React-cxxreact (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - React-jsiexecutor (= 0.70.5)
+ - React-perflogger (= 0.70.5)
+ - Yoga
+ - React-CoreModules (0.70.5):
+ - RCT-Folly (= 2021.07.22.00)
+ - RCTTypeSafety (= 0.70.5)
+ - React-Codegen (= 0.70.5)
+ - React-Core/CoreModulesHeaders (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - React-RCTImage (= 0.70.5)
+ - ReactCommon/turbomodule/core (= 0.70.5)
+ - React-cxxreact (0.70.5):
+ - boost (= 1.76.0)
+ - DoubleConversion
+ - glog
+ - RCT-Folly (= 2021.07.22.00)
+ - React-callinvoker (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - React-jsinspector (= 0.70.5)
+ - React-logger (= 0.70.5)
+ - React-perflogger (= 0.70.5)
+ - React-runtimeexecutor (= 0.70.5)
+ - React-jsi (0.70.5):
+ - boost (= 1.76.0)
+ - DoubleConversion
+ - glog
+ - RCT-Folly (= 2021.07.22.00)
+ - React-jsi/Default (= 0.70.5)
+ - React-jsi/Default (0.70.5):
+ - boost (= 1.76.0)
+ - DoubleConversion
+ - glog
+ - RCT-Folly (= 2021.07.22.00)
+ - React-jsiexecutor (0.70.5):
+ - DoubleConversion
+ - glog
+ - RCT-Folly (= 2021.07.22.00)
+ - React-cxxreact (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - React-perflogger (= 0.70.5)
+ - React-jsinspector (0.70.5)
+ - React-logger (0.70.5):
+ - glog
+ - react-native-get-random-values (1.8.0):
+ - React-Core
+ - react-native-netinfo (9.3.5):
+ - React-Core
+ - react-native-pager-view (6.0.1):
+ - React-Core
+ - react-native-safe-area-context (4.4.1):
+ - RCT-Folly
+ - RCTRequired
+ - RCTTypeSafety
+ - React-Core
+ - ReactCommon/turbomodule/core
+ - React-perflogger (0.70.5)
+ - React-RCTActionSheet (0.70.5):
+ - React-Core/RCTActionSheetHeaders (= 0.70.5)
+ - React-RCTAnimation (0.70.5):
+ - RCT-Folly (= 2021.07.22.00)
+ - RCTTypeSafety (= 0.70.5)
+ - React-Codegen (= 0.70.5)
+ - React-Core/RCTAnimationHeaders (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - ReactCommon/turbomodule/core (= 0.70.5)
+ - React-RCTBlob (0.70.5):
+ - RCT-Folly (= 2021.07.22.00)
+ - React-Codegen (= 0.70.5)
+ - React-Core/RCTBlobHeaders (= 0.70.5)
+ - React-Core/RCTWebSocket (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - React-RCTNetwork (= 0.70.5)
+ - ReactCommon/turbomodule/core (= 0.70.5)
+ - React-RCTImage (0.70.5):
+ - RCT-Folly (= 2021.07.22.00)
+ - RCTTypeSafety (= 0.70.5)
+ - React-Codegen (= 0.70.5)
+ - React-Core/RCTImageHeaders (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - React-RCTNetwork (= 0.70.5)
+ - ReactCommon/turbomodule/core (= 0.70.5)
+ - React-RCTLinking (0.70.5):
+ - React-Codegen (= 0.70.5)
+ - React-Core/RCTLinkingHeaders (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - ReactCommon/turbomodule/core (= 0.70.5)
+ - React-RCTNetwork (0.70.5):
+ - RCT-Folly (= 2021.07.22.00)
+ - RCTTypeSafety (= 0.70.5)
+ - React-Codegen (= 0.70.5)
+ - React-Core/RCTNetworkHeaders (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - ReactCommon/turbomodule/core (= 0.70.5)
+ - React-RCTSettings (0.70.5):
+ - RCT-Folly (= 2021.07.22.00)
+ - RCTTypeSafety (= 0.70.5)
+ - React-Codegen (= 0.70.5)
+ - React-Core/RCTSettingsHeaders (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - ReactCommon/turbomodule/core (= 0.70.5)
+ - React-RCTText (0.70.5):
+ - React-Core/RCTTextHeaders (= 0.70.5)
+ - React-RCTVibration (0.70.5):
+ - RCT-Folly (= 2021.07.22.00)
+ - React-Codegen (= 0.70.5)
+ - React-Core/RCTVibrationHeaders (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - ReactCommon/turbomodule/core (= 0.70.5)
+ - React-runtimeexecutor (0.70.5):
+ - React-jsi (= 0.70.5)
+ - ReactCommon/turbomodule/core (0.70.5):
+ - DoubleConversion
+ - glog
+ - RCT-Folly (= 2021.07.22.00)
+ - React-bridging (= 0.70.5)
+ - React-callinvoker (= 0.70.5)
+ - React-Core (= 0.70.5)
+ - React-cxxreact (= 0.70.5)
+ - React-jsi (= 0.70.5)
+ - React-logger (= 0.70.5)
+ - React-perflogger (= 0.70.5)
+ - RNAWSCognito (6.1.2):
+ - React-Core
+ - RNCAsyncStorage (1.17.11):
+ - React-Core
+ - RNCPicker (2.4.8):
+ - React-Core
+ - RNFastImage (8.6.3):
+ - React-Core
+ - SDWebImage (~> 5.11.1)
+ - SDWebImageWebPCoder (~> 0.8.4)
+ - RNFS (2.20.0):
+ - React-Core
+ - RNScreens (3.18.2):
+ - React-Core
+ - React-RCTImage
+ - SDWebImage (5.11.1):
+ - SDWebImage/Core (= 5.11.1)
+ - SDWebImage/Core (5.11.1)
+ - SDWebImageWebPCoder (0.8.5):
+ - libwebp (~> 1.0)
+ - SDWebImage/Core (~> 5.10)
+ - Yoga (1.14.0)
+
+DEPENDENCIES:
+ - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`)
+ - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
+ - EXApplication (from `../node_modules/expo-application/ios`)
+ - EXConstants (from `../node_modules/expo-constants/ios`)
+ - EXFileSystem (from `../node_modules/expo-file-system/ios`)
+ - EXFont (from `../node_modules/expo-font/ios`)
+ - EXImageLoader (from `../node_modules/expo-image-loader/ios`)
+ - EXJSONUtils (from `../node_modules/expo-json-utils/ios`)
+ - EXManifests (from `../node_modules/expo-manifests/ios`)
+ - Expo (from `../node_modules/expo`)
+ - expo-dev-client (from `../node_modules/expo-dev-client/ios`)
+ - expo-dev-launcher (from `../node_modules/expo-dev-launcher`)
+ - expo-dev-menu (from `../node_modules/expo-dev-menu`)
+ - expo-dev-menu-interface (from `../node_modules/expo-dev-menu-interface/ios`)
+ - ExpoImagePicker (from `../node_modules/expo-image-picker/ios`)
+ - ExpoKeepAwake (from `../node_modules/expo-keep-awake/ios`)
+ - ExpoModulesCore (from `../node_modules/expo-modules-core`)
+ - EXSplashScreen (from `../node_modules/expo-splash-screen/ios`)
+ - EXUpdatesInterface (from `../node_modules/expo-updates-interface/ios`)
+ - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`)
+ - FBReactNativeSpec (from `../node_modules/react-native/React/FBReactNativeSpec`)
+ - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
+ - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
+ - RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`)
+ - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`)
+ - React (from `../node_modules/react-native/`)
+ - React-bridging (from `../node_modules/react-native/ReactCommon`)
+ - React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`)
+ - React-Codegen (from `build/generated/ios`)
+ - React-Core (from `../node_modules/react-native/`)
+ - React-Core/RCTWebSocket (from `../node_modules/react-native/`)
+ - React-CoreModules (from `../node_modules/react-native/React/CoreModules`)
+ - React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`)
+ - React-jsi (from `../node_modules/react-native/ReactCommon/jsi`)
+ - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
+ - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
+ - React-logger (from `../node_modules/react-native/ReactCommon/logger`)
+ - react-native-get-random-values (from `../node_modules/react-native-get-random-values`)
+ - "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)"
+ - react-native-pager-view (from `../node_modules/react-native-pager-view`)
+ - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
+ - React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`)
+ - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`)
+ - React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`)
+ - React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`)
+ - React-RCTImage (from `../node_modules/react-native/Libraries/Image`)
+ - React-RCTLinking (from `../node_modules/react-native/Libraries/LinkingIOS`)
+ - React-RCTNetwork (from `../node_modules/react-native/Libraries/Network`)
+ - React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`)
+ - React-RCTText (from `../node_modules/react-native/Libraries/Text`)
+ - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
+ - React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`)
+ - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`)
+ - RNAWSCognito (from `../node_modules/amazon-cognito-identity-js`)
+ - "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
+ - "RNCPicker (from `../node_modules/@react-native-picker/picker`)"
+ - RNFastImage (from `../node_modules/react-native-fast-image`)
+ - RNFS (from `../node_modules/react-native-fs`)
+ - RNScreens (from `../node_modules/react-native-screens`)
+ - Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
+
+SPEC REPOS:
+ trunk:
+ - fmt
+ - libwebp
+ - SDWebImage
+ - SDWebImageWebPCoder
+
+EXTERNAL SOURCES:
+ boost:
+ :podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec"
+ DoubleConversion:
+ :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec"
+ EXApplication:
+ :path: "../node_modules/expo-application/ios"
+ EXConstants:
+ :path: "../node_modules/expo-constants/ios"
+ EXFileSystem:
+ :path: "../node_modules/expo-file-system/ios"
+ EXFont:
+ :path: "../node_modules/expo-font/ios"
+ EXImageLoader:
+ :path: "../node_modules/expo-image-loader/ios"
+ EXJSONUtils:
+ :path: "../node_modules/expo-json-utils/ios"
+ EXManifests:
+ :path: "../node_modules/expo-manifests/ios"
+ Expo:
+ :path: "../node_modules/expo"
+ expo-dev-client:
+ :path: "../node_modules/expo-dev-client/ios"
+ expo-dev-launcher:
+ :path: "../node_modules/expo-dev-launcher"
+ expo-dev-menu:
+ :path: "../node_modules/expo-dev-menu"
+ expo-dev-menu-interface:
+ :path: "../node_modules/expo-dev-menu-interface/ios"
+ ExpoImagePicker:
+ :path: "../node_modules/expo-image-picker/ios"
+ ExpoKeepAwake:
+ :path: "../node_modules/expo-keep-awake/ios"
+ ExpoModulesCore:
+ :path: "../node_modules/expo-modules-core"
+ EXSplashScreen:
+ :path: "../node_modules/expo-splash-screen/ios"
+ EXUpdatesInterface:
+ :path: "../node_modules/expo-updates-interface/ios"
+ FBLazyVector:
+ :path: "../node_modules/react-native/Libraries/FBLazyVector"
+ FBReactNativeSpec:
+ :path: "../node_modules/react-native/React/FBReactNativeSpec"
+ glog:
+ :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec"
+ RCT-Folly:
+ :podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec"
+ RCTRequired:
+ :path: "../node_modules/react-native/Libraries/RCTRequired"
+ RCTTypeSafety:
+ :path: "../node_modules/react-native/Libraries/TypeSafety"
+ React:
+ :path: "../node_modules/react-native/"
+ React-bridging:
+ :path: "../node_modules/react-native/ReactCommon"
+ React-callinvoker:
+ :path: "../node_modules/react-native/ReactCommon/callinvoker"
+ React-Codegen:
+ :path: build/generated/ios
+ React-Core:
+ :path: "../node_modules/react-native/"
+ React-CoreModules:
+ :path: "../node_modules/react-native/React/CoreModules"
+ React-cxxreact:
+ :path: "../node_modules/react-native/ReactCommon/cxxreact"
+ React-jsi:
+ :path: "../node_modules/react-native/ReactCommon/jsi"
+ React-jsiexecutor:
+ :path: "../node_modules/react-native/ReactCommon/jsiexecutor"
+ React-jsinspector:
+ :path: "../node_modules/react-native/ReactCommon/jsinspector"
+ React-logger:
+ :path: "../node_modules/react-native/ReactCommon/logger"
+ react-native-get-random-values:
+ :path: "../node_modules/react-native-get-random-values"
+ react-native-netinfo:
+ :path: "../node_modules/@react-native-community/netinfo"
+ react-native-pager-view:
+ :path: "../node_modules/react-native-pager-view"
+ react-native-safe-area-context:
+ :path: "../node_modules/react-native-safe-area-context"
+ React-perflogger:
+ :path: "../node_modules/react-native/ReactCommon/reactperflogger"
+ React-RCTActionSheet:
+ :path: "../node_modules/react-native/Libraries/ActionSheetIOS"
+ React-RCTAnimation:
+ :path: "../node_modules/react-native/Libraries/NativeAnimation"
+ React-RCTBlob:
+ :path: "../node_modules/react-native/Libraries/Blob"
+ React-RCTImage:
+ :path: "../node_modules/react-native/Libraries/Image"
+ React-RCTLinking:
+ :path: "../node_modules/react-native/Libraries/LinkingIOS"
+ React-RCTNetwork:
+ :path: "../node_modules/react-native/Libraries/Network"
+ React-RCTSettings:
+ :path: "../node_modules/react-native/Libraries/Settings"
+ React-RCTText:
+ :path: "../node_modules/react-native/Libraries/Text"
+ React-RCTVibration:
+ :path: "../node_modules/react-native/Libraries/Vibration"
+ React-runtimeexecutor:
+ :path: "../node_modules/react-native/ReactCommon/runtimeexecutor"
+ ReactCommon:
+ :path: "../node_modules/react-native/ReactCommon"
+ RNAWSCognito:
+ :path: "../node_modules/amazon-cognito-identity-js"
+ RNCAsyncStorage:
+ :path: "../node_modules/@react-native-async-storage/async-storage"
+ RNCPicker:
+ :path: "../node_modules/@react-native-picker/picker"
+ RNFastImage:
+ :path: "../node_modules/react-native-fast-image"
+ RNFS:
+ :path: "../node_modules/react-native-fs"
+ RNScreens:
+ :path: "../node_modules/react-native-screens"
+ Yoga:
+ :path: "../node_modules/react-native/ReactCommon/yoga"
+
+SPEC CHECKSUMS:
+ boost: a7c83b31436843459a1961bfd74b96033dc77234
+ DoubleConversion: 5189b271737e1565bdce30deb4a08d647e3f5f54
+ EXApplication: 034b1c40a8e9fe1bff76a1e511ee90dff64ad834
+ EXConstants: 3c86653c422dd77e40d10cbbabb3025003977415
+ EXFileSystem: 60602b6eefa6873f97172c684b7537c9760b50d6
+ EXFont: 319606bfe48c33b5b5063fb0994afdc496befe80
+ EXImageLoader: 84b65e6bd9d3345d6fbb3ab936a546c54496a64d
+ EXJSONUtils: 09aef2c1fba1a116ca8c73a2c8299aac00d96b43
+ EXManifests: 347f49430b63444579aa013f0ad057d16b8d1cc8
+ Expo: b9fa98bf260992312ee3c424400819fb9beadafe
+ expo-dev-client: d723d52ccfbe2eb47ee24d1ac0cf5b39001589c2
+ expo-dev-launcher: 953f564f7d006f1af50b119cacb48cafcad40c73
+ expo-dev-menu: fa9e67b193032700e2908b4737d9d199c0b43c30
+ expo-dev-menu-interface: 45581093393dacd51ce5e7f641cf9ed5064a2e3f
+ ExpoImagePicker: ce37302446e70145bb413f0f74886441abdae022
+ ExpoKeepAwake: 69b59d0a8d2b24de9f82759c39b3821fec030318
+ ExpoModulesCore: 485dff3a59b036a33b6050c0a5aea3cf1037fdd1
+ EXSplashScreen: 3e989924f61a8dd07ee4ea584c6ba14be9b51949
+ EXUpdatesInterface: bffd1ead18f0bab04fa784ca159c115607b8a23c
+ FBLazyVector: affa4ba1bfdaac110a789192f4d452b053a86624
+ FBReactNativeSpec: fe8b5f1429cfe83a8d72dc8ed61dc7704cac8745
+ fmt: ff9d55029c625d3757ed641535fd4a75fedc7ce9
+ glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b
+ libwebp: f62cb61d0a484ba548448a4bd52aabf150ff6eef
+ RCT-Folly: 0080d0a6ebf2577475bda044aa59e2ca1f909cda
+ RCTRequired: 21229f84411088e5d8538f21212de49e46cc83e2
+ RCTTypeSafety: 62eed57a32924b09edaaf170a548d1fc96223086
+ React: f0254ccddeeef1defe66c6b1bb9133a4f040792b
+ React-bridging: e46911666b7ec19538a620a221d6396cd293d687
+ React-callinvoker: 66b62e2c34546546b2f21ab0b7670346410a2b53
+ React-Codegen: b6999435966df3bdf82afa3f319ba0d6f9a8532a
+ React-Core: dabbc9d1fe0a11d884e6ee1599789cf8eb1058a5
+ React-CoreModules: 5b6b7668f156f73a56420df9ec68ca2ec8f2e818
+ React-cxxreact: c7ca2baee46db22a30fce9e639277add3c3f6ad1
+ React-jsi: a565dcb49130ed20877a9bb1105ffeecbb93d02d
+ React-jsiexecutor: 31564fa6912459921568e8b0e49024285a4d584b
+ React-jsinspector: badd81696361249893a80477983e697aab3c1a34
+ React-logger: fdda34dd285bdb0232e059b19d9606fa0ec3bb9c
+ react-native-get-random-values: a6ea6a8a65dc93e96e24a11105b1a9c8cfe1d72a
+ react-native-netinfo: 85b2a435c4d3705c08b0c42ff2d6ef6b9622ea0a
+ react-native-pager-view: 3051346698a0ba0c4e13e40097cc11b00ee03cca
+ react-native-safe-area-context: 99b24a0c5acd0d5dcac2b1a7f18c49ea317be99a
+ React-perflogger: e68d3795cf5d247a0379735cbac7309adf2fb931
+ React-RCTActionSheet: 05452c3b281edb27850253db13ecd4c5a65bc247
+ React-RCTAnimation: 578eebac706428e68466118e84aeacf3a282b4da
+ React-RCTBlob: f47a0aa61e7d1fb1a0e13da832b0da934939d71a
+ React-RCTImage: 60f54b66eed65d86b6dffaf4733d09161d44929d
+ React-RCTLinking: 91073205aeec4b29450ca79b709277319368ac9e
+ React-RCTNetwork: ca91f2c9465a7e335c8a5fae731fd7f10572213b
+ React-RCTSettings: 1a9a5d01337d55c18168c1abe0f4a589167d134a
+ React-RCTText: c591e8bd9347a294d8416357ca12d779afec01d5
+ React-RCTVibration: 8e5c8c5d17af641f306d7380d8d0fe9b3c142c48
+ React-runtimeexecutor: 7401c4a40f8728fd89df4a56104541b760876117
+ ReactCommon: c9246996e73bf75a2c6c3ff15f1e16707cdc2da9
+ RNAWSCognito: 06ca81fa480fd7f9ff539d01bc41f9d531ff0a19
+ RNCAsyncStorage: 8616bd5a58af409453ea4e1b246521bb76578d60
+ RNCPicker: 0bf8ef8f7800524f32d2bb2a8bcadd53eda0ecd1
+ RNFastImage: 5c9c9fed9c076e521b3f509fe79e790418a544e8
+ RNFS: 4ac0f0ea233904cb798630b3c077808c06931688
+ RNScreens: 34cc502acf1b916c582c60003dc3089fa01dc66d
+ SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d
+ SDWebImageWebPCoder: 908b83b6adda48effe7667cd2b7f78c897e5111d
+ Yoga: eca980a5771bf114c41a754098cd85e6e0d90ed7
+
+PODFILE CHECKSUM: 1abcb7441bca7078fb6ff33d9367ceb191efa7ed
+
+COCOAPODS: 1.11.3
diff --git a/ios/Podfile.properties.json b/ios/Podfile.properties.json
new file mode 100644
index 0000000..f6d872e
--- /dev/null
+++ b/ios/Podfile.properties.json
@@ -0,0 +1,3 @@
+{
+ "expo.jsEngine": "jsc"
+}
diff --git a/package-lock.json b/package-lock.json
index 67eccab..6e0071b 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -27,13 +27,15 @@
"expo": "~47.0.12",
"expo-dev-client": "~2.0.1",
"expo-image-picker": "~14.0.2",
- "expo-modules-autolinking": "^0.8.1",
+ "expo-modules-autolinking": "^1.0.0",
"expo-splash-screen": "~0.17.5",
"expo-status-bar": "~1.4.2",
+ "formik": "^2.2.9",
"graphql": "^15.8.0",
"react": "18.1.0",
"react-dom": "18.1.0",
"react-native": "0.70.5",
+ "react-native-fast-image": "^8.6.3",
"react-native-fs": "^2.20.0",
"react-native-get-random-values": "^1.8.0",
"react-native-keyboard-aware-scroll-view": "^0.9.5",
@@ -41,6 +43,7 @@
"react-native-safe-area-context": "4.4.1",
"react-native-screens": "~3.18.0",
"react-native-tab-view": "^3.3.4",
+ "react-native-toast-message": "^2.1.6",
"react-native-url-polyfill": "^1.3.0",
"react-navigation": "^4.4.4",
"toggle-switch-react-native": "^3.3.0"
@@ -18914,9 +18917,9 @@
}
},
"node_modules/expo-modules-autolinking": {
- "version": "0.8.1",
- "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-0.8.1.tgz",
- "integrity": "sha512-S8qfaXCv//7tQWV9M+JKx3CF7ypYhDdSUbkUQdaVO/r8D76/aRTArY/aRw1yEfaAOzyK8C8diDToV1itl51DfQ==",
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-1.1.2.tgz",
+ "integrity": "sha512-oOlkAccVnHwwR5ccvF/F/x4Omj9HWzSimMUlIVz0SVGdNBEqTPyn0L/d4uIufhyQbEWvrarqL8o5Yz11wEI0SQ==",
"dependencies": {
"chalk": "^4.1.0",
"commander": "^7.2.0",
@@ -19752,6 +19755,37 @@
"node": ">= 6"
}
},
+ "node_modules/formik": {
+ "version": "2.2.9",
+ "resolved": "https://registry.npmjs.org/formik/-/formik-2.2.9.tgz",
+ "integrity": "sha512-LQLcISMmf1r5at4/gyJigGn0gOwFbeEAlji+N9InZF6LIMXnFNkO42sCI8Jt84YZggpD4cPWObAZaxpEFtSzNA==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://opencollective.com/formik"
+ }
+ ],
+ "dependencies": {
+ "deepmerge": "^2.1.1",
+ "hoist-non-react-statics": "^3.3.0",
+ "lodash": "^4.17.21",
+ "lodash-es": "^4.17.21",
+ "react-fast-compare": "^2.0.1",
+ "tiny-warning": "^1.0.2",
+ "tslib": "^1.10.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/formik/node_modules/deepmerge": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz",
+ "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/fragment-cache": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
@@ -23492,6 +23526,11 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
+ "node_modules/lodash-es": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
+ "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
+ },
"node_modules/lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@@ -26304,6 +26343,11 @@
"react": "^18.1.0"
}
},
+ "node_modules/react-fast-compare": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz",
+ "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw=="
+ },
"node_modules/react-freeze": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/react-freeze/-/react-freeze-1.0.3.tgz",
@@ -26379,6 +26423,15 @@
"nullthrows": "^1.1.1"
}
},
+ "node_modules/react-native-fast-image": {
+ "version": "8.6.3",
+ "resolved": "https://registry.npmjs.org/react-native-fast-image/-/react-native-fast-image-8.6.3.tgz",
+ "integrity": "sha512-Sdw4ESidXCXOmQ9EcYguNY2swyoWmx53kym2zRsvi+VeFCHEdkO+WG1DK+6W81juot40bbfLNhkc63QnWtesNg==",
+ "peerDependencies": {
+ "react": "^17 || ^18",
+ "react-native": ">=0.60.0"
+ }
+ },
"node_modules/react-native-fs": {
"version": "2.20.0",
"resolved": "https://registry.npmjs.org/react-native-fs/-/react-native-fs-2.20.0.tgz",
@@ -26499,6 +26552,15 @@
"react-native-pager-view": "*"
}
},
+ "node_modules/react-native-toast-message": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/react-native-toast-message/-/react-native-toast-message-2.1.6.tgz",
+ "integrity": "sha512-VctXuq20vmRa9AE13acaNZhrLcS3FaBS2zEevS3+vhBsnVZYG0FIlWIis9tVnpnNxUb3ART+BWtwQjzSttXTng==",
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*"
+ }
+ },
"node_modules/react-native-url-polyfill": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/react-native-url-polyfill/-/react-native-url-polyfill-1.3.0.tgz",
@@ -28296,6 +28358,11 @@
"xtend": "~4.0.1"
}
},
+ "node_modules/tiny-warning": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
+ "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
+ },
"node_modules/tmp": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
@@ -44696,9 +44763,9 @@
}
},
"expo-modules-autolinking": {
- "version": "0.8.1",
- "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-0.8.1.tgz",
- "integrity": "sha512-S8qfaXCv//7tQWV9M+JKx3CF7ypYhDdSUbkUQdaVO/r8D76/aRTArY/aRw1yEfaAOzyK8C8diDToV1itl51DfQ==",
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/expo-modules-autolinking/-/expo-modules-autolinking-1.1.2.tgz",
+ "integrity": "sha512-oOlkAccVnHwwR5ccvF/F/x4Omj9HWzSimMUlIVz0SVGdNBEqTPyn0L/d4uIufhyQbEWvrarqL8o5Yz11wEI0SQ==",
"requires": {
"chalk": "^4.1.0",
"commander": "^7.2.0",
@@ -45193,6 +45260,27 @@
"mime-types": "^2.1.12"
}
},
+ "formik": {
+ "version": "2.2.9",
+ "resolved": "https://registry.npmjs.org/formik/-/formik-2.2.9.tgz",
+ "integrity": "sha512-LQLcISMmf1r5at4/gyJigGn0gOwFbeEAlji+N9InZF6LIMXnFNkO42sCI8Jt84YZggpD4cPWObAZaxpEFtSzNA==",
+ "requires": {
+ "deepmerge": "^2.1.1",
+ "hoist-non-react-statics": "^3.3.0",
+ "lodash": "^4.17.21",
+ "lodash-es": "^4.17.21",
+ "react-fast-compare": "^2.0.1",
+ "tiny-warning": "^1.0.2",
+ "tslib": "^1.10.0"
+ },
+ "dependencies": {
+ "deepmerge": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz",
+ "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA=="
+ }
+ }
+ },
"fragment-cache": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
@@ -47985,6 +48073,11 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
},
+ "lodash-es": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
+ "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
+ },
"lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@@ -50187,6 +50280,11 @@
"scheduler": "^0.22.0"
}
},
+ "react-fast-compare": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz",
+ "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw=="
+ },
"react-freeze": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/react-freeze/-/react-freeze-1.0.3.tgz",
@@ -50271,6 +50369,12 @@
"nullthrows": "^1.1.1"
}
},
+ "react-native-fast-image": {
+ "version": "8.6.3",
+ "resolved": "https://registry.npmjs.org/react-native-fast-image/-/react-native-fast-image-8.6.3.tgz",
+ "integrity": "sha512-Sdw4ESidXCXOmQ9EcYguNY2swyoWmx53kym2zRsvi+VeFCHEdkO+WG1DK+6W81juot40bbfLNhkc63QnWtesNg==",
+ "requires": {}
+ },
"react-native-fs": {
"version": "2.20.0",
"resolved": "https://registry.npmjs.org/react-native-fs/-/react-native-fs-2.20.0.tgz",
@@ -50359,6 +50463,12 @@
"use-latest-callback": "^0.1.5"
}
},
+ "react-native-toast-message": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/react-native-toast-message/-/react-native-toast-message-2.1.6.tgz",
+ "integrity": "sha512-VctXuq20vmRa9AE13acaNZhrLcS3FaBS2zEevS3+vhBsnVZYG0FIlWIis9tVnpnNxUb3ART+BWtwQjzSttXTng==",
+ "requires": {}
+ },
"react-native-url-polyfill": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/react-native-url-polyfill/-/react-native-url-polyfill-1.3.0.tgz",
@@ -51752,6 +51862,11 @@
"xtend": "~4.0.1"
}
},
+ "tiny-warning": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
+ "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA=="
+ },
"tmp": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
diff --git a/package.json b/package.json
index 23696d4..2b1071d 100644
--- a/package.json
+++ b/package.json
@@ -30,13 +30,15 @@
"expo": "~47.0.12",
"expo-dev-client": "~2.0.1",
"expo-image-picker": "~14.0.2",
- "expo-modules-autolinking": "^0.8.1",
+ "expo-modules-autolinking": "^1.0.0",
"expo-splash-screen": "~0.17.5",
"expo-status-bar": "~1.4.2",
+ "formik": "^2.2.9",
"graphql": "^15.8.0",
"react": "18.1.0",
"react-dom": "18.1.0",
"react-native": "0.70.5",
+ "react-native-fast-image": "^8.6.3",
"react-native-fs": "^2.20.0",
"react-native-get-random-values": "^1.8.0",
"react-native-keyboard-aware-scroll-view": "^0.9.5",
@@ -44,6 +46,7 @@
"react-native-safe-area-context": "4.4.1",
"react-native-screens": "~3.18.0",
"react-native-tab-view": "^3.3.4",
+ "react-native-toast-message": "^2.1.6",
"react-native-url-polyfill": "^1.3.0",
"react-navigation": "^4.4.4",
"toggle-switch-react-native": "^3.3.0"
diff --git a/src/components/CachedImage/CachedImage.js b/src/components/CachedImage/CachedImage.js
new file mode 100644
index 0000000..db28a06
--- /dev/null
+++ b/src/components/CachedImage/CachedImage.js
@@ -0,0 +1,54 @@
+import { useEffect, useState } from "react";
+import { getUriFromCache, cacheRemoteUri } from "../../crud/CacheOperations";
+import FastImage from "react-native-fast-image";
+
+export default function CachedImage({ username, picName, imageStyle, refresh, userPfp = false }) {
+ const [imageUri, setImageUri] = useState(null);
+ const [uriIsSet, setUriIsSet] = useState(false);
+
+ async function setImageFromCacheOrAWS() {
+ /*
+ if (isPfp) {
+ console.log("usr", username, "pic", picName);
+ }*/
+ let uriFromCache = await getUriFromCache(username, picName);
+ /*
+ if (isPfp) {
+ console.log(uriFromCache);
+ }*/
+ if (uriFromCache === "") {
+ uriFromCache = await cacheRemoteUri(username, picName);
+ }
+ setImageUri(uriFromCache);
+ setUriIsSet(true);
+ }
+
+ useEffect(() => {
+ /*
+ if (isPfp) {
+ console.log("IN CAHCED IMAGE");
+ }*/
+ setImageFromCacheOrAWS();
+ }, [refresh]);
+ let prioritee = FastImage.priority.normal;
+ if (userPfp) {
+ //console.log("Hi");
+ // if this is the user's pfp, load it ASAP because I don't want the pfp to be empty for half a second when you swipe to profile screen
+ // I don't really know if this makes it better at all but it was worth a shot
+ prioritee = FastImage.priority.high;
+ }
+
+ return (
+ uriIsSet && (
+
+ )
+ ); //;
+}
diff --git a/src/components/CachedImage/index.js b/src/components/CachedImage/index.js
new file mode 100644
index 0000000..2550abc
--- /dev/null
+++ b/src/components/CachedImage/index.js
@@ -0,0 +1 @@
+export { default } from "./CachedImage";
diff --git a/src/components/Comment/Comment.js b/src/components/Comment/Comment.js
index eb0e4d7..1a170fb 100644
--- a/src/components/Comment/Comment.js
+++ b/src/components/Comment/Comment.js
@@ -5,10 +5,7 @@ import ProfileMini from "../ProfileMini";
import { Storage } from "@aws-amplify/storage";
import CustomButton from "../CustomButton/CustomButton";
import CustomTextInput from "../CustomTextInput/CustomTextInput";
-import {
- checkForDeletability,
- createComment,
-} from "../../crud/CommentOperations";
+import { checkForDeletability, createComment } from "../../crud/CommentOperations";
import { getCurrentUser, getImageFromCache } from "../../crud/CacheOperations";
import NonCurrUserProfileModal from "../modals/NonCurrUserProfileModal.js/NonCurrUserProfileModal";
import { getCurrentAuthenticatedUser } from "../../library/GetAuthenticatedUser";
@@ -17,8 +14,7 @@ import ErrorModal from "../modals/ErrorModal/ErrorModal";
const OptionsButton = require("../../../assets/icons/Gymbit_Icons_Black/Three_Dots_Black.png");
-const Comment = ({ commentModel, postID, replies, style }) => {
- const [pfp, setPfp] = useState("");
+const Comment = ({ commentModel, postID, replies, style, refresh }) => {
const [replyOpen, setReplyOpen] = useState(false);
const [replyText, setReplyText] = useState("");
const [repliesOpen, setRepliesOpen] = useState(false);
@@ -69,9 +65,9 @@ const Comment = ({ commentModel, postID, replies, style }) => {
} else setErrorModalVisible(true);
}
- useEffect(() => {
+ /*useEffect(() => {
getPic();
- }, []);
+ }, []);*/
async function onReplySubmit() {
setReplyOpen(false);
@@ -94,7 +90,6 @@ const Comment = ({ commentModel, postID, replies, style }) => {
modalVisible={modalVisible}
setModalVisible={setModalVisible}
username={commentModel?.username}
- image={pfp}
>
{
errorMessage={errorMessage}
setExternalModal={setCommentModalVisible}
>
- setModalVisible(true)}
- style={styles.leftSide}
- >
+ setModalVisible(true)} style={styles.leftSide} />
setModalVisible(true)}>
{commentModel?.username}
- checkIfDeletable(postID, commentModel?.username)}
- >
+ checkIfDeletable(postID, commentModel?.username)}>
diff --git a/src/components/Exercise/Exercise.js b/src/components/Exercise/Exercise.js
new file mode 100644
index 0000000..d9f8ea5
--- /dev/null
+++ b/src/components/Exercise/Exercise.js
@@ -0,0 +1,42 @@
+import { View, Text, StyleSheet } from "react-native";
+import { blueThemeColor } from "../../library/constants";
+export default function Exercise(exercise, index) {
+ const name = exercise.exercise.exerciseName;
+ const notes = exercise.exercise.exerciseNotes;
+ return (
+
+
+ {name}
+
+
+ {notes}
+
+
+ );
+}
+const styles = StyleSheet.create({
+ exerciseNameContainer: {
+ height: 30,
+ },
+ exerciseName: {
+ color: blueThemeColor,
+ fontSize: 20,
+ fontWeight: "bold",
+ marginTop: 2,
+ marginLeft: 10,
+ //textAlign: "center",
+ //borderBottomWidth: 3,
+ },
+ exerciseContainer: {
+ //flex: 1,
+ //minHeight: 100,
+ flexDirection: "column",
+ //backgroundColor: "#202124",
+ //alignItems: "center",
+ //alignSelf: "center",
+ width: "80%",
+ },
+ exerciseNotes: {
+ marginLeft: 20,
+ },
+});
diff --git a/src/components/Exercise/index.js b/src/components/Exercise/index.js
new file mode 100644
index 0000000..f095277
--- /dev/null
+++ b/src/components/Exercise/index.js
@@ -0,0 +1 @@
+export { default } from "./Exercise";
diff --git a/src/components/FollowerMini/FollowerMini.js b/src/components/FollowerMini/FollowerMini.js
index 53c389f..8a3608a 100644
--- a/src/components/FollowerMini/FollowerMini.js
+++ b/src/components/FollowerMini/FollowerMini.js
@@ -38,12 +38,13 @@ const FollowerMini = ({ username, onProfileClick, onDelete, style }) => {
return (
+ modalVisible={modalVisible}
+ setModalVisible={setModalVisible}
+ username={username}
+ image={userImageSrc}
+ >
- setModalVisible(true)}>
+ setModalVisible(true)} />
setModalVisible(true)} style={styles.usernameContainer}>
@{username}
diff --git a/src/components/HomeHeader/HomeHeader.js b/src/components/HomeHeader/HomeHeader.js
index 625a156..235b46e 100644
--- a/src/components/HomeHeader/HomeHeader.js
+++ b/src/components/HomeHeader/HomeHeader.js
@@ -6,9 +6,11 @@ import {
Touchable,
Text,
TextInput,
+ ScrollView,
Pressable,
+ ActivityIndicator,
} from "react-native";
-import React from "react";
+import React, { useRef } from "react";
import { useNavigation } from "@react-navigation/native";
import { useState, useEffect } from "react";
import { Storage } from "@aws-amplify/storage";
@@ -19,21 +21,34 @@ import getPictureFileName from "../../library/getPictureFileName";
import { createPost } from "../../crud/PostOperations";
import ImageSelector from "../../components/ImageSelector";
import { DataStore } from "@aws-amplify/datastore";
-import { getNotifications } from "../../crud/NotificationOperations";
import { getCurrentUser } from "../../crud/CacheOperations";
-import { blueThemeColor } from "../../library/constants";
+import { getWorkouts } from "../../crud/WorkoutOperations";
+import { blueThemeColor, grayThemeColor } from "../../library/constants";
+import { useNetInfo } from "@react-native-community/netinfo";
+import { Toast } from "react-native-toast-message/lib/src/Toast";
+import CustomButton from "../CustomButton/CustomButton";
+import CreateWorkoutModal from "../modals/CreateWorkoutModal";
+import { getNotifications } from "../../crud/NotificationOperations";
+import WorkoutSelection from "../WorkoutSelection";
+import FastImage from "react-native-fast-image";
/**
* Creates the header that will go above the two home screens (Mutual and Explore)
*/
-const HomeHeader = ({ handlePress }) => {
+const HomeHeader = ({ handlePress, refresh, setRefresh }) => {
const navigation = useNavigation();
- const [refresh, setRefresh] = useState(true);
+ //const [refresh, setRefresh] = useState(true);
const [blowup, setBlowup] = useState(false);
const [text, setText] = useState(""); // the caption you write
- const [workoutSelection, setWorkoutSelection] = useState([]); // array of workouts you selected
+ const [workoutSelection, setWorkoutSelection] = useState(null); // array of workouts you selected
const [image, setImage] = useState(null);
const [notificationCount, setNotificationCount] = useState(0);
+ const networkConnection = useNetInfo();
+ const [createPostTouched, setCreatePostTouched] = useState(false);
+ const [showCreateWorkout, setShowCreateWorkout] = useState(false);
+ const [refreshWorkout, setRefreshWorkout] = useState(false);
+ const [scrollToBottom, setScrollToBottom] = useState(false);
+ const [showUploading, setShowUploading] = useState(false);
Storage.configure();
const imageSRC = require("../../../assets/icons/Gymbit_Icons_Black/Back_Icon_Black.png");
@@ -51,32 +66,90 @@ const HomeHeader = ({ handlePress }) => {
setNotificationCount(notifications.length);
}
+ const handleCreatePostBlowUp = () => {
+ if (networkConnection.isConnected) {
+ setBlowup(!blowup);
+ } else {
+ setCreatePostTouched(!createPostTouched);
+ }
+ };
+
useEffect(() => {
findNotificationCount();
- }),
- [navigation];
+ }, [navigation]);
+ const showPostUploadedToast = () => {
+ Toast.show({
+ type: "success",
+ text1: "Successfully uploaded your new post!",
+ //text2: "Go check it out on your mutuals page 🔥",
+ position: "bottom",
+ visibilityTime: 6000,
+ bottomOffset: 80,
+ });
+ };
+ const showPostNotUploadedToast = (usr) => {
+ if (usr === "") {
+ usr = "friend";
+ }
+ Toast.show({
+ type: "error",
+ text1: "Uh oh, there was trouble uploading your post...",
+ text2: "Try again later. Sorry, " + usr + " 😔",
+ position: "bottom",
+ visibilityTime: 6000,
+ bottomOffset: 80,
+ });
+ };
+ const showNetworkNotConnectedToast = () => {
+ Toast.show({
+ type: "error",
+ text1: "No network connection detected.",
+ text2: "Can't create a post.",
+ position: "bottom",
+ visibilityTime: 4000,
+ bottomOffset: 80,
+ });
+ };
async function savePost() {
- await DataStore.start();
+ setShowUploading(true);
+ //await DataStore.start();
+ let username = await getCurrentUser();
try {
// try catch just in case sending the image doesn't work
- const { attributes } = await Auth.currentAuthenticatedUser();
- let username = attributes.preferred_username;
+ //const { attributes } = await getCurrentUser();
var fileName = username + "/" + getPictureFileName();
+ await createPost(text, fileName, username, workoutSelection);
+ handleBlowUp();
+ Toast.show({
+ type: "info",
+ text1: "Your new post is loading!",
+ text2: "It'll show up soon 😄",
+ position: "bottom",
+ visibilityTime: 3000,
+ bottomOffset: 80,
+ });
const response = await fetch(image);
const blob = await response.blob();
- await createPost(text, fileName, username);
- Storage.put(fileName, blob);
- setImage(null);
+ await Storage.put(fileName, blob);
+ setShowUploading(false);
setText("");
- setWorkoutSelection([]);
- } catch {
- console.error("Error uploading file");
- // TODO make a UI popup thing that lets the user know that their post wasn't uploaded (please try again later)
+ setWorkoutSelection(null);
+ setImage(null);
+ showPostUploadedToast();
+ } catch (error) {
+ showPostNotUploadedToast(username);
+ console.error("Error uploading file", error);
}
- handleBlowUp();
+ setRefresh(!refresh);
}
+ useEffect(() => {
+ if (networkConnection.isConnected === false) {
+ showNetworkNotConnectedToast();
+ }
+ }, [createPostTouched]);
+
return (
<>
@@ -87,29 +160,32 @@ const HomeHeader = ({ handlePress }) => {
}}
>
{notificationCount}
-
+
-
+
-
-
+
+
- {blowup ? (
+ {blowup && (
+
+ {showCreateWorkout && (
+
+ )}
@@ -120,84 +196,38 @@ const HomeHeader = ({ handlePress }) => {
-
- {workoutSelection.join(", ")}
-
- Post Gymbit
-
+
+ {showUploading ? (
+
+ ) : (
+
+ Post Gymbit
+
+ )}
- ) : (
-
)}
>
);
};
-function WorkoutSelection(props) {
- const workoutSelection = props.workoutSelection;
- const setWorkoutSelection = props.setWorkoutSelection;
- const updateFunction = (text) => {
- setWorkoutSelection([...new Set([...workoutSelection, text])]);
- };
- return (
-
-
-
- What did you do today?
-
-
-
- updateFunction("Run")}
- style={styles.workoutSelection}
- >
- Run
-
- updateFunction("Leg Day")}
- style={styles.workoutSelection}
- >
- Leg Day
-
- updateFunction("Back and Biceps")}
- style={styles.workoutSelection}
- >
- Back and Biceps
-
- updateFunction("Chest and Triceps")}
- style={styles.workoutSelection}
- >
- Chest and Triceps
-
- updateFunction("Bike")}
- style={styles.workoutSelection}
- >
- Bike
-
- {workoutSelection.join(", ")}
-
-
- );
-}
-
const styles = StyleSheet.create({
+ header: {
+ //height: "10%",
+ },
container: {
width: "100%",
- height: 90,
+ height: 100,
+ //alignItems: "center",
paddingTop: 38,
backgroundColor: "white",
flexDirection: "row",
@@ -277,35 +307,17 @@ const styles = StyleSheet.create({
fontSize: 18,
},
- workoutSelectionContainer: {
- borderWidth: 3,
- borderLeftWidth: 0,
- alignItems: "center",
- flex: 1,
- },
-
- what: {
- backgroundColor: "#2E8CFF",
- height: 40,
- alignItems: "center",
- justifyContent: "center",
- width: "100%",
- },
-
- workoutSelection: {
- flex: 1,
- width: "100%",
- },
backArrow: {
width: 60,
height: 60,
paddingBottom: 50,
alignSelf: "flex-start",
paddingLeft: 10,
- backgroundColor: "rgba(200,212,225,0.75)",
+ //backgroundColor: "rgba(200,212,225,0.75)",
},
counter: {
borderRadius: 100,
+ color: "#FFFFFF",
backgroundColor: blueThemeColor,
width: 20,
textAlign: "center",
diff --git a/src/components/ImageSelector/ImageSelector.js b/src/components/ImageSelector/ImageSelector.js
index f1c3654..c1ca257 100644
--- a/src/components/ImageSelector/ImageSelector.js
+++ b/src/components/ImageSelector/ImageSelector.js
@@ -1,4 +1,4 @@
-import { View, Image, TouchableOpacity, Text, StyleSheet } from "react-native";
+import { View, Image, TouchableOpacity, Text, StyleSheet, Pressable } from "react-native";
import { AntDesign } from "@expo/vector-icons";
import * as ImagePicker from "expo-image-picker";
@@ -26,6 +26,16 @@ const styles = StyleSheet.create({
alignItems: "center",
justifyContent: "center",
},
+ transparentView: {
+ flex: 1,
+ position: "absolute",
+ left: 0,
+ top: 0,
+ width: "100%",
+ height: "100%",
+ backgroundColor: "rgba(52, 52, 52, 0.8)",
+ zIndex: -1,
+ },
});
/**
*
@@ -35,10 +45,12 @@ const styles = StyleSheet.create({
export default function ImageSelector(props) {
const image = props.image;
const setImage = props.setImage;
+ function chooseCameraOrUpload() {
+ ;
+ }
const addImage = async () => {
let _image = await ImagePicker.launchImageLibraryAsync({
- mediaTypes:
- ImagePicker.MediaTypeOptions.Images /*Only allow image upload */,
+ mediaTypes: ImagePicker.MediaTypeOptions.Images /*Only allow image upload */,
allowsEditing: true /*true= pull up an editing interface after image upload */,
aspect: [1, 1] /*1:1 image ratio, so it will be a square */,
quality: 1 /*highest quality image possible, on a scale of 0-1 we want 1 lol */,
@@ -47,9 +59,7 @@ export default function ImageSelector(props) {
};
return (
- {image && (
-
- )}
+ {image && }
{image ? "Edit" : "Upload"} Image
diff --git a/src/components/Post/Post.js b/src/components/Post/Post.js
index a264cf7..9207ebd 100644
--- a/src/components/Post/Post.js
+++ b/src/components/Post/Post.js
@@ -1,37 +1,30 @@
-import {
- View,
- Image,
- Text,
- StyleSheet,
- Pressable,
- TouchableOpacity,
-} from "react-native";
+import { View, Image, Text, StyleSheet, Pressable, TouchableOpacity, ActivityIndicator } from "react-native";
import { useState, useEffect } from "react";
import { Storage } from "@aws-amplify/storage";
import Reactions from "../Reactions";
import { blueThemeColor, grayThemeColor } from "../../library/constants";
import ProfileMini from "../ProfileMini";
import { useNavigation } from "@react-navigation/native";
-import {
- cacheImageFromAWS,
- getCurrentUser,
- getImageFromCache,
-} from "../../crud/CacheOperations";
+import { getCurrentUser } from "../../crud/CacheOperations";
import { useNetInfo } from "@react-native-community/netinfo";
import NonCurrUserProfileModal from "../modals/NonCurrUserProfileModal.js/NonCurrUserProfileModal";
import Comment from "../Comment";
import { createComment, getComments } from "../../crud/CommentOperations";
import CustomButton from "../CustomButton/CustomButton";
import CustomTextInput from "../CustomTextInput/CustomTextInput";
-import { getCurrentAuthenticatedUser } from "../../library/GetAuthenticatedUser";
+import CachedImage from "../CachedImage/CachedImage";
+import Workout from "../Workout/Workout";
+import { getWorkoutById } from "../../crud/WorkoutOperations";
import { getAndObserveComments } from "../../crud/observeQueries/CommentObserveQueries";
-
+import { getUriFromCache, cacheRemoteUri } from "../../crud/CacheOperations";
+import FastImage from "react-native-fast-image";
export default function Post(props) {
const entry = props.entry;
const username = entry.username;
const refresh = props.refresh;
const photoStr = entry.photo;
+ const workoutId = entry.postWorkoutId;
const picName = photoStr.substring(photoStr.indexOf("/") + 1);
const [picture, setPicture] = useState(null);
const [pfp, setPfp] = useState("");
@@ -45,59 +38,19 @@ export default function Post(props) {
const [shortCommentDisplay, setShortCommentDisplay] = useState(true);
const [showCommentOption, setCommentOption] = useState(false);
const [commentText, setCommentText] = useState("");
+ const [hasWorkout, setHasWorkout] = useState(false);
+ const [workout, setWorkout] = useState(null);
+ const [uriIsSet, setUriIsSet] = useState(false);
+ const [imageUri, setImageUri] = useState(null);
const handleBlowUp = () => {
setBlowup(!blowup);
};
let commentList = comments.map((val) => {
- return (
-
- );
+ return ;
});
- async function getPictures() {
- // TODO retrieve post picture from the passed entry fileName
- //const postPfp = await getImageFromCache(username, "pfp.png"); // console logs pic "pfp.png found for user x..."
- const postPfp = entry.cachedPfp;
-
- if (postPfp !== "") {
- setPfp(postPfp);
- }
- //const pic = entry.cachedPostPicture;
- const pic = await getImageFromCache(username, picName);
- if (pic !== "") {
- setPicture(pic);
- } else if (entry.shouldBeCached === true) {
- console.log("Pic not in cache but it should be", entry.caption);
- let picCached = await cacheImageFromAWS(username, picName);
- //let picha = await Storage.get(photoStr);
- setPicture(picCached);
- } else {
- console.log(
- "Pic",
- picName,
- "for",
- username,
- "must be acquired using Storage.get"
- );
- try {
- let picFromAWS = await Storage.get(photoStr);
- setPicture(picFromAWS);
- } catch (e) {
- console.log(
- "Storage.get failed; connection unavailable to render",
- picName
- );
- }
- }
- }
-
async function onCommentSubmit() {
setCommentOption(false);
// Call CRUD to make new datastore object
@@ -121,7 +74,7 @@ export default function Post(props) {
async function handleUserClick(username) {
try {
- if (username === await getCurrentAuthenticatedUser()) {
+ if (username === (await getCurrentUser())) {
navigation.navigate("Profile");
} else {
setModalVisible(true);
@@ -132,7 +85,7 @@ export default function Post(props) {
}
useEffect(() => {
- getPictures();
+ setImageFromCacheOrAWS();
const subscription = retrieveComments();
return () => {
if (subscription && subscription.unsubscribe) subscription.unsubscribe();
@@ -155,17 +108,38 @@ export default function Post(props) {
setReplies(replyMap);
}, [allComments]);
+ useEffect(() => {
+ getWorkoutForPost();
+ }, []);
+
+ async function setImageFromCacheOrAWS() {
+ let uriFromCache = await getUriFromCache(username, picName);
+ if (uriFromCache === "") {
+ uriFromCache = await cacheRemoteUri(username, picName);
+ }
+ setImageUri(uriFromCache);
+ setUriIsSet(true);
+ }
+
+ async function getWorkoutForPost() {
+ if (workoutId !== undefined && workoutId !== null) {
+ let workout = await getWorkoutById(workoutId);
+ setWorkout(workout);
+ setHasWorkout(true);
+ }
+ }
return (
setModalVisible(true)}
@@ -176,34 +150,29 @@ export default function Post(props) {
{getTimeElapsed(entry.createdAt)}
-
-
- {blowup && (
-
-
- Today's Workout
-
-
- - {entry.caption}
-
+
+ {uriIsSet ? (
+
+ ) : (
+
+
)}
+ {blowup && hasWorkout && }
{/*replace get time elapsed w/ actual on click utility*/}
{/* Need to implement caption box as intended*/}
{entry.caption}
-
+
{showCommentOption && (
)}
- {showCommentOption && (
-
- )}
+ {showCommentOption && }
{shortCommentDisplay ? commentList.slice(0, 2) : commentList}
{comments.length > 2 && (
{
+ Toast.show({
+ type: "success",
+ text1: "Welcome to GymBit!",
+ text2: "We're glad you're here 😁💪",
+ position: "bottom",
+ visibilityTime: 4000,
+ bottomOffset: 80,
+ });
+ };
+
+ const showOnlineToast = (usr) => {
+ Toast.show({
+ type: "success",
+ text1: "You are now online!",
+ text2: "Welcome back, " + usr + " 😁💪",
+ position: "bottom",
+ visibilityTime: 4000,
+ bottomOffset: 80,
+ });
+ };
+ const showWelcomeBackToast = (usr) => {
+ Toast.show({
+ type: "success",
+ text1: "Welcome back, " + usr + " 💪",
+ //text2: "We're glad you're here 😁💪",
+ position: "bottom",
+ visibilityTime: 4000,
+ bottomOffset: 80,
+ });
+ };
+
+ const delay = (ms) => new Promise((res) => setTimeout(res, ms));
+
+ const showNotConnectedToast = async () => {
+ setOfflineInitialCompleted(true);
+ Toast.show({
+ type: "info",
+ text1: "You're not connected to the internet 😬",
+ position: "bottom",
+ visibilityTime: 3000,
+ bottomOffset: 80,
+ });
+ await delay(4000);
+ Toast.show({
+ type: "info",
+ text1: "You can still look around 👀",
+ text2: "And also create goals 💪",
+ position: "bottom",
+ visibilityTime: 3000,
+ bottomOffset: 80,
+ });
+ };
+
+ async function offlineOperations() {
+ await fetchPostCache();
+ }
useEffect(() => {
+ setSwipeRefresh(true);
// First thing done upon startup of the app
if (postsInitialCompleted === false) {
- fetchPostCache(); // will set postsInitialCompleted to true after completion
+ offlineOperations(); // will set postsInitialCompleted to true after completion
}
- if (
- networkConnection.isConnected === true &&
- postsInitialCompleted === true
- ) {
+ if (networkConnection.isConnected) {
//list.current.scrollToIndex({ index: 0 });
- cacheStuffFromAWS();
- } else {
- // in case there is no conneciton, a swipe refresh should end with nothing happening
+ doOnlineOperations();
+ } else if (postsInitialCompleted) {
+ // in case there is no connection, a swipe refresh should end with nothing happening
// need to test when using app with no connection
setSwipeRefresh(false);
+ if (offlineInitialCompleted === false) {
+ showNotConnectedToast();
+ }
}
- console.log("PostList refreshed");
+ //console.log("PostList refreshed");
}, [refresh, networkConnection]);
return (
- }
- refreshing={swipeRefresh}
- onRefresh={() => {
- setSwipeRefresh(true);
- setRefresh(!refresh);
- }}
- keyExtractor={(item) => item.id}
- />
+ <>
+ }
+ extraData={refresh}
+ refreshing={swipeRefresh}
+ onRefresh={() => {
+ setRefresh(!refresh);
+ }}
+ keyExtractor={(item) => item.id}
+ />
+ >
);
}
diff --git a/src/components/ProfileMini/ProfileMini.js b/src/components/ProfileMini/ProfileMini.js
index 9df02d9..8b87f2a 100644
--- a/src/components/ProfileMini/ProfileMini.js
+++ b/src/components/ProfileMini/ProfileMini.js
@@ -1,26 +1,42 @@
import { Image, StyleSheet, Pressable } from "react-native";
+import { useEffect, useState } from "react";
+import CachedImage from "../CachedImage/CachedImage";
+import { getUriFromCache, cacheRemoteUri } from "../../crud/CacheOperations";
+import FastImage from "react-native-fast-image";
const defaultProfile = require("../../../assets/icons/Gymbit_Icons_Black/Profile_Icon.png");
-const ProfileMini = ({ style, src, onClick, imageStyle }) => {
+const ProfileMini = ({ style, onClick, imageStyle, username }) => {
let containerStyles = { ...styles.container, ...style };
let imageStyles = { ...styles.image, ...imageStyle };
+ let picName = "pfp.png";
+ const [imageUri, setImageUri] = useState(null);
+ const [uriIsSet, setUriIsSet] = useState(false);
+ async function setImageFromCacheOrAWS() {
+ let uriFromCache = await getUriFromCache(username, picName);
+ if (uriFromCache === "") {
+ uriFromCache = await cacheRemoteUri(username, picName);
+ }
+ setImageUri(uriFromCache);
+ setUriIsSet(true);
+ }
+ useEffect(() => {
+ setImageFromCacheOrAWS();
+ });
return (
-
- {src && (
-
+ {uriIsSet && (
+
+ style={imageStyles}
+ resizeMode={FastImage.resizeMode.cover}
+ />
)}
);
diff --git a/src/components/SuggestedFollower/SuggestedFollower.js b/src/components/SuggestedFollower/SuggestedFollower.js
index ce924ba..23ad394 100644
--- a/src/components/SuggestedFollower/SuggestedFollower.js
+++ b/src/components/SuggestedFollower/SuggestedFollower.js
@@ -1,11 +1,4 @@
-import {
- View,
- Modal,
- StyleSheet,
- Pressable,
- Text,
- ScrollView,
-} from "react-native";
+import { View, Modal, StyleSheet, Pressable, Text, ScrollView } from "react-native";
import React, { useState, useEffect } from "react";
import CustomButton from "../CustomButton";
@@ -14,34 +7,13 @@ import { blueThemeColor } from "../../library/constants";
import { getImageFromCache } from "../../crud/CacheOperations";
const SuggestedFollower = ({ username, addNewFollower }) => {
- const [pfp, setPfp] = useState("");
-
- useEffect(() => {
- async function getPic() {
- try {
- let pfps3 = await getImageFromCache(username, "pfp.png");
- if (pfps3 === "") {
- pfps3 = await Storage.get(username + "/pfp.png");
- }
- setPfp(pfps3);
- } catch (error) {
- console.log("Error retrieving pfp in comment: " + error);
- }
- }
- getPic();
- }, []);
-
return (
-
+
{username}
-
+
);
};
diff --git a/src/components/Workout/Workout.js b/src/components/Workout/Workout.js
new file mode 100644
index 0000000..18ba2c4
--- /dev/null
+++ b/src/components/Workout/Workout.js
@@ -0,0 +1,94 @@
+import { View, ScrollView, Text, StyleSheet } from "react-native";
+import { blueThemeColor } from "../../library/constants";
+import Exercise from "../Exercise/Exercise";
+export default function Workout({ workout, isAbsolute = false }) {
+ if (Array.isArray(workout) && workout.length > 0) {
+ workout = workout[0];
+ }
+ let JsonWorkout = workout;
+ try {
+ JsonWorkout = JSON.parse(JsonWorkout);
+ } catch {
+ JsonWorkout = workout;
+ }
+ let JsonExercises = JsonWorkout.exercises;
+ try {
+ JsonExercises = JSON.parse(JsonExercises);
+ } catch {
+ JsonExercises = JsonWorkout.exercises;
+ }
+ let workoutName = JsonWorkout.workoutName;
+ return (
+
+
+ {workoutName}
+
+
+ {JsonExercises.map((exercise, index) => (
+
+ ))}
+
+
+ );
+}
+const styles = StyleSheet.create({
+ blowupmain: {
+ width: "100%",
+ height: 400,
+ //position: this.
+ //height: 400,
+ //marginTop: 20,
+ //position: "absolute",
+ //right: 0,
+ backgroundColor: "rgba(200,212,225,0.7)",
+ borderRightWidth: 0,
+ borderLeftWidth: 0,
+ borderWidth: 2,
+ borderTopWidth: 3,
+ borderRightColor: "black",
+ marginBottom: 20,
+ },
+ blowupmainAbsolute: {
+ width: "100%",
+ height: 400,
+ position: "absolute",
+ //height: 400,
+ //marginTop: 20,
+ //position: "absolute",
+ //right: 0,
+ backgroundColor: "rgba(200,212,225,0.7)",
+ borderRightWidth: 0,
+ borderLeftWidth: 0,
+ borderWidth: 2,
+ borderTopWidth: 3,
+ borderRightColor: "black",
+ marginBottom: 20,
+ },
+ blowupheader: {
+ height: 50,
+ marginBottom: 10,
+ borderColor: "black",
+ color: blueThemeColor,
+ fontSize: 50,
+ fontWeight: "bold",
+ marginTop: 2,
+ textAlign: "center",
+ alignItems: "center",
+ borderBottomWidth: 3,
+ },
+ blowupbody: {
+ fontSize: 21,
+ textAlign: "left",
+ paddingLeft: 20,
+ marginTop: 5,
+ },
+ workoutName: {
+ color: blueThemeColor,
+ fontSize: 30,
+ fontWeight: "bold",
+ marginTop: 2,
+ marginLeft: 10,
+ //textAlign: "center",
+ //borderBottomWidth: 3,
+ },
+});
diff --git a/src/components/Workout/index.js b/src/components/Workout/index.js
new file mode 100644
index 0000000..8187410
--- /dev/null
+++ b/src/components/Workout/index.js
@@ -0,0 +1 @@
+export { default } from "./Workout";
diff --git a/src/components/WorkoutSelection/WorkoutSelection.js b/src/components/WorkoutSelection/WorkoutSelection.js
new file mode 100644
index 0000000..3ff6931
--- /dev/null
+++ b/src/components/WorkoutSelection/WorkoutSelection.js
@@ -0,0 +1,111 @@
+import { View, TouchableOpacity, StyleSheet, Text, ScrollView } from "react-native";
+import React, { useRef } from "react";
+import { useState, useEffect } from "react";
+import { getCurrentUser } from "../../crud/CacheOperations";
+import { getWorkouts } from "../../crud/WorkoutOperations";
+import { blueThemeColor } from "../../library/constants";
+
+export default function WorkoutSelection({
+ workoutSelection,
+ setWorkoutSelection,
+ refreshWorkout,
+ setShowCreateWorkout,
+ scrollToBottom,
+ setScrollToBottom,
+}) {
+ const scrollviewRef = useRef();
+ useEffect(() => {
+ getWorkoutList();
+
+ doStuff();
+ }, [refreshWorkout]);
+ const [workouts, setWorkouts] = useState([]);
+ async function getWorkoutList() {
+ let username = await getCurrentUser();
+ let workouts = await getWorkouts(username);
+ setWorkouts(workouts);
+ }
+ async function doStuff() {
+ if (scrollToBottom === true) {
+ //ScrollView.scrollToEnd
+ //setWorkoutSelection(workouts[workouts.length - 1]);
+ setWorkoutSelection(workouts[workouts.length - 1]);
+ scrollviewRef.current.scrollToEnd();
+ setScrollToBottom(false);
+ }
+ }
+ function handleWorkoutSelectionPress(workout) {
+ setWorkoutSelection(workout);
+ }
+ function handleSelectedWorkoutPress() {
+ setWorkoutSelection(null);
+ }
+ return (
+
+
+ What workout did you do today?
+
+
+ setShowCreateWorkout(true)} style={styles.workoutSelection}>
+ Create new workout
+
+ {workouts.map((workout, index) => {
+ return (
+
+ {workout === workoutSelection ? (
+ //console.log("THEY EQUAL EACH OTHER", workout);
+ // This will console.log successfully after creating a new workout, but won't return this. Will figure out later.
+ handleSelectedWorkoutPress(workout)} style={styles.workoutSelectionHighlighted}>
+ {workout.workoutName}
+
+ ) : (
+ handleWorkoutSelectionPress(workout)} style={styles.workoutSelection}>
+ {workout.workoutName}
+
+ )}
+
+ );
+ })}
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ workoutSelectionContainer: {
+ borderWidth: 3,
+ borderLeftWidth: 0,
+ alignItems: "center",
+ flex: 1,
+ },
+ workoutMainContainer: {
+ alignItems: "center",
+
+ width: "100%",
+ },
+
+ what: {
+ backgroundColor: "#2E8CFF",
+ height: 40,
+ alignItems: "center",
+ justifyContent: "center",
+ width: "100%",
+ },
+
+ workoutSelection: {
+ height: 50,
+ width: "100%",
+ alignItems: "center",
+ justifyContent: "center",
+ borderBottomWidth: 3,
+ },
+ workoutSelectionHighlighted: {
+ backgroundColor: blueThemeColor,
+ //overlayColor: blueThemeColor,
+ height: 50,
+ width: "100%",
+ alignItems: "center",
+ justifyContent: "center",
+ borderBottomWidth: 3,
+ },
+});
diff --git a/src/components/WorkoutSelection/index.js b/src/components/WorkoutSelection/index.js
new file mode 100644
index 0000000..b09f269
--- /dev/null
+++ b/src/components/WorkoutSelection/index.js
@@ -0,0 +1 @@
+export { default } from "./WorkoutSelection";
diff --git a/src/components/modals/AddFollowerModal/AddFollowerModal.js b/src/components/modals/AddFollowerModal/AddFollowerModal.js
index 317de26..3559a37 100644
--- a/src/components/modals/AddFollowerModal/AddFollowerModal.js
+++ b/src/components/modals/AddFollowerModal/AddFollowerModal.js
@@ -1,11 +1,4 @@
-import {
- View,
- Modal,
- StyleSheet,
- Pressable,
- Text,
- ScrollView,
-} from "react-native";
+import { View, Modal, StyleSheet, Pressable, Text, ScrollView } from "react-native";
import React, { useState, useEffect } from "react";
import { createFollower } from "../../../crud/FollowersOperations";
@@ -23,11 +16,7 @@ const AddFollowerModal = ({ modalVisible, setModalVisible }) => {
const [suggestedUsers, setSuggestedUsers] = useState([]);
const renderedSuggestedUsers = suggestedUsers.map((suggestedUser) => (
-
+
));
async function addNewFollower(desiredFollowValue) {
@@ -77,17 +66,9 @@ const AddFollowerModal = ({ modalVisible, setModalVisible }) => {
}, [addFriendValue]);
return (
-
-
+ closeModal}>
+
{
style={{ width: "35%" }}
>
- {suggestedUsers.length === 0 && (
- No Suggested Users
- )}
+ {suggestedUsers.length === 0 && No Suggested Users}
{suggestedUsers.length !== 0 && (
-
+
{renderedSuggestedUsers}
)}
diff --git a/src/components/modals/CreateWorkoutModal/CreateWorkoutModal.js b/src/components/modals/CreateWorkoutModal/CreateWorkoutModal.js
new file mode 100644
index 0000000..3b22145
--- /dev/null
+++ b/src/components/modals/CreateWorkoutModal/CreateWorkoutModal.js
@@ -0,0 +1,223 @@
+import { useEffect, useState } from "react";
+import { View, Image, Text, StyleSheet, Pressable, TouchableOpacity, Modal, TextInput, Button, ScrollView } from "react-native";
+import CustomButton from "../../CustomButton";
+import { Formik, Field, Form, ErrorMessage, FieldArray } from "formik";
+import { blueThemeColor, grayThemeColor } from "../../../library/constants";
+import { Toast } from "react-native-toast-message/lib/src/Toast";
+import { getCurrentUser } from "../../../crud/CacheOperations";
+import { createWorkout } from "../../../crud/WorkoutOperations";
+import Exercise from "../../Exercise/Exercise";
+export default function CreateWorkoutModal({
+ modalVisible,
+ setModalVisible,
+ refreshWorkouts,
+ setRefreshWorkouts,
+ scrollToBottom = null,
+ setScrollToBottom = null,
+ setWorkoutSelection = null,
+}) {
+ //const modalVisible = props.modalVisible;
+ //const setModalVisible = props.setModalVisible;
+ const [workoutTitle, setWorkoutTitle] = useState("");
+ //const [setsList, addToSetsList] = useState([]);
+ const [exerciseList, setExerciseList] = useState([]);
+ const [exerciseName, setExerciseName] = useState("");
+ const [exerciseNotes, setExerciseNotes] = useState("");
+ const [buttonShown, setButtonShown] = useState(true);
+ const [addNewExercise, setAddNewExercise] = useState(false);
+ const [exerciseNameNotSet, setExerciseNameNotSet] = useState(false);
+ const closeModal = () => {
+ setModalVisible(false);
+ };
+
+ function handleButtonPress() {
+ setAddNewExercise(true);
+ setButtonShown(false);
+ }
+ function handleConfirmPress() {
+ if (exerciseName.length === 0) {
+ Toast.show({
+ type: "error",
+ text1: "Please name the exercise!",
+ position: "bottom",
+ visibilityTime: 3000,
+ bottomOffset: 80,
+ });
+ } else {
+ let exercise = {
+ exerciseName: exerciseName,
+ exerciseNotes: exerciseNotes,
+ };
+
+ setExerciseList([...new Set([...exerciseList, exercise])]);
+ setExerciseName("");
+ setExerciseNotes("");
+ setButtonShown(true);
+ setAddNewExercise(false);
+ }
+ }
+ async function createNewWorkout() {
+ let currUser = await getCurrentUser();
+ let newWorkout = await createWorkout(currUser, workoutTitle, exerciseList);
+ if (scrollToBottom !== null) {
+ setScrollToBottom(true);
+ }
+ setWorkoutTitle("");
+ setExerciseList([]);
+ setRefreshWorkouts(!refreshWorkouts);
+ setModalVisible(false);
+ }
+
+ return (
+ setModalVisible(false)}>
+
+
+
+
+
+
+
+ {exerciseList.map((exercise, index) => (
+
+ ))}
+ {/*- Hello*/}
+ {addNewExercise && (
+
+
+
+
+
+
+
+
+
+ {exerciseName !== "" && exerciseNotes !== "" && (
+
+ )}
+
+ )}
+ {buttonShown && }
+
+
+ {exerciseList.length > 0 && workoutTitle !== "" && (
+
+ )}
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ exerciseNotes: {
+ marginLeft: 20,
+ },
+ addExerciseContainer: {
+ //flex: 1,
+ minHeight: 100,
+ flexDirection: "column",
+ //backgroundColor: "#202124",
+ borderTopWidth: 5,
+ borderLeftWidth: 5,
+ borderRightWidth: 5,
+ borderBottomWidth: 5,
+ //alignItems: "center",
+ marginTop: 10,
+ alignSelf: "center",
+ width: "80%",
+ },
+ exerciseContainer: {
+ //flex: 1,
+ //minHeight: 100,
+ flexDirection: "column",
+ //backgroundColor: "#202124",
+ //alignItems: "center",
+ //alignSelf: "center",
+ width: "80%",
+ },
+ addExerciseNameContainer: {
+ // flexDirection: "row",
+ height: 30,
+ //marginBottom: 20,
+ //borderColor: "black",
+ //textAlign: "center",
+ borderBottomWidth: 3,
+ },
+ exerciseNameContainer: {
+ height: 40,
+ },
+ workoutName: {
+ textAlign: "center",
+ color: blueThemeColor,
+ fontSize: 30,
+ fontWeight: "bold",
+ marginTop: 2,
+ marginLeft: 10,
+ width: "100%",
+ //textAlign: "center",
+ //borderBottomWidth: 3,
+ },
+ exerciseName: {
+ color: blueThemeColor,
+ fontSize: 20,
+ fontWeight: "bold",
+ marginTop: 2,
+ marginLeft: 10,
+ //textAlign: "center",
+ //borderBottomWidth: 3,
+ },
+ centeredView: {
+ flex: 1,
+ //top: "50%",
+ justifyContent: "center",
+ alignItems: "center",
+ },
+ transparentView: {
+ flex: 1,
+ position: "absolute",
+ left: 0,
+ top: 0,
+ width: "100%",
+ height: "100%",
+ backgroundColor: "rgba(52, 52, 52, 0.8)",
+ zIndex: -1,
+ },
+ blowupmain: {
+ width: "100%",
+ height: 400,
+ //position: "absolute",
+ //height: 400,
+ //marginTop: 20,
+ //position: "absolute",
+ //right: 0,
+ backgroundColor: "rgba(200,212,225,0.7)",
+ borderRightWidth: 0,
+ borderLeftWidth: 0,
+ borderWidth: 2,
+ borderTopWidth: 3,
+ borderRightColor: "black",
+ //marginBottom: 20,
+ },
+ blowupheader: {
+ height: 50,
+ marginBottom: 10,
+ borderColor: "black",
+ color: blueThemeColor,
+ fontSize: 50,
+ fontWeight: "bold",
+ width: "100%",
+ marginTop: 2,
+ textAlign: "center",
+ alignItems: "center",
+ borderBottomWidth: 3,
+ },
+ blowupbody: {
+ fontSize: 21,
+ textAlign: "left",
+ paddingLeft: 20,
+ marginTop: 5,
+ },
+});
diff --git a/src/components/modals/CreateWorkoutModal/index.js b/src/components/modals/CreateWorkoutModal/index.js
new file mode 100644
index 0000000..321d07d
--- /dev/null
+++ b/src/components/modals/CreateWorkoutModal/index.js
@@ -0,0 +1 @@
+export { default } from "./CreateWorkoutModal";
diff --git a/src/components/modals/NonCurrUserProfileModal.js/NonCurrUserProfileModal.js b/src/components/modals/NonCurrUserProfileModal.js/NonCurrUserProfileModal.js
index 4f47175..282666b 100644
--- a/src/components/modals/NonCurrUserProfileModal.js/NonCurrUserProfileModal.js
+++ b/src/components/modals/NonCurrUserProfileModal.js/NonCurrUserProfileModal.js
@@ -8,12 +8,7 @@ import { getFollowersList } from "../../../crud/FollowersOperations";
const imageSRC = require("../../../../assets/icons/Gymbit_Icons_Black/Back_Icon_Black.png");
-const NonCurrUserProfileModal = ({
- modalVisible,
- setModalVisible,
- username,
- image,
-}) => {
+const NonCurrUserProfileModal = ({ modalVisible, setModalVisible, username, image }) => {
const [user, setUser] = useState("");
const [followingCount, setFollowingCount] = useState("");
const [followersCount, setFollowersCount] = useState("");
@@ -50,12 +45,7 @@ const NonCurrUserProfileModal = ({
}
return (
-
+
-
-
- @{user.username !== null ? user.username : ""}
-
-
-
-
- Following
- {followingCount}
-
-
- Followers
- {followersCount}
+
+ @{username !== null ? username : ""}
+
+
+ Following
+ {followingCount}
+
+
+ Followers
+ {followersCount}
+
Bio
@@ -124,8 +114,8 @@ const styles = StyleSheet.create({
height: 80,
backgroundColor: "white",
paddingBottom: 50,
+ alignSelf: "flex-start",
paddingLeft: 10,
- alignSelf: "flex-start"
},
username: {
paddingTop: 30,
@@ -133,7 +123,7 @@ const styles = StyleSheet.create({
paddingLeft: 15,
fontSize: 20,
fontWeight: "bold",
- color: "#2E8CFF"
+ color: "#2E8CFF",
},
followercount: {
fontSize: 20,
@@ -164,7 +154,7 @@ const styles = StyleSheet.create({
minHeight: "auto",
flexDirection: "column",
alignItems: "center",
- alignSelf: "flex-start"
+ alignSelf: "flex-start",
},
followingText: {
fontSize: 11,
@@ -173,7 +163,7 @@ const styles = StyleSheet.create({
followingNumber: {
fontSize: 20,
fontWeight: "bold",
- paddingTop: 10
+ paddingTop: 10,
},
bioText: {
fontSize: 16,
diff --git a/src/components/signoutbutton/SignOutButton.js b/src/components/signoutbutton/SignOutButton.js
index 292d1a0..c737edf 100644
--- a/src/components/signoutbutton/SignOutButton.js
+++ b/src/components/signoutbutton/SignOutButton.js
@@ -9,6 +9,7 @@ import {
} from "react-native";
import { Auth, Amplify, DataStore } from "aws-amplify";
import { deleteAllCache } from "../../crud/CacheOperations";
+import FastImage from "react-native-fast-image";
const SignOutButton = () => {
const signOut = async () => {
@@ -26,6 +27,8 @@ const SignOutButton = () => {
};
async function signOutOps() {
await deleteAllCache();
+ await FastImage.clearDiskCache();
+ await FastImage.clearMemoryCache();
signOut();
}
diff --git a/src/crud/CacheOperations.js b/src/crud/CacheOperations.js
index a6dacb2..d679904 100644
--- a/src/crud/CacheOperations.js
+++ b/src/crud/CacheOperations.js
@@ -5,10 +5,6 @@ import { getCurrentAuthenticatedUser } from "../library/GetAuthenticatedUser";
const cacheDirectory = FileSystem.cacheDirectory;
-export async function logCache() {
- let files = await getAllCachedFiles();
- console.log(files);
-}
export async function deleteCachedFile(file) {
try {
const cachedFile = cacheDirectory + file;
@@ -72,17 +68,10 @@ export async function getCurrentUser() {
return username;
} catch (e) {
console.log("Error: Could not retrieve username from cache nor from S3");
+ return "";
}
}
-export async function getCacheLastModifiedUri(username, ending) {
- return cacheDirectory + username + ending + "lastModified.txt";
-}
-
-export async function getCacheImageFileUri(username, ending) {
- return cacheDirectory + username + ending;
-}
-
export async function cacheLastModified(username, lastModifiedMessage) {
const cacheLastModifiedUri = cacheDirectory + username + "pfplastModified.txt";
try {
@@ -94,6 +83,32 @@ export async function cacheLastModified(username, lastModifiedMessage) {
}
}
+export async function cacheRemoteUri(username, fileName) {
+ const cacheLastModifiedUri = cacheDirectory + username + fileName + "Uri.txt";
+ let remoteUri = await Storage.get(username + "/" + fileName);
+ try {
+ let cachedRemoteUri = await FileSystem.writeAsStringAsync(cacheLastModifiedUri, remoteUri, {
+ encoding: "utf8",
+ });
+ return remoteUri;
+ } catch (error) {
+ console.log("Error: Could not cache pfp uri", error);
+ return "";
+ }
+}
+export async function getUriFromCache(username, fileName) {
+ const cacheLastModifiedUri = cacheDirectory + username + fileName + "Uri.txt";
+ try {
+ let blah = await FileSystem.readAsStringAsync(cacheLastModifiedUri, {
+ encoding: "utf8",
+ });
+ return blah;
+ } catch (error) {
+ console.log("Error: Could not get uri from cache", error);
+ return "";
+ }
+}
+
export async function getLastModifiedCache(username, ending) {
const cacheLastModifiedUri = cacheDirectory + username + ending + "lastModified.txt";
try {
@@ -102,7 +117,8 @@ export async function getLastModifiedCache(username, ending) {
});
return lastModified;
} catch (e) {
- console.log("Could not find lasttModified for", username);
+ console.log("Could not find lastModified for", username);
+ return "";
}
}
@@ -126,7 +142,7 @@ export async function getCachedCurrUser() {
return cachedUserString;
} catch (e) {
console.log("Error: Could not read who the current user is from cache", e);
- return null;
+ return "";
}
}
@@ -153,36 +169,6 @@ export async function cachePosts(posts) {
}
}
-export async function getLastModifiedAWS(username, file) {
- let lastModified = null;
- const myInit = {
- queryStringParameters: {
- username: username, // OPTIONAL
- file: file,
- },
- };
- await API.get("getLastModified", "/getLastModified", myInit)
- .then((response) => {
- lastModified = response;
- })
- .catch((error) => {
- console.log("Error: could not get last modified using API call" + error.response);
- });
- return lastModified;
-}
-
-export async function cachePostsThatShouldBeCached(posts) {
- const cachedPostsUri = cacheDirectory + "postsCached.txt";
- try {
- let postsString = posts.toString();
- let po = await FileSystem.writeAsStringAsync(cachedPostsUri, postsString, {
- encoding: "utf8",
- });
- } catch (error) {
- console.log("Error: Could not cache posts that should be cached (for old cache deletion)");
- }
-}
-
export async function getPostsThatShouldBeCached() {
try {
const cachedPostsUri = cacheDirectory + "postsCached.txt";
@@ -251,7 +237,33 @@ export async function getImageFromCache(username, ending) {
}
}
-export async function cacheImageFromAWS(username, ending, addPng = false) {
+export async function getImageFromAWS(username, ending) {
+ try {
+ const uriAWS = await Storage.get(username + "/" + ending);
+ return uriAWS;
+ } catch (e) {
+ console.log("Error: could not get image", ending, "for", username, "from aws", e);
+ return null;
+ }
+}
+
+export async function cacheUriForImageFromAWS(username, ending) {
+ try {
+ const uriAWS = await Storage.get(username + "/" + ending);
+ const cacheFile = cacheDirectory + username + ending + "uri.txt";
+ await cacheImage(uriAWS, cacheFile);
+ return uriAWS;
+ } catch (e) {
+ console.log("Error: could not get image", ending, "for", username, "from aws", e);
+ return null;
+ }
+}
+
+export async function movePfpToCache(oldUri, username) {
+ const pfpCache = cacheDirectory + username + "pfp.png";
+}
+
+export async function cacheImageFromAWS(username, ending) {
const uriAWS = await Storage.get(username + "/" + ending);
//console.log(uriAWS);
let cacheImageFileUri = cacheDirectory + username + ending;
@@ -269,37 +281,16 @@ export async function cacheImageFromAWS(username, ending, addPng = false) {
}
export async function saveImageToAWS(fileName, blob) {
- await Storage.put(fileName, blob);
+ try {
+ await Storage.put(fileName, blob);
+ return true;
+ } catch (e) {
+ console.log("Error: Failed to upload image", fileName, "to AWS");
+ return false;
+ }
}
export async function updatePfpCache(username) {
- const cachedImage = await getImageFromCache(username, "pfp.png");
- // we are assuming that if the image exists in client then it should exist in the backend as well
- if (cachedImage !== "") {
- const lastModifiedAWS = await getLastModifiedAWS(username, "pfp.png");
- const lastModifiedCache = await getLastModifiedCache(username, "pfp");
- if (lastModifiedCache !== null) {
- if (lastModifiedAWS > lastModifiedCache) {
- //lastModifiedAWS has a higher alphabetical order (newer) than lastModifiedCache
- await cacheImageFromAWS(username, "pfp.png");
- await cacheLastModified(username, lastModifiedAWS);
- } else if (lastModifiedCache < lastModifiedAWS) {
- let fileName = username + "/pfp.png";
- saveImageToAWS(fileName, getCacheImageFileUri(username, "pfp.png"));
- } else {
- }
- } else {
- await cacheImageFromAWS(username, "pfp.png");
- await cacheLastModified(username, lastModifiedAWS);
- }
- } else {
- console.log("Profile pic for", username, "not found in cache; checking if it is in the backend");
- const lastModifiedAWS = await getLastModifiedAWS(username, "pfp.png");
- if (lastModifiedAWS === "None" || lastModifiedAWS === null) {
- return false;
- } else {
- let imageFromAWS = await cacheImageFromAWS(username, "pfp.png");
- await cacheLastModified(username, lastModifiedAWS);
- }
- }
+ let remoteUriAWS = await cacheRemoteUri(username, "pfp.png");
+ return remoteUriAWS;
}
diff --git a/src/crud/GoalOperations.js b/src/crud/GoalOperations.js
index a519e2e..f687571 100644
--- a/src/crud/GoalOperations.js
+++ b/src/crud/GoalOperations.js
@@ -56,8 +56,8 @@ export async function deleteGoal(goalID) {
try {
const goalToDelete = await DataStore.query(Goal, goalID);
await DataStore.delete(goalToDelete);
- console.log(`Successfully delete goal ${goalToDelete.id}`);
+ console.log(`Successfully deleted goal ${goalToDelete.id}`);
} catch (error) {
- console.error("Error saving goal", error);
+ console.error("Error deleting goal", error);
}
}
diff --git a/src/crud/PostOperations.js b/src/crud/PostOperations.js
index e9e07a0..5ee9d22 100644
--- a/src/crud/PostOperations.js
+++ b/src/crud/PostOperations.js
@@ -4,6 +4,7 @@ import { getCurrentUser } from "./CacheOperations";
import { DataStore, SortDirection } from "aws-amplify";
import { Post, Follows, User } from "../models";
import { getUserId } from "./UserOperations";
+import { getCurrentAuthenticatedUser } from "../library/GetAuthenticatedUser";
/**
* Creates a post and saves the new post in the backend
* @param {String} username
@@ -11,20 +12,31 @@ import { getUserId } from "./UserOperations";
* @param {Image} profilePicture
* @param {String} bio
*/
-export async function createPost(caption, photo, username) {
+export async function createPost(caption, photo, username, workout) {
try {
const user = await getCurrentUser();
const userId = await getUserId(user);
-
- await DataStore.save(
- new Post({
- caption: caption,
- photo: photo,
- username: username,
- userID: userId,
- })
- );
+ if (workout === null) {
+ await DataStore.save(
+ new Post({
+ caption: caption,
+ photo: photo,
+ username: username,
+ userID: userId,
+ })
+ );
+ } else {
+ await DataStore.save(
+ new Post({
+ caption: caption,
+ photo: photo,
+ username: username,
+ userID: userId,
+ Workout: workout,
+ })
+ );
+ }
console.log(`Post successfully created.`);
} catch (error) {
console.error("Error saving post", error);
@@ -64,11 +76,21 @@ export async function getUsersFollowed(username) {
export async function getPostsForMutualFeedFromAWS(username) {
try {
- const userId = await getUserId(username);
-
+ setTimeout(() => (loop = false), 10000);
+ let loop = true;
+ let userId;
+ // TODO: Remove workaround
+ console.log("MY USERNAME::: ", username);
+ while (loop) {
+ userId = await getUserId(username);
+ console.log("IDIDIDID: ", userId);
+
+ if (userId) loop = false;
+ }
const usersFollowed = await DataStore.query(Follows, (uf) => uf.username.eq(username));
+ console.log("USERS FOLLOWED");
+ usersFollowed.forEach((val) => console.log(val));
const usersFollowedIDs = [userId];
-
console.log(`Retrieved users followed for ${username}`);
for (let i = 0; i < usersFollowed.length; i++) {
@@ -82,8 +104,7 @@ export async function getPostsForMutualFeedFromAWS(username) {
sort: (s) => s.createdAt(SortDirection.DESCENDING),
});
for (let j = 0; j < postsToBeAdded.length; j++) {
- if (dateIsInPast3Days(postsToBeAdded[j]))
- posts.push(postsToBeAdded[j]);
+ if (dateIsInPast3Days(postsToBeAdded[j])) posts.push(postsToBeAdded[j]);
}
}
@@ -108,20 +129,16 @@ export async function getPostsForMutualFeedFromAWS(username) {
}
function dateIsInPast3Days(post) {
-
const createdAt = post.createdAt;
const difference = getTime(createdAt);
- if (difference >= 3)
- return false;
- else
- return true;
-
- }
+ if (difference >= 3) return false;
+ else return true;
+}
- function getTime(createdAt) {
- var ans = ""; // the output
+function getTime(createdAt) {
+ var ans = ""; // the output
if (createdAt == undefined) {
// Checks that createdAt exists
// Will not exist when DataStore is not connected to remote
@@ -136,19 +153,16 @@ function dateIsInPast3Days(post) {
var minutesDifference = diff / (1000 * 60);
var hoursDifference = Math.floor(minutesDifference / 60);
var daysDifference = Math.floor(hoursDifference / 24);
-
-
return Math.floor(daysDifference);
- }
-
+}
export async function getUserByPostId(postId) {
- const post = await DataStore.query(Post, postId);
- return post.username;
+ const post = await DataStore.query(Post, postId);
+ return post.username;
}
export async function getCreatedAt(postId) {
const post = await DataStore.query(Post, postId);
return String(post.createdAt);
-}
\ No newline at end of file
+}
diff --git a/src/crud/ReactionOperations.js b/src/crud/ReactionOperations.js
index 9b44a99..345bb8e 100644
--- a/src/crud/ReactionOperations.js
+++ b/src/crud/ReactionOperations.js
@@ -8,7 +8,6 @@ import { getTimeElapsed } from "../library/getTimeElapsed";
export async function createReaction(username, reactionType, postID) {
try {
- console.log("POSTID: ", postID);
const reaction = new Reaction({
postID: postID,
username: username,
@@ -23,9 +22,7 @@ export async function createReaction(username, reactionType, postID) {
let time = getTimeElapsed(createdAt);
let content = username + " reacted to your post from " + time;
- if (postsUsername !== username)
- await createNotification(postsUsername, date, content, username);
-
+ if (postsUsername !== username) await createNotification(postsUsername, date, content, username);
} catch (error) {
console.error(`There was an error creating a reaction.`, error);
}
@@ -34,11 +31,7 @@ export async function createReaction(username, reactionType, postID) {
export async function removeReaction(username, reactionType, postID) {
try {
const reactionToDelete = await DataStore.query(Reaction, (r) =>
- r.and((r) => [
- r.username.eq(username),
- r.reactionType.eq(reactionType),
- r.postID.eq(postID),
- ])
+ r.and((r) => [r.username.eq(username), r.reactionType.eq(reactionType), r.postID.eq(postID)])
);
if (reactionToDelete.length === 0) return;
await DataStore.delete(reactionToDelete[0]);
@@ -51,9 +44,7 @@ export async function removeReaction(username, reactionType, postID) {
export async function getReactions(postID) {
try {
- const reactionList = await DataStore.query(Reaction, (r) =>
- r.postID.eq(postID)
- );
+ const reactionList = await DataStore.query(Reaction, (r) => r.postID.eq(postID));
return reactionList;
} catch (error) {
console.error("There was an error retrieving reaction list.", error);
@@ -63,11 +54,7 @@ export async function getReactions(postID) {
export async function getUserReactions(postID, username, reactionType) {
try {
const reactions = await DataStore.query(Reaction, (r) =>
- r.and((r) => [
- r.username.eq(username),
- r.reactionType.eq(reactionType),
- r.postID.eq(postID),
- ])
+ r.and((r) => [r.username.eq(username), r.reactionType.eq(reactionType), r.postID.eq(postID)])
);
return reactions;
} catch (error) {
diff --git a/src/crud/UserOperations.js b/src/crud/UserOperations.js
index 62b9030..61ca3d6 100644
--- a/src/crud/UserOperations.js
+++ b/src/crud/UserOperations.js
@@ -2,6 +2,7 @@ import { DataStore, SortDirection } from "aws-amplify";
import { Post, User } from "../models";
import { Storage } from "aws-amplify";
import { getCurrentUser } from "./CacheOperations";
+import { ConsoleLogger } from "@aws-amplify/core";
/**
* Creates a user and saves the new user in the backend
@@ -190,9 +191,7 @@ export async function doesUserExist(username) {
export async function doesUserExistLower(lowerUsername) {
try {
- const user = await DataStore.query(User, (u) =>
- u.lowerUsername.eq(lowerUsername)
- );
+ const user = await DataStore.query(User, (u) => u.lowerUsername.eq(lowerUsername));
if (user[0] === undefined) console.log(`This user does not exist.`);
@@ -204,9 +203,7 @@ export async function doesUserExistLower(lowerUsername) {
export async function getUserIdByLowerUsername(lowerUsername) {
try {
- const user = await DataStore.query(User, (u) =>
- u.lowerUsername.eq(lowerUsername)
- );
+ const user = await DataStore.query(User, (u) => u.lowerUsername.eq(lowerUsername));
if (!user || !user.length) return "";
console.log(`Successfully found actual username for ${lowerUsername}`);
@@ -246,9 +243,7 @@ export async function togglePrivacy(username, privacy) {
})
);
- console.log(
- `Successfully changed ${username}'s privacy status to ${privacy}`
- );
+ console.log(`Successfully changed ${username}'s privacy status to ${privacy}`);
} catch (error) {
console.error(`Error changing ${username}'s privacy status to ${privacy}`);
}
@@ -261,9 +256,7 @@ export async function togglePrivacy(username, privacy) {
*/
export async function getUsersbyStartofUsername(username) {
try {
- const users = await DataStore.query(User, (u) =>
- u.username.beginsWith(username)
- );
+ const users = await DataStore.query(User, (u) => u.username.beginsWith(username));
return users;
} catch (error) {
console.error(`Error getting users by start of username.`, error);
@@ -332,13 +325,9 @@ export async function getUsersPostTimes(username) {
const posts = [];
- const postList = await DataStore.query(
- Post,
- (p) => p.username.eq(username),
- {
- sort: (s) => s.createdAt(SortDirection.DESCENDING),
- }
- );
+ const postList = await DataStore.query(Post, (p) => p.username.eq(username), {
+ sort: (s) => s.createdAt(SortDirection.DESCENDING),
+ });
for (let i = 0; i < postList.length; i++) {
posts.push(postList[i].createdAt);
@@ -419,19 +408,9 @@ export async function setLowerUsername(username) {
const original = await DataStore.query(User, userId);
- if (
- original.lowerUsername === null ||
- original.lowerUsername === undefined
- ) {
- await DataStore.save(
- User.copyOf(
- original,
- (updated) => (updated.lowerUsername = lowerUsername)
- )
- );
- console.log(
- `Successfully set lowercase username of ${username} to ${lowerUsername}`
- );
+ if (original.lowerUsername === null || original.lowerUsername === undefined) {
+ await DataStore.save(User.copyOf(original, (updated) => (updated.lowerUsername = lowerUsername)));
+ console.log(`Successfully set lowercase username of ${username} to ${lowerUsername}`);
} else {
console.log("Lowercase username already set");
}
diff --git a/src/crud/WorkoutOperations.js b/src/crud/WorkoutOperations.js
new file mode 100644
index 0000000..7389ca1
--- /dev/null
+++ b/src/crud/WorkoutOperations.js
@@ -0,0 +1,58 @@
+import { DataStore } from "aws-amplify";
+import { Workout } from "../models";
+import { getUserId } from "./UserOperations";
+
+export async function createWorkout(username, workoutName, exercises) {
+ try {
+ const userId = await getUserId(username);
+ let exercisesString = JSON.stringify(exercises);
+ const workout = new Workout({
+ username: username,
+ workoutName: workoutName,
+ exercises: exercisesString,
+ userID: userId,
+ });
+ await DataStore.save(workout);
+ console.log(`Workout ${workout.id} successfully created.`);
+ return workout;
+ } catch (error) {
+ console.error("Error saving workout", error);
+ return "";
+ }
+}
+
+export async function getWorkoutById(workoutId) {
+ try {
+ let workout = await DataStore.query(Workout, (w) => w.id.eq(workoutId));
+ return workout;
+ } catch (e) {
+ console.error("Error retrieving the workout for the user", e);
+ }
+}
+
+/**
+ * Returns all goals for any given user
+ * @param {String} username
+ * @returns goals
+ */
+export async function getWorkouts(username) {
+ try {
+ const userId = await getUserId(username);
+ const workouts = await DataStore.query(Workout, (w) => w.username.eq(username));
+ console.log(`Successfully retrieved workouts for ${username}`);
+
+ return workouts;
+ } catch (error) {
+ console.error(`Error retrieving workouts for ${username}`);
+ }
+}
+
+export async function deleteWorkout(workoutId) {
+ try {
+ const workoutToDelete = await DataStore.query(Workout, workoutId);
+ await DataStore.delete(workoutToDelete);
+ console.log(`Successfully deleted workout ${workoutToDelete.id}`);
+ } catch (error) {
+ console.error("Error deleting workout", error);
+ }
+}
diff --git a/src/screens/CreatePost.js b/src/screens/CreatePost.js
index caa24aa..94a1174 100644
--- a/src/screens/CreatePost.js
+++ b/src/screens/CreatePost.js
@@ -8,6 +8,10 @@ import { Auth } from "aws-amplify";
import { useNavigation } from "@react-navigation/native";
import getPictureFileName from "../library/getPictureFileName";
import { createPost } from "../crud/PostOperations";
+import { Toast } from "react-native-toast-message/lib/src/Toast";
+import { getCurrentUser } from "../crud/CacheOperations";
+import { getWorkouts } from "../crud/WorkoutOperations";
+import { blueThemeColor } from "../library/constants";
const styles = StyleSheet.create({
header: {
@@ -59,60 +63,96 @@ export function CreatePost() {
const navigation = useNavigation();
//const [username, setUsername] = useState("usernameNotFound");
Storage.configure(); // protected = you can write and read your posts, others can only read
+
+ const showPostUploadedToast = () => {
+ Toast.show({
+ type: "success",
+ text1: "Successfully uploaded your new post!",
+ text2: "Go check it out on your mutuals page 🔥",
+ position: "bottom",
+ visibilityTime: 6000,
+ });
+ };
+ const showPostNotUploadedToast = (usr) => {
+ // username; pass username as prop to all shits?
+ if (usr === "") {
+ usr = "friend";
+ }
+ Toast.show({
+ type: "error",
+ text1: "Uh oh, there was trouble uploading your post...",
+ text2: "Try again later. Sorry, " + usr + " 😔",
+ position: "bottom",
+ visibilityTime: 6000,
+ });
+ };
async function savePost() {
- await DataStore.start();
+ //await DataStore.start();
+ let username = await getCurrentUser();
try {
// try catch just in case sending the image doesn't work
- const { attributes } = await Auth.currentAuthenticatedUser();
- let username = attributes.preferred_username;
+ //const { attributes } = await getCurrentUser();
var fileName = username + "/" + getPictureFileName();
const response = await fetch(image);
const blob = await response.blob();
await createPost(text, fileName, username);
- Storage.put(fileName, blob);
+ await Storage.put(fileName, blob);
+ showPostUploadedToast();
} catch (error) {
+ showPostNotUploadedToast(username);
console.error("Error uploading file", error);
// TODO make a UI popup thing that lets the user know that their post wasn't uploaded (please try again later)
}
navigation.navigate("Mutuals");
}
return (
-
-
-
-
-
-
-
-
- {workoutSelection.join(", ")}
-
- Post Gymbit
-
+ <>
+
+
+
+
+
+
+
+
+ {workoutSelection.join(", ")}
+
+ Post Gymbit
+
+
-
+ >
);
}
function WorkoutSelection(props) {
+ const [workouts, setWorkouts] = useState([]);
+ async function getWorkoutList() {
+ let username = await getCurrentUser();
+ let workouts = await getWorkouts(username);
+ setWorkouts(workouts);
+ }
+ getWorkoutList();
const workoutSelection = props.workoutSelection;
const setWorkoutSelection = props.setWorkoutSelection;
- const updateFunction = (text) => {
- setWorkoutSelection([...new Set([...workoutSelection, text])]);
- };
return (
- What did you do today?
+ What workout did you do today?
- updateFunction("Run")} style={styles.workoutSelection}>
+ {workouts.map((workout) => (
+ setWorkoutSelection(workout)} style={styles.workoutSelection}>
+ {workout.workoutName}
+
+ ))}
+ {/* updateFunction("Run")} style={styles.workoutSelection}>
Run
updateFunction("Leg Day")} style={styles.workoutSelection}>
Leg Day
- updateFunction("Back and Biceps")} style={styles.workoutSelection}>
+ updateFunction("Bacccccccck and Biceps")} style={styles.workoutSelection}>
Back and Biceps
updateFunction("Chest and Triceps")} style={styles.workoutSelection}>
@@ -122,6 +162,7 @@ function WorkoutSelection(props) {
Bike
{workoutSelection.join(", ")}
+ */}
);
diff --git a/src/screens/MutualScreen.js b/src/screens/MutualScreen.js
index 4f979a3..f3288da 100644
--- a/src/screens/MutualScreen.js
+++ b/src/screens/MutualScreen.js
@@ -1,4 +1,4 @@
-import { View, Text} from "react-native";
+import { View, Text } from "react-native";
import { useState, useEffect } from "react";
import { useNavigation } from "@react-navigation/native";
import PostList from "../components/PostList";
@@ -6,8 +6,11 @@ import HomeHeader from "../components/HomeHeader/HomeHeader";
import { setLowerUsername } from "../crud/UserOperations";
import { getCurrentUser } from "../crud/CacheOperations";
-export function MutualScreen() {
- const [refresh, setRefresh] = useState(true);
+export function MutualScreen(props) {
+ //const [refresh, setRefresh] = useState(false);
+ const refresh = props.refresh;
+ const setRefresh = props.setRefresh;
+
const nav = useNavigation();
useEffect(() => {
@@ -22,11 +25,12 @@ export function MutualScreen() {
// await setLowerUsername(username);
// }
return (
-
-
- setRefresh(!refresh)} />
-
-
-
+
+ setRefresh(!refresh)} />
+
+
);
}
diff --git a/src/screens/ProfileScreen.js b/src/screens/ProfileScreen.js
index 4ea494c..567596c 100644
--- a/src/screens/ProfileScreen.js
+++ b/src/screens/ProfileScreen.js
@@ -5,23 +5,8 @@ import { blueThemeColor, grayThemeColor } from "../library/constants";
import React from "react";
import { getFollowsList } from "../crud/FollowingOperations";
import { getFollowersList } from "../crud/FollowersOperations";
-import {
- getBio,
- updateCurrentStreak,
- updateProfilePicture,
- getWeeklyGoal,
-} from "../crud/UserOperations";
-import { findUserByUsername } from "../crud/UserOperations";
-import {
- getLastModifiedCache,
- getLastModifiedAWS,
- cacheLastModified,
- getImageFromCache,
- cacheImageFromAWS,
- saveImageToAWS,
- getCachedCurrUser,
- getCurrentUser,
-} from "../crud/CacheOperations";
+import { getBio, updateCurrentStreak, getWeeklyGoal } from "../crud/UserOperations";
+import { saveImageToAWS, getCurrentUser, cacheRemoteUri } from "../crud/CacheOperations";
import ProfileMini from "../components/ProfileMini";
import Bio from "../components/Bio";
import CustomButton from "../components/CustomButton";
@@ -34,39 +19,83 @@ import * as FileSystem from "expo-file-system";
import "react-native-url-polyfill/auto";
import "react-native-get-random-values";
import Header from "../components/Header";
+import { getCurrentAuthenticatedUser } from "../library/GetAuthenticatedUser";
+import { Toast } from "react-native-toast-message/lib/src/Toast";
+import { useNetInfo } from "@react-native-community/netinfo";
//Need to also create the buttons to be clickable and call different functions
export function ProfileScreen(props) {
const navigation = useNavigation();
+ //const [refresh, setRefresh] = useState(false);
+ //const { refresh, setRefresh } = route.params;
+ const networkConnection = useNetInfo();
+ const refresh = props.refresh;
+ const setRefresh = props.setRefresh;
+ const [usernameSet, setUsernameSet] = useState(false);
const [username, setUsername] = useState("");
- const [followercount, setFollowerCount] = useState("");
- const [followingcount, setFollowingCount] = useState("");
+ const [followercount, setFollowerCount] = useState(0);
+ const [followingcount, setFollowingCount] = useState(0);
const [modalVisible, setModalVisible] = useState(false);
const [showMakePfp, setShowMakePfp] = useState(false);
- const [profilePic, setProfilePic] = useState("");
const [reload, setReload] = useState(false);
const [streak, setStreak] = useState(0);
const [showStreak, setShowStreak] = useState(false);
+ const [showPfpUploaded, setShowPfpUploaded] = useState(false);
useEffect(() => {
renderProfileInfo();
- getFollowersCount(username);
- getFollowingCount(username);
- }, [modalVisible, navigation]);
+ if (username !== "") {
+ getFollowersCount(username);
+ getFollowingCount(username);
+ }
+ }, [modalVisible, username]);
+
+ const showPfpUploadedToast = (usr) => {
+ Toast.show({
+ type: "success",
+ text1: "Successfully stored your new pfp!",
+ text2: "Lookin' good, " + usr + " 😎",
+ position: "bottom",
+ visibilityTime: 6000,
+ bottomOffset: 80,
+ });
+ };
+ const showPfpNotUploadedToast = (usr) => {
+ if (usr === "") {
+ usr = "friend";
+ }
+ Toast.show({
+ type: "error",
+ text1: "Oops, there was an issue uploading your new pfp...",
+ text2: "Try again later. Sorry, " + usr + " 😔",
+ position: "bottom",
+ visibilityTime: 6000,
+ bottomOffset: 80,
+ });
+ };
+
+ const showPfpCantChangeToast = () => {
+ Toast.show({
+ type: "error",
+ text1: "No Network connection detected.",
+ text2: "Can't change profile picture.",
+ position: "bottom",
+ visibilityTime: 4000,
+ bottomOffset: 80,
+ });
+ };
async function renderProfileInfo() {
let username = await getCurrentUser();
setUsername(username);
- const cachedImage = await getImageFromCache(username, "pfp.png");
- setProfilePic(cachedImage);
- let currStreak = await updateCurrentStreak(username);
+ /*let currStreak = await updateCurrentStreak(username);
setStreak(currStreak);
- console.log(streak);
if (streak > 0) {
setShowStreak(true);
} else {
setShowStreak(false);
- }
+ }*/
+ setUsernameSet(true);
}
async function getFollowingCount(username) {
@@ -79,10 +108,16 @@ export function ProfileScreen(props) {
setFollowerCount(followersList.length);
}
+ function handleProfileImageClick() {
+ if (networkConnection.isConnected) {
+ addProfileImage();
+ } else {
+ showPfpCantChangeToast();
+ }
+ }
const addProfileImage = async () => {
let _image = await ImagePicker.launchImageLibraryAsync({
- mediaTypes:
- ImagePicker.MediaTypeOptions.Images /*Only allow image upload */,
+ mediaTypes: ImagePicker.MediaTypeOptions.Images /*Only allow image upload */,
allowsEditing: true /*true= pull up an editing interface after image upload */,
aspect: [1, 1] /*1:1 image ratio, so it will be a square */,
quality: 1 /*highest quality image possible, on a scale of 0-1 we want 1 lol */,
@@ -93,19 +128,18 @@ export function ProfileScreen(props) {
const response = await fetch(_image.uri);
const blob = await response.blob();
const fileName = username + "/pfp.png";
- //updateProfilePicture(username, fileName);
- await saveImageToAWS(fileName, blob);
- let lastModified = await getLastModifiedAWS(username, "pfp.png");
- cacheLastModified(username, lastModified);
- let path = await cacheImageFromAWS(username, "pfp.png");
- if (path !== "") {
- setProfilePic(path);
+ let pfpUploaded = await saveImageToAWS(fileName, blob);
+ await cacheRemoteUri(username, "pfp.png");
+ setRefresh(!refresh);
+ if (pfpUploaded === true) {
+ showPfpUploadedToast(username);
+ } else {
+ showPfpNotUploadedToast(username);
}
setShowMakePfp(false);
} catch (error) {
console.log("Error uploading image to S3", error);
}
- //updateProfilePicture(username,image);
};
return (
@@ -113,37 +147,17 @@ export function ProfileScreen(props) {
-
-
-
- {showStreak ? (
+
+
+
+ {usernameSet && showStreak && (
-
+
{streak}
- ) : (
-
)}
- addProfileImage()} src={profilePic} />
+ handleProfileImageClick()} username={username} refresh={refresh} setRefresh={setRefresh} />
+
@{username}
Following
-
- navigation.navigate("Followers", { isFollowerPage: true })
- }
- >
+ navigation.navigate("Followers", { isFollowerPage: true })}>
{followingcount}
Followers
-
- navigation.navigate("Followers", { isFollowerPage: false })
- }
- >
+ navigation.navigate("Followers", { isFollowerPage: false })}>
{followercount}
setModalVisible(true)}>
Bio
-
+
{/*@{username}*/}
-
- ""}
- >
- Delete old cache
-
Toggle privacy
-
- Your current weekly workout goal is {goal}. Change goal bellow
-
+ Your current weekly workout goal is {goal}. Change goal below
-
+
-
- Change weekly goal
-
+ Change weekly goal
);
diff --git a/src/screens/WorkoutsScreen.js b/src/screens/WorkoutsScreen.js
new file mode 100644
index 0000000..292bd1c
--- /dev/null
+++ b/src/screens/WorkoutsScreen.js
@@ -0,0 +1,71 @@
+import { useEffect, useState } from "react";
+import { View, Image, Text, StyleSheet, Pressable, TouchableOpacity, ScrollView } from "react-native";
+import CustomButton from "../components/CustomButton";
+import { blueThemeColor, grayThemeColor } from "../library/constants";
+import CreateWorkoutModal from "../components/modals/CreateWorkoutModal";
+import { getWorkouts } from "../crud/WorkoutOperations";
+import { getCurrentUser } from "../crud/CacheOperations";
+import Workout from "../components/Workout/Workout";
+import Header from "../components/Header";
+
+export function WorkoutsScreen() {
+ const [modalVisible, setModalVisible] = useState(false);
+ const [workouts, setWorkouts] = useState([]);
+ const [refreshWorkouts, setRefreshWorkouts] = useState(false);
+
+ async function getWorkoutsForScreen() {
+ let currUser = await getCurrentUser();
+ let ejercicios = await getWorkouts(currUser);
+ setWorkouts(ejercicios);
+ }
+ useEffect(() => {
+ getWorkoutsForScreen();
+ }, [refreshWorkouts]);
+ return (
+ <>
+
+
+
+
+
+
+ setModalVisible(true)}
+ />
+
+
+ {workouts.map((workout, index) => (
+
+ ))}
+
+
+ >
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ backgroundColor: "white",
+ display: "flex",
+ flexDirection: "column",
+ height: "100%",
+ alignItems: "center",
+ },
+ stickyHeader: {
+ width: "100%",
+ marginBottom: "5%",
+ //marginTop: "20%",
+ display: "flex",
+ flexDirection: "column",
+ alignItems: "center",
+ paddingBottom: 5,
+ },
+});