diff --git a/Makefile b/Makefile index 2423e84..a3f4c6c 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,9 @@ ios: web: npm run start-react +web-cc: + npm run start-react --reset-cache + web-build: npm run build @@ -35,15 +38,20 @@ asset: cc: npx react-native start --reset-cache -clean: - rm -rf ./node_modules - rm -rf ./ios/Pods - rm -rf ./ios/Podfile.lock - rm -rf ./ios/build +clean-web: + sudo rm -rf node_modules && rm -rf dist + +clean-ios: + sudo rm -rf ./ios/Pods + sudo rm -rf ./ios/Podfile.lock + sudo rm -rf ./ios/build clean-android: cd android && ./gradlew clean -fclean: clean +fclean-ios: clean-ios + sudo rm -rf node_modules re: fclean all + +re-web: clean-web npm web diff --git a/babel.config.js b/babel.config.js index 5bd910c..2da7e8a 100644 --- a/babel.config.js +++ b/babel.config.js @@ -43,6 +43,7 @@ module.exports = { ? ['react-native-web', { commonjs: true }] : ['@babel/plugin-transform-private-methods', { loose: true }], moduleResolver, + '@babel/plugin-proposal-export-namespace-from', 'react-native-reanimated/plugin', [ 'module:react-native-dotenv', diff --git a/ios/Podfile b/ios/Podfile index a5ae5ff..fbb6412 100644 --- a/ios/Podfile +++ b/ios/Podfile @@ -5,7 +5,7 @@ require Pod::Executable.execute_command('node', ['-p', {paths: [process.argv[1]]}, )', __dir__]).strip -platform :ios, min_ios_version_supported +platform :ios, '12.0' prepare_react_native_project! linkage = ENV['USE_FRAMEWORKS'] diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 12776bf..e4d3fa8 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1187,6 +1187,8 @@ PODS: - React-utils (= 0.74.2) - RNAppleAuthentication (2.3.0): - React-Core + - RNCAsyncStorage (1.23.1): + - React-Core - RNCCheckbox (0.5.17): - BEMCheckBox (~> 1.4) - React-Core @@ -1324,6 +1326,7 @@ DEPENDENCIES: - React-utils (from `../node_modules/react-native/ReactCommon/react/utils`) - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) - "RNAppleAuthentication (from `../node_modules/@invertase/react-native-apple-authentication`)" + - "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)" - "RNCCheckbox (from `../node_modules/@react-native-community/checkbox`)" - "RNCPicker (from `../node_modules/@react-native-picker/picker`)" - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) @@ -1458,6 +1461,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon" RNAppleAuthentication: :path: "../node_modules/@invertase/react-native-apple-authentication" + RNCAsyncStorage: + :path: "../node_modules/@react-native-async-storage/async-storage" RNCCheckbox: :path: "../node_modules/@react-native-community/checkbox" RNCPicker: @@ -1538,6 +1543,7 @@ SPEC CHECKSUMS: React-utils: 4476b7fcbbd95cfd002f3e778616155241d86e31 ReactCommon: ecad995f26e0d1e24061f60f4e5d74782f003f12 RNAppleAuthentication: e99eaf3c4c01ad8ecb6125dd6f0cfd98871685b5 + RNCAsyncStorage: 826b603ae9c0f88b5ac4e956801f755109fa4d5c RNCCheckbox: a3ca9978cb0846b981d28da4e9914bd437403d77 RNCPicker: b7873ba797dc586bfaf3307d737cbdc620a9ff3e RNGestureHandler: 2282cfbcf86c360d29f44ace393203afd5c6cff7 diff --git a/ios/dearmypeace.xcodeproj/project.pbxproj b/ios/dearmypeace.xcodeproj/project.pbxproj index e9540db..c258056 100644 --- a/ios/dearmypeace.xcodeproj/project.pbxproj +++ b/ios/dearmypeace.xcodeproj/project.pbxproj @@ -8,17 +8,16 @@ /* Begin PBXBuildFile section */ 00E356F31AD99517003FC87E /* dearmypeaceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 00E356F21AD99517003FC87E /* dearmypeaceTests.m */; }; + 00E393ADA26EB29D6592BA6D /* libPods-dearmypeace.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 01CBCA0C2B5A7C70184E05B7 /* libPods-dearmypeace.a */; }; 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 */; }; - 259931529CC4095FD0534697 /* libPods-dearmypeace-dearmypeaceTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 01F1A403AABC01FF65B3B09A /* libPods-dearmypeace-dearmypeaceTests.a */; }; 25E2C58D98F541E99BBD73DF /* FontAwesome6_Solid.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E43AEB7153D44212887C9CF8 /* FontAwesome6_Solid.ttf */; }; 32FED066E9354FBA8FA88E8B /* FontAwesome6_Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C4D6C37E9964464887F61F24 /* FontAwesome6_Regular.ttf */; }; 3503CAE617EAFAE94E7B529F /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 72431CFA959C8F6262843DC9 /* PrivacyInfo.xcprivacy */; }; 37709B0C850C4E079916FAAF /* GowunBatang-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 69C39DA37EE04490A92B2DD3 /* GowunBatang-Regular.ttf */; }; 3B51D791DC294D72B6E6CC47 /* SimpleLineIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 310A28E80235433194003EC2 /* SimpleLineIcons.ttf */; }; 3D143E09F13C4701A3EDD451 /* Fontisto.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 4AB4F72C4C2246A690E9A574 /* Fontisto.ttf */; }; - 5DF11AC526AA35A1BB355A2A /* libPods-dearmypeace.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F1351DEF879BD1089EB9F682 /* libPods-dearmypeace.a */; }; 5F2975D4800947B5B438A508 /* FontAwesome.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A7D7DEC49252466C8666BA0C /* FontAwesome.ttf */; }; 641965F627514DDBAF620056 /* Feather.ttf in Resources */ = {isa = PBXBuildFile; fileRef = D5B1D94BBD1045779ABCC8F1 /* Feather.ttf */; }; 64880C4F2C3283F9009E2304 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 64880C4E2C3283F8009E2304 /* GoogleService-Info.plist */; }; @@ -38,6 +37,7 @@ D1B3BAE2393541CDA1CEF139 /* Entypo.ttf in Resources */ = {isa = PBXBuildFile; fileRef = B4493148EC4849E2BCCF74B2 /* Entypo.ttf */; }; E7433AA766DE445DA1FCB03B /* Zocial.ttf in Resources */ = {isa = PBXBuildFile; fileRef = BEC14622A37A46E78E05EC95 /* Zocial.ttf */; }; EC5BED14BEDC431BABD36978 /* MaterialCommunityIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 582A185F068242EA99AC1C92 /* MaterialCommunityIcons.ttf */; }; + EEA3DB0D7E4A80F3F1CF1AC3 /* libPods-dearmypeace-dearmypeaceTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 71E790C2D11877C38E4C93F6 /* libPods-dearmypeace-dearmypeaceTests.a */; }; F901C5C4D4E74E159FCCE97F /* Octicons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C99962C5F21544D3911260E0 /* Octicons.ttf */; }; FC7A548B569647A7B0A537E7 /* GowunBatang-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C134CBC23561433A9B1EA77C /* GowunBatang-Bold.ttf */; }; /* End PBXBuildFile section */ @@ -56,7 +56,7 @@ 00E356EE1AD99517003FC87E /* dearmypeaceTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = dearmypeaceTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 00E356F11AD99517003FC87E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 00E356F21AD99517003FC87E /* dearmypeaceTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = dearmypeaceTests.m; sourceTree = ""; }; - 01F1A403AABC01FF65B3B09A /* libPods-dearmypeace-dearmypeaceTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-dearmypeace-dearmypeaceTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 01CBCA0C2B5A7C70184E05B7 /* libPods-dearmypeace.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-dearmypeace.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07F961A680F5B00A75B9A /* dearmypeace.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = dearmypeace.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = dearmypeace/AppDelegate.h; sourceTree = ""; }; 13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = dearmypeace/AppDelegate.mm; sourceTree = ""; }; @@ -68,6 +68,7 @@ 391B37A4C9314BE58D0CA0BD /* AntDesign.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = AntDesign.ttf; path = ../src/assets/fonts/AntDesign.ttf; sourceTree = ""; }; 39C746303B6C4263A279335D /* FontAwesome5_Regular.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome5_Regular.ttf; path = ../src/assets/fonts/FontAwesome5_Regular.ttf; sourceTree = ""; }; 4AB4F72C4C2246A690E9A574 /* Fontisto.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Fontisto.ttf; path = ../src/assets/fonts/Fontisto.ttf; sourceTree = ""; }; + 4C73CFAC77110283A381247E /* Pods-dearmypeace.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-dearmypeace.debug.xcconfig"; path = "Target Support Files/Pods-dearmypeace/Pods-dearmypeace.debug.xcconfig"; sourceTree = ""; }; 582A185F068242EA99AC1C92 /* MaterialCommunityIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = MaterialCommunityIcons.ttf; path = ../src/assets/fonts/MaterialCommunityIcons.ttf; sourceTree = ""; }; 64880C4E2C3283F8009E2304 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "../key/GoogleService-Info.plist"; sourceTree = ""; }; 64880C502C33C1BC009E2304 /* Kalam-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; name = "Kalam-Bold.ttf"; path = "../src/assets/fonts/Kalam-Bold.ttf"; sourceTree = ""; }; @@ -76,29 +77,28 @@ 64C8F1AC2C2BFBBD00CAC7F8 /* dearmypeace.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = dearmypeace.entitlements; path = dearmypeace/dearmypeace.entitlements; sourceTree = ""; }; 69C39DA37EE04490A92B2DD3 /* GowunBatang-Regular.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GowunBatang-Regular.ttf"; path = "../src/assets/fonts/GowunBatang-Regular.ttf"; sourceTree = ""; }; 6DF4937B063240499BE351DD /* FontAwesome5_Brands.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome5_Brands.ttf; path = ../src/assets/fonts/FontAwesome5_Brands.ttf; sourceTree = ""; }; + 71E790C2D11877C38E4C93F6 /* libPods-dearmypeace-dearmypeaceTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-dearmypeace-dearmypeaceTests.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 72431CFA959C8F6262843DC9 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = dearmypeace/PrivacyInfo.xcprivacy; sourceTree = ""; }; 76C538F261A64E7A9AFA721A /* Foundation.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Foundation.ttf; path = ../src/assets/fonts/Foundation.ttf; sourceTree = ""; }; - 76DF136B0CE383515282061E /* Pods-dearmypeace.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-dearmypeace.debug.xcconfig"; path = "Target Support Files/Pods-dearmypeace/Pods-dearmypeace.debug.xcconfig"; sourceTree = ""; }; 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = dearmypeace/LaunchScreen.storyboard; sourceTree = ""; }; 8AEB0B34B3AE42309B1E7F15 /* Inder-Regular.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Inder-Regular.ttf"; path = "../src/assets/fonts/Inder-Regular.ttf"; sourceTree = ""; }; + 986738C446E346E4DEAB1D02 /* Pods-dearmypeace-dearmypeaceTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-dearmypeace-dearmypeaceTests.debug.xcconfig"; path = "Target Support Files/Pods-dearmypeace-dearmypeaceTests/Pods-dearmypeace-dearmypeaceTests.debug.xcconfig"; sourceTree = ""; }; A158E64498BC4713A5954755 /* FontAwesome6_Brands.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome6_Brands.ttf; path = ../src/assets/fonts/FontAwesome6_Brands.ttf; sourceTree = ""; }; A473DD0784EE4C70A9866D67 /* Ionicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Ionicons.ttf; path = ../src/assets/fonts/Ionicons.ttf; sourceTree = ""; }; A7D7DEC49252466C8666BA0C /* FontAwesome.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome.ttf; path = ../src/assets/fonts/FontAwesome.ttf; sourceTree = ""; }; AD62A83DE24C4711B055F16C /* EvilIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = EvilIcons.ttf; path = ../src/assets/fonts/EvilIcons.ttf; sourceTree = ""; }; - B0026305359FB7A82B000A37 /* Pods-dearmypeace.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-dearmypeace.release.xcconfig"; path = "Target Support Files/Pods-dearmypeace/Pods-dearmypeace.release.xcconfig"; sourceTree = ""; }; - B27D24D32F3F56892192F051 /* Pods-dearmypeace-dearmypeaceTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-dearmypeace-dearmypeaceTests.debug.xcconfig"; path = "Target Support Files/Pods-dearmypeace-dearmypeaceTests/Pods-dearmypeace-dearmypeaceTests.debug.xcconfig"; sourceTree = ""; }; B4493148EC4849E2BCCF74B2 /* Entypo.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Entypo.ttf; path = ../src/assets/fonts/Entypo.ttf; sourceTree = ""; }; BD650CEB73A44158B6D64397 /* FontAwesome5_Solid.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome5_Solid.ttf; path = ../src/assets/fonts/FontAwesome5_Solid.ttf; sourceTree = ""; }; BEC14622A37A46E78E05EC95 /* Zocial.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Zocial.ttf; path = ../src/assets/fonts/Zocial.ttf; sourceTree = ""; }; C134CBC23561433A9B1EA77C /* GowunBatang-Bold.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "GowunBatang-Bold.ttf"; path = "../src/assets/fonts/GowunBatang-Bold.ttf"; sourceTree = ""; }; C4D6C37E9964464887F61F24 /* FontAwesome6_Regular.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome6_Regular.ttf; path = ../src/assets/fonts/FontAwesome6_Regular.ttf; sourceTree = ""; }; C99962C5F21544D3911260E0 /* Octicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Octicons.ttf; path = ../src/assets/fonts/Octicons.ttf; sourceTree = ""; }; + D12C027A237EB4EFA27A48D2 /* Pods-dearmypeace-dearmypeaceTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-dearmypeace-dearmypeaceTests.release.xcconfig"; path = "Target Support Files/Pods-dearmypeace-dearmypeaceTests/Pods-dearmypeace-dearmypeaceTests.release.xcconfig"; sourceTree = ""; }; + D4A26386750FD6042449D095 /* Pods-dearmypeace.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-dearmypeace.release.xcconfig"; path = "Target Support Files/Pods-dearmypeace/Pods-dearmypeace.release.xcconfig"; sourceTree = ""; }; D5B1D94BBD1045779ABCC8F1 /* Feather.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Feather.ttf; path = ../src/assets/fonts/Feather.ttf; sourceTree = ""; }; E43AEB7153D44212887C9CF8 /* FontAwesome6_Solid.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome6_Solid.ttf; path = ../src/assets/fonts/FontAwesome6_Solid.ttf; sourceTree = ""; }; E4E9B612449947BCB6E514E7 /* MaterialIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = MaterialIcons.ttf; path = ../src/assets/fonts/MaterialIcons.ttf; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; - F1351DEF879BD1089EB9F682 /* libPods-dearmypeace.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-dearmypeace.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - F58EFBB30DB2CB429D25FF2E /* Pods-dearmypeace-dearmypeaceTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-dearmypeace-dearmypeaceTests.release.xcconfig"; path = "Target Support Files/Pods-dearmypeace-dearmypeaceTests/Pods-dearmypeace-dearmypeaceTests.release.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -106,7 +106,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 259931529CC4095FD0534697 /* libPods-dearmypeace-dearmypeaceTests.a in Frameworks */, + EEA3DB0D7E4A80F3F1CF1AC3 /* libPods-dearmypeace-dearmypeaceTests.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -114,7 +114,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 5DF11AC526AA35A1BB355A2A /* libPods-dearmypeace.a in Frameworks */, + 00E393ADA26EB29D6592BA6D /* libPods-dearmypeace.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -159,8 +159,8 @@ isa = PBXGroup; children = ( ED297162215061F000B7C4FE /* JavaScriptCore.framework */, - F1351DEF879BD1089EB9F682 /* libPods-dearmypeace.a */, - 01F1A403AABC01FF65B3B09A /* libPods-dearmypeace-dearmypeaceTests.a */, + 01CBCA0C2B5A7C70184E05B7 /* libPods-dearmypeace.a */, + 71E790C2D11877C38E4C93F6 /* libPods-dearmypeace-dearmypeaceTests.a */, ); name = Frameworks; sourceTree = ""; @@ -232,10 +232,10 @@ BBD78D7AC51CEA395F1C20DB /* Pods */ = { isa = PBXGroup; children = ( - 76DF136B0CE383515282061E /* Pods-dearmypeace.debug.xcconfig */, - B0026305359FB7A82B000A37 /* Pods-dearmypeace.release.xcconfig */, - B27D24D32F3F56892192F051 /* Pods-dearmypeace-dearmypeaceTests.debug.xcconfig */, - F58EFBB30DB2CB429D25FF2E /* Pods-dearmypeace-dearmypeaceTests.release.xcconfig */, + 4C73CFAC77110283A381247E /* Pods-dearmypeace.debug.xcconfig */, + D4A26386750FD6042449D095 /* Pods-dearmypeace.release.xcconfig */, + 986738C446E346E4DEAB1D02 /* Pods-dearmypeace-dearmypeaceTests.debug.xcconfig */, + D12C027A237EB4EFA27A48D2 /* Pods-dearmypeace-dearmypeaceTests.release.xcconfig */, ); path = Pods; sourceTree = ""; @@ -247,12 +247,12 @@ isa = PBXNativeTarget; buildConfigurationList = 00E357021AD99517003FC87E /* Build configuration list for PBXNativeTarget "dearmypeaceTests" */; buildPhases = ( - B6D01C1A1A561142C8718984 /* [CP] Check Pods Manifest.lock */, + A513134869FC09EFE2F75944 /* [CP] Check Pods Manifest.lock */, 00E356EA1AD99517003FC87E /* Sources */, 00E356EB1AD99517003FC87E /* Frameworks */, 00E356EC1AD99517003FC87E /* Resources */, - BA0075308824C7B92195F1ED /* [CP] Copy Pods Resources */, - F894B917BE95BA54176F9201 /* [CP] Embed Pods Frameworks */, + CD8208F9E4DD694FEDFA382E /* [CP] Embed Pods Frameworks */, + 93B793BEACE5B972264B349A /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -268,13 +268,13 @@ isa = PBXNativeTarget; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "dearmypeace" */; buildPhases = ( - C94E4BE67ABEC46407BFC47B /* [CP] Check Pods Manifest.lock */, + 7007549C98F95F7B75E45874 /* [CP] Check Pods Manifest.lock */, 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, - 5B1D2728ADC6ABFF9B42A642 /* [CP] Copy Pods Resources */, - C96E59B62EB72AA922394C14 /* [CP] Embed Pods Frameworks */, + 0B7B309510DCAB7301505DBF /* [CP] Embed Pods Frameworks */, + DE4D48098B6B8157BC4B6C59 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -383,24 +383,24 @@ shellPath = /bin/sh; shellScript = "set -e\n\nWITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"$REACT_NATIVE_PATH/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n"; }; - 5B1D2728ADC6ABFF9B42A642 /* [CP] Copy Pods Resources */ = { + 0B7B309510DCAB7301505DBF /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-dearmypeace/Pods-dearmypeace-resources-${CONFIGURATION}-input-files.xcfilelist", + "${PODS_ROOT}/Target Support Files/Pods-dearmypeace/Pods-dearmypeace-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); - name = "[CP] Copy Pods Resources"; + name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-dearmypeace/Pods-dearmypeace-resources-${CONFIGURATION}-output-files.xcfilelist", + "${PODS_ROOT}/Target Support Files/Pods-dearmypeace/Pods-dearmypeace-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-dearmypeace/Pods-dearmypeace-resources.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-dearmypeace/Pods-dearmypeace-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - B6D01C1A1A561142C8718984 /* [CP] Check Pods Manifest.lock */ = { + 7007549C98F95F7B75E45874 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -415,14 +415,14 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-dearmypeace-dearmypeaceTests-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-dearmypeace-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; }; - BA0075308824C7B92195F1ED /* [CP] Copy Pods Resources */ = { + 93B793BEACE5B972264B349A /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -439,7 +439,7 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-dearmypeace-dearmypeaceTests/Pods-dearmypeace-dearmypeaceTests-resources.sh\"\n"; showEnvVarsInLog = 0; }; - C94E4BE67ABEC46407BFC47B /* [CP] Check Pods Manifest.lock */ = { + A513134869FC09EFE2F75944 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -454,45 +454,45 @@ outputFileListPaths = ( ); outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-dearmypeace-checkManifestLockResult.txt", + "$(DERIVED_FILE_DIR)/Pods-dearmypeace-dearmypeaceTests-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; }; - C96E59B62EB72AA922394C14 /* [CP] Embed Pods Frameworks */ = { + CD8208F9E4DD694FEDFA382E /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-dearmypeace/Pods-dearmypeace-frameworks-${CONFIGURATION}-input-files.xcfilelist", + "${PODS_ROOT}/Target Support Files/Pods-dearmypeace-dearmypeaceTests/Pods-dearmypeace-dearmypeaceTests-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-dearmypeace/Pods-dearmypeace-frameworks-${CONFIGURATION}-output-files.xcfilelist", + "${PODS_ROOT}/Target Support Files/Pods-dearmypeace-dearmypeaceTests/Pods-dearmypeace-dearmypeaceTests-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-dearmypeace/Pods-dearmypeace-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-dearmypeace-dearmypeaceTests/Pods-dearmypeace-dearmypeaceTests-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - F894B917BE95BA54176F9201 /* [CP] Embed Pods Frameworks */ = { + DE4D48098B6B8157BC4B6C59 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-dearmypeace-dearmypeaceTests/Pods-dearmypeace-dearmypeaceTests-frameworks-${CONFIGURATION}-input-files.xcfilelist", + "${PODS_ROOT}/Target Support Files/Pods-dearmypeace/Pods-dearmypeace-resources-${CONFIGURATION}-input-files.xcfilelist", ); - name = "[CP] Embed Pods Frameworks"; + name = "[CP] Copy Pods Resources"; outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-dearmypeace-dearmypeaceTests/Pods-dearmypeace-dearmypeaceTests-frameworks-${CONFIGURATION}-output-files.xcfilelist", + "${PODS_ROOT}/Target Support Files/Pods-dearmypeace/Pods-dearmypeace-resources-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-dearmypeace-dearmypeaceTests/Pods-dearmypeace-dearmypeaceTests-frameworks.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-dearmypeace/Pods-dearmypeace-resources.sh\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -528,7 +528,7 @@ /* Begin XCBuildConfiguration section */ 00E356F61AD99517003FC87E /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = B27D24D32F3F56892192F051 /* Pods-dearmypeace-dearmypeaceTests.debug.xcconfig */; + baseConfigurationReference = 986738C446E346E4DEAB1D02 /* Pods-dearmypeace-dearmypeaceTests.debug.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -555,7 +555,7 @@ }; 00E356F71AD99517003FC87E /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = F58EFBB30DB2CB429D25FF2E /* Pods-dearmypeace-dearmypeaceTests.release.xcconfig */; + baseConfigurationReference = D12C027A237EB4EFA27A48D2 /* Pods-dearmypeace-dearmypeaceTests.release.xcconfig */; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; COPY_PHASE_STRIP = NO; @@ -579,7 +579,7 @@ }; 13B07F941A680F5B00A75B9A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 76DF136B0CE383515282061E /* Pods-dearmypeace.debug.xcconfig */; + baseConfigurationReference = 4C73CFAC77110283A381247E /* Pods-dearmypeace.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; @@ -612,7 +612,7 @@ }; 13B07F951A680F5B00A75B9A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = B0026305359FB7A82B000A37 /* Pods-dearmypeace.release.xcconfig */; + baseConfigurationReference = D4A26386750FD6042449D095 /* Pods-dearmypeace.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; diff --git a/package-lock.json b/package-lock.json index 52e6217..9abe3d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,9 @@ "name": "dearmypeace", "version": "0.0.1", "dependencies": { + "@babel/plugin-proposal-export-namespace-from": "^7.18.9", "@invertase/react-native-apple-authentication": "^2.3.0", + "@react-native-async-storage/async-storage": "^1.23.1", "@react-native-community/checkbox": "^0.5.17", "@react-native-google-signin/google-signin": "^12.2.1", "@react-native-picker/picker": "^2.7.7", @@ -620,6 +622,23 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-proposal-export-namespace-from": { + "version": "7.18.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz", + "integrity": "sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-export-namespace-from instead.", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.9", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-proposal-logical-assignment-operators": { "version": "7.20.7", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz", @@ -3363,6 +3382,18 @@ "node": ">=14" } }, + "node_modules/@react-native-async-storage/async-storage": { + "version": "1.23.1", + "resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.23.1.tgz", + "integrity": "sha512-Qd2kQ3yi6Y3+AcUlrHxSLlnBvpdCEMVGFlVBneVOjaFaPU61g1huc38g339ysXspwY1QZA2aNhrk/KlHGO+ewA==", + "license": "MIT", + "dependencies": { + "merge-options": "^3.0.4" + }, + "peerDependencies": { + "react-native": "^0.0.0-0 || >=0.60 <1.0" + } + }, "node_modules/@react-native-community/checkbox": { "version": "0.5.17", "resolved": "https://registry.npmjs.org/@react-native-community/checkbox/-/checkbox-0.5.17.tgz", @@ -14162,6 +14193,27 @@ "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", "dev": true }, + "node_modules/merge-options": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz", + "integrity": "sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==", + "license": "MIT", + "dependencies": { + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/merge-options/node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", diff --git a/package.json b/package.json index 4b19416..f7e6823 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,9 @@ "build": "BABEL_ENV=web webpack --config webpack.config.js --mode production" }, "dependencies": { + "@babel/plugin-proposal-export-namespace-from": "^7.18.9", "@invertase/react-native-apple-authentication": "^2.3.0", + "@react-native-async-storage/async-storage": "^1.23.1", "@react-native-community/checkbox": "^0.5.17", "@react-native-google-signin/google-signin": "^12.2.1", "@react-native-picker/picker": "^2.7.7", diff --git a/src/assets/images/piece_peace_4.png b/src/assets/images/piece_peace_4.png deleted file mode 100644 index c526910..0000000 Binary files a/src/assets/images/piece_peace_4.png and /dev/null differ diff --git a/src/assets/images/staindglass.png b/src/assets/images/staindglass.png index a9607fb..c526910 100644 Binary files a/src/assets/images/staindglass.png and b/src/assets/images/staindglass.png differ diff --git a/src/assets/images/staindglass_NON.png b/src/assets/images/staindglass_NON.png new file mode 100644 index 0000000..b865733 Binary files /dev/null and b/src/assets/images/staindglass_NON.png differ diff --git a/src/assets/images/staindglass_white.png b/src/assets/images/staindglass_white.png new file mode 100644 index 0000000..c431981 Binary files /dev/null and b/src/assets/images/staindglass_white.png differ diff --git a/src/components/ai/AiLetterEntryContent.tsx b/src/components/ai/AiLetterEntryContent.tsx index 18b5db7..6552274 100644 --- a/src/components/ai/AiLetterEntryContent.tsx +++ b/src/components/ai/AiLetterEntryContent.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { View, StyleSheet } from 'react-native'; import { IAiLetterEntry } from '@type/IAiLetterEntry'; import { fontBasic } from '@utils/Sizing'; -import MyText from '@components/common/MyText'; +import Markdown from 'react-native-markdown-display'; interface AiLetterEntryContentProps { section: IAiLetterEntry; @@ -11,7 +11,7 @@ interface AiLetterEntryContentProps { const AiLetterEntryContent: React.FC = ({ section }) => { return ( - {section.content} + {section.content} ); }; @@ -23,8 +23,18 @@ const styles = StyleSheet.create({ backgroundColor: '#F1E2CC', }, contentText: { - color: 'black', - fontSize: fontBasic, + body: { + fontSize: fontBasic, + fontFamily: 'GowunBatang-Regular', + }, + heading2: { + fontSize: 24, + fontFamily: 'GowunBatang-Bold', + marginTop: 10, + }, + heading3: { + marginTop: 10, + }, }, }); diff --git a/src/components/ai/AiLetterEntryHeader.tsx b/src/components/ai/AiLetterEntryHeader.tsx index 7b706d8..6870829 100644 --- a/src/components/ai/AiLetterEntryHeader.tsx +++ b/src/components/ai/AiLetterEntryHeader.tsx @@ -4,6 +4,7 @@ import { IAiLetterEntry } from '@type/IAiLetterEntry'; import MyText from '@components/common/MyText'; import Entypo from 'react-native-vector-icons/Entypo'; import { fontBasic, fontMedium } from '@utils/Sizing'; +import { alertColor } from '@utils/colors'; interface AiLetterEntryHeaderProps { section: IAiLetterEntry; @@ -101,7 +102,7 @@ const styles = StyleSheet.create({ position: 'absolute', top: 1, right: -4, - backgroundColor: '#EB6D52', + backgroundColor: alertColor, borderRadius: 4, width: 4, height: 4, diff --git a/src/components/common/MyText.tsx b/src/components/common/MyText.tsx index 928ecfc..5cd2cd1 100644 --- a/src/components/common/MyText.tsx +++ b/src/components/common/MyText.tsx @@ -5,6 +5,7 @@ interface MyTextProps extends TextProps { font?: string; size?: number; bold?: boolean; + style?: any; } // android 호환성 문제로 fontweight은 사용 불가 diff --git a/src/components/common/TabIcons.tsx b/src/components/common/TabIcons.tsx index 9cf6f42..0e33610 100644 --- a/src/components/common/TabIcons.tsx +++ b/src/components/common/TabIcons.tsx @@ -8,6 +8,7 @@ import AntDesign from 'react-native-vector-icons/AntDesign'; import MyIconButtons from '@components/common/MyIconButtons'; import { useRecoilValue } from 'recoil'; import { userInfoState } from '@stores/login'; +import { alertColor } from '@utils/colors'; export const CalendarIcon = memo(({ color }: ITabBarIconProps) => { if (Platform.OS === 'web') { @@ -55,7 +56,7 @@ const styles = StyleSheet.create({ position: 'absolute', right: -1, top: 1, - backgroundColor: '#EB6D52', + backgroundColor: alertColor, borderRadius: 8, width: 7, height: 7, diff --git a/src/components/login/storageUtils.ts b/src/components/login/storageUtils.ts new file mode 100644 index 0000000..eb91471 --- /dev/null +++ b/src/components/login/storageUtils.ts @@ -0,0 +1,19 @@ +import AsyncStorage from '@react-native-async-storage/async-storage'; + +export const saveCheckStatus = async (key: string, value: boolean) => { + try { + await AsyncStorage.setItem(key, JSON.stringify(value)); + } catch (e) { + console.error('Failed to save check status', e); + } +}; + +export const getCheckStatus = async (key: string): Promise => { + try { + const value = await AsyncStorage.getItem(key); + return value ? JSON.parse(value) : false; + } catch (e) { + console.error('Failed to load check status', e); + return false; + } +}; diff --git a/src/components/login/storageUtils.web.ts b/src/components/login/storageUtils.web.ts new file mode 100644 index 0000000..82e52da --- /dev/null +++ b/src/components/login/storageUtils.web.ts @@ -0,0 +1,17 @@ +export const saveCheckStatus = async (key: string, value: boolean) => { + try { + localStorage.setItem(key, JSON.stringify(value)); + } catch (e) { + console.error('Failed to save check status', e); + } +}; + +export const getCheckStatus = async (key: string): Promise => { + try { + const value = localStorage.getItem(key); + return value ? JSON.parse(value) : false; + } catch (e) { + console.error('Failed to load check status', e); + return false; + } +}; diff --git a/src/hooks/ai/ailetterHook.ts b/src/hooks/ai/ailetterHook.ts index d6ab87a..1a539cd 100644 --- a/src/hooks/ai/ailetterHook.ts +++ b/src/hooks/ai/ailetterHook.ts @@ -38,8 +38,6 @@ export const useAiLetterData = (initialDateStr: string) => { console.log('fetchMonthSummary result: ', result); return result; }, - staleTime: isCurrentMonth(currentDateStr) ? 0 : Infinity, - gcTime: isCurrentMonth(currentDateStr) ? 0 : Infinity, }); const fetchContentForID = async (id: IID) => { diff --git a/src/navigators/TabNavigator.tsx b/src/navigators/TabNavigator.tsx index 9bcb6eb..4d4586c 100644 --- a/src/navigators/TabNavigator.tsx +++ b/src/navigators/TabNavigator.tsx @@ -9,14 +9,10 @@ import PieceChip from '@components/diary/header/PieceChip'; import SettingButton from '@components/diary/header/SettingButton'; import { CalendarIcon, AiLetterIcon, PieceIcon, ShopIcon } from '@components/common/TabIcons'; import { appColor3 } from '@utils/colors'; -import { useRecoilValue } from 'recoil'; -import { userInfoState } from '@stores/login'; const Tab = createBottomTabNavigator(); const TabNavigator = () => { - const userInfo = useRecoilValue(userInfoState); - return ( { component={AiLetter} options={{ tabBarLabel: '편지', - tabBarIcon: ({ color }) => , + tabBarIcon: ({ focused, color, size }) => ( + + ), tabBarIconStyle: { marginTop: 5 }, }} /> diff --git a/src/screens/ai/AiLetterCalendar.tsx b/src/screens/ai/AiLetterCalendar.tsx index 07941a3..241a621 100644 --- a/src/screens/ai/AiLetterCalendar.tsx +++ b/src/screens/ai/AiLetterCalendar.tsx @@ -1,32 +1,52 @@ -import React, { useRef, useState, useCallback, useEffect } from 'react'; -import { View, StyleSheet } from 'react-native'; +import React, { useState, useCallback, useEffect, useRef } from 'react'; +import { View, StyleSheet, PanResponder, Animated as RNAnimated } from 'react-native'; import { format } from 'date-fns'; import { IDate, IDay } from '@type/Diary'; import { CalendarProvider } from 'react-native-calendars'; import { appColor3 } from '@utils/colors'; import AiLetterCalendarHeader from '@screens/ai/AiLetterCalendarHeader'; +import MyText from '@components/common/MyText'; const getYear = () => format(new Date(), 'yyyy'); const getMonth = () => format(new Date(), 'MM') as IDate['month']; const getDay = () => format(new Date(), 'dd'); const AiLetterCalendar = ({ children, onMonthChange }) => { - const todayBtnTheme = useRef({ - todayButtonTextColor: appColor3, - }); + const [isToday, setIsToday] = useState(true); + const [, setIsDragging] = useState(false); + const timerRef = useRef(null); + const DRAG_THRESHOLD = 10; + const [selectedDate, setSelectedDate] = useState({ year: getYear(), month: getMonth(), day: getDay(), }); + const position = useRef(new RNAnimated.ValueXY({ x: 0, y: 0 })).current; + const startPosition = useRef({ x: 0, y: 0 }).current; + useEffect(() => { setSelectedDate({ year: getYear(), month: getMonth(), day: getDay() }); }, []); + useEffect(() => { + const checkIfToday = () => { + const todayYear = getYear(); + const todayMonth = getMonth(); + const todayDay = getDay(); + setIsToday( + selectedDate.year === todayYear && + selectedDate.month === todayMonth && + selectedDate.day === todayDay, + ); + }; + + checkIfToday(); + }, [selectedDate]); + const handleMonthChange = useCallback( (date) => { - console.log('ExpandableCalendarScreen onMonthChange: ', date); const year = date.year.toString(); const month = date.month.toString().padStart(2, '0') as IDate['month']; const day = getDay(); @@ -36,6 +56,12 @@ const AiLetterCalendar = ({ children, onMonthChange }) => { [onMonthChange], ); + const handleMonthYearSelect = (month: number, year: number) => { + setSelectedDate((prevState) => ({ ...prevState, month: month.toString().padStart(2, '0') })); + setSelectedDate((prevState) => ({ ...prevState, year: year.toString() })); + onMonthChange(`${year}-${month.toString().padStart(2, '0')}`); + }; + const onLeftPress = () => { const newDate = new Date(Number(selectedDate.year), Number(selectedDate.month) - 2); const year = format(newDate, 'yyyy'); @@ -54,22 +80,78 @@ const AiLetterCalendar = ({ children, onMonthChange }) => { onMonthChange(`${year}-${month}`); }; + const handleTodayPress = () => { + const year = getYear(); + const month = getMonth(); + const day = getDay(); + setSelectedDate({ year, month, day }); + onMonthChange(`${year}-${month}`); + }; + + const panResponder = useRef( + PanResponder.create({ + onStartShouldSetPanResponder: () => true, + onPanResponderGrant: (evt) => { + startPosition.x = evt.nativeEvent.pageX; + startPosition.y = evt.nativeEvent.pageY; + position.setOffset({ + x: position.x._value, + y: position.y._value, + }); + position.setValue({ x: 0, y: 0 }); + setIsDragging(false); + if (timerRef.current) { + clearTimeout(timerRef.current); + } + }, + onPanResponderMove: (evt, gestureState) => { + position.setValue({ x: gestureState.dx, y: gestureState.dy }); + }, + onPanResponderRelease: (evt, gestureState) => { + position.flattenOffset(); + const distance = Math.sqrt(Math.pow(gestureState.dx, 2) + Math.pow(gestureState.dy, 2)); + if (distance <= DRAG_THRESHOLD) { + handleTodayPress(); + } else { + setIsDragging(true); + } + timerRef.current = setTimeout(() => { + setIsDragging(false); + }, 100); + }, + onPanResponderTerminate: () => { + setIsDragging(false); + }, + }), + ).current; + + const animatedStyle = { + transform: position.getTranslateTransform(), + }; + return ( {}} onMonthChange={handleMonthChange} - showTodayButton - todayButtonStyle={{ backgroundColor: 'rgba(255, 255, 255, 0.47)' }} - theme={todayBtnTheme.current} > {children} + + {!isToday && ( + + 오늘 + + )} ); @@ -84,5 +166,22 @@ const styles = StyleSheet.create({ paddingLeft: 16, paddingRight: 16, backgroundColor: 'transparent', + userSelect: 'none', + }, + todayButton: { + position: 'absolute', + bottom: 16, + right: 16, + backgroundColor: 'rgba(255, 255, 255, 0.47)', + borderRadius: 10, + paddingVertical: 5, + paddingHorizontal: 5, + borderColor: appColor3, + borderWidth: 1, + }, + todayButtonText: { + color: appColor3, + userSelect: 'none', + fontFamily: 'GowunBatang-Bold', }, }); diff --git a/src/screens/ai/AiLetterCalendarHeader.tsx b/src/screens/ai/AiLetterCalendarHeader.tsx index bc57a32..6581562 100644 --- a/src/screens/ai/AiLetterCalendarHeader.tsx +++ b/src/screens/ai/AiLetterCalendarHeader.tsx @@ -1,20 +1,30 @@ -import React from 'react'; -import { View, StyleSheet, Pressable } from 'react-native'; +import React, { useState, useEffect } from 'react'; +import { + View, + StyleSheet, + Pressable, + Modal, + FlatList, + TouchableWithoutFeedback, +} from 'react-native'; import CalendarArrow from '@components/diary/calendar/CalendarArrow'; import { IDay } from '@type/Diary'; -import { fontLarge } from '@utils/Sizing'; import MyText from '@components/common/MyText'; +import { appColor3 } from '@utils/colors'; +import { fontLarge } from '@utils/Sizing'; interface AiLetterCalendarHeaderProps { selectedDate: IDay; onLeftPress: () => void; onRightPress: () => void; + onMonthYearSelect: (month: number, year: number) => void; } const AiLetterCalendarHeader = ({ selectedDate, onLeftPress, onRightPress, + onMonthYearSelect, }: AiLetterCalendarHeaderProps) => { const kMonth = [ '일 월', @@ -31,11 +41,49 @@ const AiLetterCalendarHeader = ({ '십이 월', ]; + const [isModalVisible, setModalVisible] = useState(false); + const [selectedMonth, setSelectedMonth] = useState(parseInt(selectedDate.month, 10)); + const [selectedYear, setSelectedYear] = useState(parseInt(selectedDate.year, 10)); + + useEffect(() => { + setSelectedMonth(parseInt(selectedDate.month, 10)); + setSelectedYear(parseInt(selectedDate.year, 10)); + }, [selectedDate]); + + const handleModalDismiss = () => { + onMonthYearSelect(selectedMonth, selectedYear); + setModalVisible(false); + }; + + const renderMonthItem = ({ item }) => ( + setSelectedMonth(item.index + 1)}> + + + {item.month} + + + + ); + + const renderYearItem = ({ item }) => ( + setSelectedYear(item)}> + + + {item} + + + + ); + return ( - {`${kMonth[selectedDate.month - 1]} ${ - selectedDate.year - }`} + + setModalVisible(true)}> + {`${ + kMonth[selectedMonth - 1] + } ${selectedYear}`} + + @@ -44,6 +92,38 @@ const AiLetterCalendarHeader = ({ + + {/* Month and Year Modal */} + + + + + + + ({ month, index }))} + renderItem={renderMonthItem} + keyExtractor={(item) => item.index.toString()} + initialScrollIndex={Math.max(0, selectedMonth - 1)} + getItemLayout={(data, index) => ({ length: 50, offset: 50 * index, index })} + showsVerticalScrollIndicator={false} + /> + + + 2000 + i)} + renderItem={renderYearItem} + keyExtractor={(item) => item.toString()} + initialScrollIndex={Math.max(0, selectedYear - 2000)} + getItemLayout={(data, index) => ({ length: 50, offset: 50 * index, index })} + showsVerticalScrollIndicator={false} + /> + + + + + + ); }; @@ -58,6 +138,11 @@ const styles = StyleSheet.create({ paddingHorizontal: 10, paddingVertical: 5, }, + MYContainer: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + }, headerText: { fontSize: 26, color: '#333333', @@ -66,4 +151,49 @@ const styles = StyleSheet.create({ flexDirection: 'row', gap: 10, }, + modalOverlay: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: 'rgba(0, 0, 0, 0.5)', + }, + modalContent: { + width: 300, + maxHeight: 300, + backgroundColor: '#ffffff', + borderRadius: 10, + padding: 10, + flexDirection: 'row', + }, + modalListContainer: { + flexDirection: 'row', + justifyContent: 'space-between', + width: '100%', + }, + modalMonth: { + width: '50%', + }, + modalYear: { + width: '50%', + }, + modalItem: { + paddingVertical: 10, + paddingHorizontal: 20, + }, + modalText: { + fontSize: fontLarge, + textAlign: 'center', + }, + selectedText: { + fontSize: fontLarge, + textAlign: 'center', + color: appColor3, + }, + selectedStyle: { + borderColor: appColor3, + borderWidth: 1, + borderRadius: 15, + paddingVertical: 10, + paddingHorizontal: 19, + }, }); diff --git a/src/screens/login/CheckBoxWrapper.tsx b/src/screens/login/CheckBoxWrapper.tsx new file mode 100644 index 0000000..55e8e4d --- /dev/null +++ b/src/screens/login/CheckBoxWrapper.tsx @@ -0,0 +1,54 @@ +import React from 'react'; +import { View, Pressable, StyleSheet } from 'react-native'; +import CustomCheckbox from '@screens/login/CustomCheckbox'; +import { fontBasic } from '@utils/Sizing'; +import MyText from '@components/common/MyText'; + +interface Props { + isPolicyChecked: boolean; + isTermsChecked: boolean; + handleCheckboxPress: () => void; +} + +const CheckboxWrapper: React.FC = ({ + isPolicyChecked, + isTermsChecked, + handleCheckboxPress, +}) => { + return ( + + + + 이용약관 + + 개인정보처리방침 + 동의 + + + ); +}; + +const styles = StyleSheet.create({ + termsWrapper: { + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'center', + }, + termsText: { + fontFamily: 'GowunBatang-Regular', + fontSize: fontBasic, + color: '#000', + textDecorationLine: 'underline', + marginLeft: 3.5, + }, + termsTextNoLine: { + fontFamily: 'GowunBatang-Regular', + fontSize: fontBasic, + color: '#000', + }, +}); + +export default CheckboxWrapper; diff --git a/src/screens/login/CustomCheckbox.tsx b/src/screens/login/CustomCheckbox.tsx new file mode 100644 index 0000000..7fd5109 --- /dev/null +++ b/src/screens/login/CustomCheckbox.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import CheckBox from '@react-native-community/checkbox'; +import { StyleSheet } from 'react-native'; + +interface Props { + isChecked: boolean; + handleCheckboxPress: () => void; +} + +const CustomCheckbox: React.FC = ({ isChecked, handleCheckboxPress }) => { + return ( + + ); +}; + +const styles = StyleSheet.create({ + checkbox: { + width: 20, + height: 20, + marginRight: 5, + }, +}); + +export default CustomCheckbox; diff --git a/src/screens/login/CustomCheckbox.web.tsx b/src/screens/login/CustomCheckbox.web.tsx new file mode 100644 index 0000000..0dcac73 --- /dev/null +++ b/src/screens/login/CustomCheckbox.web.tsx @@ -0,0 +1,29 @@ +import React from 'react'; +import { CheckBox as WebCheckBox } from 'react-native-web'; +import { StyleSheet } from 'react-native'; + +interface Props { + isChecked: boolean; + handleCheckboxPress: () => void; +} + +const CustomCheckbox: React.FC = ({ isChecked, handleCheckboxPress }) => { + return ( + + ); +}; + +const styles = StyleSheet.create({ + checkbox: { + width: 20, + height: 20, + marginRight: 5, + }, +}); + +export default CustomCheckbox; diff --git a/src/screens/login/LoginScreen.tsx b/src/screens/login/LoginScreen.tsx index f426cdc..35eac49 100644 --- a/src/screens/login/LoginScreen.tsx +++ b/src/screens/login/LoginScreen.tsx @@ -1,35 +1,32 @@ import React, { useState, useEffect, useRef } from 'react'; -import { Image, View, StyleSheet, Platform, Modal, Pressable, Animated } from 'react-native'; +import { Image, View, StyleSheet, Animated } from 'react-native'; import MyText from '@components/common/MyText'; -import CheckBox from '@react-native-community/checkbox'; -import { CheckBox as WebCheckBox } from 'react-native-web'; -import { ScrollView } from 'react-native-gesture-handler'; -import Markdown from 'react-native-markdown-display'; import logo from '@assets/logo/logo.png'; -import terms from '@stores/terms'; -import policy from '@stores/policy'; -import { fontBasic, fontLarge, fontMedium } from '@utils/Sizing'; +import { fontLarge } from '@utils/Sizing'; import AppleLogin from '@screens/login/AppleLogin'; import GoogleLogin from '@screens/login/GoogleLogin'; +import TermsModal from '@screens/login/TermsModal'; +import CheckboxWrapper from '@screens/login/CheckBoxWrapper'; +import { saveCheckStatus, getCheckStatus } from '@components/login/storageUtils'; const LoginScreen = () => { const [isPolicyChecked, setIsPolicyChecked] = useState(false); const [isTermsChecked, setIsTermsChecked] = useState(false); const [isModalVisible, setIsModalVisible] = useState(false); const fadeAnim = useRef(new Animated.Value(0)).current; - const modalFadeAnim = useRef(new Animated.Value(0)).current; - const slideAnim = useRef(new Animated.Value(300)).current; const loginFuncRef = useRef<(() => void) | null>(null); const handleCheckboxPress = () => { setIsModalVisible(true); }; - const handleAgree = () => { + const handleAgree = async () => { if (!isPolicyChecked) { setIsPolicyChecked(true); + await saveCheckStatus('policy', true); } else { setIsTermsChecked(true); + await saveCheckStatus('terms', true); setIsModalVisible(false); if (loginFuncRef.current) { loginFuncRef.current(); @@ -45,6 +42,14 @@ const LoginScreen = () => { }; useEffect(() => { + const loadCheckStatus = async () => { + const policyStatus = await getCheckStatus('policy'); + const termsStatus = await getCheckStatus('terms'); + setIsPolicyChecked(policyStatus); + setIsTermsChecked(termsStatus); + }; + loadCheckStatus(); + Animated.timing(fadeAnim, { toValue: 1, duration: 1000, @@ -52,36 +57,6 @@ const LoginScreen = () => { }).start(); }, [fadeAnim]); - useEffect(() => { - if (isModalVisible) { - Animated.parallel([ - Animated.timing(modalFadeAnim, { - toValue: 1, - duration: 300, - useNativeDriver: true, - }), - Animated.timing(slideAnim, { - toValue: 0, - duration: 300, - useNativeDriver: true, - }), - ]).start(); - } else { - Animated.parallel([ - Animated.timing(modalFadeAnim, { - toValue: 0, - duration: 300, - useNativeDriver: true, - }), - Animated.timing(slideAnim, { - toValue: 300, - duration: 300, - useNativeDriver: true, - }), - ]).start(); - } - }, [isModalVisible, modalFadeAnim, slideAnim]); - const handleLoginPress = (loginFunc: () => void) => { if (!isPolicyChecked || !isTermsChecked) { loginFuncRef.current = loginFunc; @@ -100,58 +75,18 @@ const LoginScreen = () => { - - {Platform.OS === 'web' ? ( - - ) : ( - - )} - - 이용약관 - - 개인정보처리방침 - 동의 - - + - - - - - - {isPolicyChecked ? terms : policy} - - - - - 동의 - - - 취소 - - - - - + ); }; @@ -169,93 +104,11 @@ const styles = StyleSheet.create({ fontFamily: 'Kalam-Bold', marginBottom: 72, }, - content: { - fontSize: fontBasic, - paddingHorizontal: 10, - }, loginOptions: { width: '80%', alignItems: 'center', marginBottom: 15, }, - termsWrapper: { - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - }, - termsText: { - fontFamily: 'GowunBatang-Regular', - fontSize: fontBasic, - color: '#000', - textDecorationLine: 'underline', - marginLeft: 3.5, - }, - termsTextNoLine: { - fontFamily: 'GowunBatang-Regular', - fontSize: fontBasic, - color: '#000', - }, - modalContainer: { - flex: 1, - justifyContent: 'center', - alignItems: 'center', - backgroundColor: 'rgba(0, 0, 0, 0.5)', - }, - modalContent: { - width: '80%', - backgroundColor: '#fff', - padding: 20, - borderRadius: 10, - alignItems: 'center', - }, - modalTerms: { - maxHeight: 300, - marginBottom: 20, - }, - modalText: { - fontSize: fontMedium, - marginBottom: 20, - }, - modalButtons: { - flexDirection: 'row', - }, - agreeButton: { - marginHorizontal: 10, - paddingVertical: 10, - paddingHorizontal: 20, - backgroundColor: '#444', - borderRadius: 20, - }, - cancelButton: { - marginHorizontal: 10, - paddingVertical: 10, - paddingHorizontal: 20, - backgroundColor: '#ccc', - borderRadius: 20, - }, - buttonText: { - color: '#fff', - fontSize: fontMedium, - }, - checkbox: { - width: 20, - height: 20, - marginRight: 5, - }, - markdown: { - body: { - fontSize: fontBasic, - fontFamily: 'GowunBatang-Regular', - }, - heading2: { - fontSize: 24, - fontFamily: 'GowunBatang-Bold', - marginTop: 10, - }, - heading3: { - marginTop: 10, - }, - }, }); export default LoginScreen; diff --git a/src/screens/login/TermsModal.tsx b/src/screens/login/TermsModal.tsx new file mode 100644 index 0000000..87a8e79 --- /dev/null +++ b/src/screens/login/TermsModal.tsx @@ -0,0 +1,139 @@ +import React, { useRef, useEffect } from 'react'; +import { View, StyleSheet, Modal, Pressable, Animated } from 'react-native'; +import { ScrollView } from 'react-native-gesture-handler'; +import Markdown from 'react-native-markdown-display'; +import MyText from '@components/common/MyText'; +import terms from '@stores/terms'; +import policy from '@stores/policy'; +import { fontBasic, fontMedium } from '@utils/Sizing'; + +interface Props { + isModalVisible: boolean; + handleAgree: () => void; + handleCancel: () => void; + isPolicyChecked: boolean; +} + +const TermsModal: React.FC = ({ + isModalVisible, + handleAgree, + handleCancel, + isPolicyChecked, +}) => { + const modalFadeAnim = useRef(new Animated.Value(0)).current; + const slideAnim = useRef(new Animated.Value(300)).current; + + useEffect(() => { + if (isModalVisible) { + Animated.parallel([ + Animated.timing(modalFadeAnim, { + toValue: 1, + duration: 300, + useNativeDriver: true, + }), + Animated.timing(slideAnim, { + toValue: 0, + duration: 300, + useNativeDriver: true, + }), + ]).start(); + } else { + Animated.parallel([ + Animated.timing(modalFadeAnim, { + toValue: 0, + duration: 300, + useNativeDriver: true, + }), + Animated.timing(slideAnim, { + toValue: 300, + duration: 300, + useNativeDriver: true, + }), + ]).start(); + } + }, [isModalVisible, modalFadeAnim, slideAnim]); + + return ( + + + + + + {isPolicyChecked ? terms : policy} + + + + + 동의 + + + 취소 + + + + + + ); +}; + +const styles = StyleSheet.create({ + modalContainer: { + flex: 1, + justifyContent: 'center', + alignItems: 'center', + backgroundColor: 'rgba(0, 0, 0, 0.5)', + }, + modalContent: { + width: '80%', + backgroundColor: '#fff', + padding: 20, + borderRadius: 10, + alignItems: 'center', + }, + modalTerms: { + maxHeight: 300, + marginBottom: 20, + }, + modalButtons: { + flexDirection: 'row', + }, + agreeButton: { + marginHorizontal: 10, + paddingVertical: 10, + paddingHorizontal: 20, + backgroundColor: '#444', + borderRadius: 20, + }, + cancelButton: { + marginHorizontal: 10, + paddingVertical: 10, + paddingHorizontal: 20, + backgroundColor: '#ccc', + borderRadius: 20, + }, + buttonText: { + color: '#fff', + fontSize: fontMedium, + }, + markdown: { + body: { + fontSize: fontBasic, + fontFamily: 'GowunBatang-Regular', + }, + heading2: { + fontSize: 24, + fontFamily: 'GowunBatang-Bold', + marginTop: 10, + }, + heading3: { + marginTop: 10, + }, + }, +}); + +export default TermsModal; diff --git a/src/screens/piece/Piece.tsx b/src/screens/piece/Piece.tsx index 0c24838..94cfdcf 100644 --- a/src/screens/piece/Piece.tsx +++ b/src/screens/piece/Piece.tsx @@ -1,119 +1,67 @@ -import React, { useState, useEffect, useRef } from 'react'; -import { View, StyleSheet, Animated, PanResponder, Image } from 'react-native'; -import { PieChart } from 'react-native-chart-kit'; +import React, { useRef, useState } from 'react'; +import { View, StyleSheet, Animated, Image, TouchableWithoutFeedback } from 'react-native'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; import MyText from '@components/common/MyText'; -import PieceEntries from '@api/mock/PieceEntries'; -import { appColor1, appColor2, appColor3, appColor4, appColor5 } from '@utils/colors'; -import stainedglass from '@assets/images/piece_peace_4.png'; +import stainedglassTranparent from '@assets/images/staindglass_NON.png'; +import stainedglass from '@assets/images/staindglass.png'; import { fontBasic } from '@utils/Sizing'; -const chartConfig = { - backgroundColor: '#ffffff', - backgroundGradientFrom: '#ffffff', - backgroundGradientTo: '#ffffff', - color: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`, - labelColor: (opacity = 1) => `rgba(0, 0, 0, ${opacity})`, - style: { - borderRadius: 16, - }, - propsForDots: { - r: '6', - strokeWidth: '2', - stroke: '#ffa726', - }, -}; - const Piece = () => { - const [chartData, setChartData] = useState([]); - const [layoutWidth, setLayoutWidth] = useState(0); - const [currentIndex, setCurrentIndex] = useState(0); - const pan = useRef(new Animated.Value(0)).current; + const flipAnim = useRef(new Animated.Value(0)).current; + const [flipped, setFlipped] = useState(false); - useEffect(() => { - const coloredEntries = PieceEntries.map((entry) => { - let color = ''; - switch (entry.name) { - case '행복': - color = appColor5; - break; - case '슬픔': - color = appColor4; - break; - case '화': - color = appColor3; - break; - case '힘듦': - color = appColor2; - break; - case '무난함': - color = appColor1; - break; - default: - color = entry.color; - } - return { ...entry, color }; - }); - setChartData(coloredEntries); - }, []); + const handleImagePress = () => { + if (flipped) { + Animated.spring(flipAnim, { + toValue: 0, + useNativeDriver: true, + }).start(() => setFlipped(false)); + } else { + Animated.spring(flipAnim, { + toValue: 1, + useNativeDriver: true, + }).start(() => setFlipped(true)); + } + }; - const panResponder = useRef( - PanResponder.create({ - onStartShouldSetPanResponder: () => true, - onPanResponderMove: Animated.event([null, { dx: pan }], { useNativeDriver: false }), - onPanResponderRelease: (e, gestureState) => { - if (gestureState.dx > layoutWidth / 4) { - // 오른쪽으로 일정 거리 이상 스와이프하면 이미지로 전환 - Animated.spring(pan, { - toValue: layoutWidth, - useNativeDriver: true, - }).start(() => { - setCurrentIndex(1); - pan.setValue(0); - }); - } else if (gestureState.dx < -layoutWidth / 4) { - // 왼쪽으로 일정 거리 이상 스와이프하면 차트로 전환 - Animated.spring(pan, { - toValue: -layoutWidth, - useNativeDriver: true, - }).start(() => { - setCurrentIndex(0); - pan.setValue(0); - }); - } else { - // 원래 위치로 복귀 - Animated.spring(pan, { - toValue: 0, - useNativeDriver: true, - }).start(); - } - }, - }), - ).current; + const frontInterpolate = flipAnim.interpolate({ + inputRange: [0, 1], + outputRange: ['0deg', '180deg'], + }); + + const backInterpolate = flipAnim.interpolate({ + inputRange: [0, 1], + outputRange: ['180deg', '360deg'], + }); + + const frontAnimatedStyle = { + transform: [{ rotateY: frontInterpolate }], + }; + + const backAnimatedStyle = { + transform: [{ rotateY: backInterpolate }], + }; return ( - { - const { width } = event.nativeEvent.layout; - setLayoutWidth(width); - }} - > - - + + + + + + + + + + + + 리포트 - 여기에 해당 페이지의 리포트가 표시됩니다. + 2주의 기록이 쌓이면 리포트가 제공됩니다. @@ -125,22 +73,21 @@ const styles = StyleSheet.create({ flex: 1, backgroundColor: 'transparent', }, - swipeContainer: { + imageWrapper: { flex: 1, justifyContent: 'center', alignItems: 'center', - padding: 20, - backgroundColor: '#fff', - borderRadius: 16, - margin: 20, - elevation: 4, - shadowColor: '#000', - shadowOffset: { width: 0, height: 2 }, - shadowOpacity: 0.2, - shadowRadius: 4, + }, + imageContainer: { + width: '100%', + height: '100%', + backfaceVisibility: 'hidden', + }, + backImageContainer: { + position: 'absolute', }, image: { - width: '70%', + width: '100%', height: '100%', }, reportContainer: { diff --git a/src/utils/colors.ts b/src/utils/colors.ts index 8e2a22c..43f5724 100644 --- a/src/utils/colors.ts +++ b/src/utils/colors.ts @@ -5,6 +5,7 @@ export const appColor2 = '#E8C795'; export const appColor3 = '#C48E24'; export const appColor4 = '#A46F07'; export const appColor5 = '#765921'; +export const alertColor = '#EB6D52'; export const dotColors: { [key: number]: string } = { 1: '#D5C0A4', diff --git a/webpack.config.js b/webpack.config.js index 9e973ab..dba111e 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -16,16 +16,16 @@ const uncompiled = [ 'react-native-paper', 'react-native-element-dropdown', '@invertase/react-native-apple-authentication', - 'react-native-encrypted-storage', 'react-native-chart-kit', - 'react-native-gesture-handler', - 'react-native-reanimated', 'react-native-date-picker', - 'react-native-encrypted-storage', 'react-native-markdown-display', 'react-apple-signin-auth', 'react-native-svg', 'react-native-svg-transformer', + 'react-native-gesture-handler', + 'react-native-reanimated', + '@react-native-async-storage/async-storage', + 'react-native-encrypted-storage', ]; const babelLoaderConfiguration = { @@ -86,7 +86,7 @@ module.exports = { resourceRegExp: /^@invertase\/react-native-apple-authentication$/, }), new webpack.IgnorePlugin({ - resourceRegExp: /react-native-reanimated/, + resourceRegExp: /^@react-native-async-storage\/async-storage$/, }), new webpack.IgnorePlugin({ resourceRegExp: /react-native-encrypted-storage/, diff --git a/yarn.lock b/yarn.lock index c6787d5..2818707 100644 --- a/yarn.lock +++ b/yarn.lock @@ -180,7 +180,7 @@ dependencies: "@babel/types" "^7.24.7" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.7", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.7", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": version "7.24.7" resolved "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz" integrity sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg== @@ -332,6 +332,14 @@ "@babel/helper-plugin-utils" "^7.24.7" "@babel/plugin-syntax-export-default-from" "^7.24.7" +"@babel/plugin-proposal-export-namespace-from@^7.18.9": + version "7.18.9" + resolved "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz" + integrity sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-proposal-logical-assignment-operators@^7.18.0": version "7.20.7" resolved "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.20.7.tgz" @@ -1634,6 +1642,13 @@ resolved "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== +"@react-native-async-storage/async-storage@^1.23.1": + version "1.23.1" + resolved "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.23.1.tgz" + integrity sha512-Qd2kQ3yi6Y3+AcUlrHxSLlnBvpdCEMVGFlVBneVOjaFaPU61g1huc38g339ysXspwY1QZA2aNhrk/KlHGO+ewA== + dependencies: + merge-options "^3.0.4" + "@react-native-community/checkbox@^0.5.17": version "0.5.17" resolved "https://registry.npmjs.org/@react-native-community/checkbox/-/checkbox-0.5.17.tgz" @@ -5856,6 +5871,11 @@ is-path-inside@^3.0.3: resolved "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + is-plain-obj@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz" @@ -6811,6 +6831,13 @@ merge-descriptors@1.0.1: resolved "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz" integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== +merge-options@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/merge-options/-/merge-options-3.0.4.tgz" + integrity sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ== + dependencies: + is-plain-obj "^2.1.0" + merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz" @@ -8164,7 +8191,7 @@ react-native-web@^0.19.12: postcss-value-parser "^4.2.0" styleq "^0.1.3" -react-native@*, "react-native@>= 0.30.0", "react-native@>= 0.50.0", "react-native@>= 0.62", "react-native@>= 0.64.3", react-native@>=0.50.4, react-native@>=0.59.0, react-native@>=0.60.0, react-native@0.74.2: +react-native@*, "react-native@^0.0.0-0 || >=0.60 <1.0", "react-native@>= 0.30.0", "react-native@>= 0.50.0", "react-native@>= 0.62", "react-native@>= 0.64.3", react-native@>=0.50.4, react-native@>=0.59.0, react-native@>=0.60.0, react-native@0.74.2: version "0.74.2" resolved "https://registry.npmjs.org/react-native/-/react-native-0.74.2.tgz" integrity sha512-EBMBjPPL4/GjHMP4NqsZabT3gI5WU9cSmduABGAGrd8uIcmTZ5F2Ng9k6gFmRm7n8e8CULxDNu98ZpQfBjl7Bw==