diff --git a/android/app/build.gradle b/android/app/build.gradle index 58ebdb2..6dfe281 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -99,6 +99,12 @@ android { keyAlias 'androiddebugkey' keyPassword 'android' } + release { + storeFile file('learningisfun.keystore') + storePassword 'Test@123' + keyAlias 'learningisfun' + keyPassword 'Test@123' + } } buildTypes { debug { @@ -107,7 +113,7 @@ android { release { // Caution! In production, you need to generate your own keystore file. // see https://reactnative.dev/docs/signed-apk-android. - signingConfig signingConfigs.debug + signingConfig signingConfigs.release shrinkResources (findProperty('android.enableShrinkResourcesInReleaseBuilds')?.toBoolean() ?: false) minifyEnabled enableProguardInReleaseBuilds proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" diff --git a/android/app/learningisfun.keystore b/android/app/learningisfun.keystore new file mode 100644 index 0000000..7e3441f Binary files /dev/null and b/android/app/learningisfun.keystore differ diff --git a/android/app/src/main/ic_launcher-playstore.png b/android/app/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000..02a159e Binary files /dev/null and b/android/app/src/main/ic_launcher-playstore.png differ diff --git a/android/app/src/main/res/drawable/splashscreen_image.png b/android/app/src/main/res/drawable/splashscreen_image.png index cc94f37..5b3bae4 100644 Binary files a/android/app/src/main/res/drawable/splashscreen_image.png and b/android/app/src/main/res/drawable/splashscreen_image.png differ diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..036d09b --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index a2f5908..98a26be 100644 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..86a6f94 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png index 1b52399..e04b0f0 100644 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and b/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index ff10afd..385d51f 100644 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..96c7c64 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png index 115a4c7..36aacae 100644 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and b/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index dcd3cd8..c4ff5d5 100644 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..7ae121a Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png index 459ca60..249ee94 100644 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index 8ca12fe..6e5d7bf 100644 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..a3f9fd5 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png index 8e19b41..ed9a3fa 100644 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index b824ebd..7a03d95 100644 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png new file mode 100644 index 0000000..faf4b59 Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png index 4c19a13..f417a95 100644 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/android/app/src/main/res/values/ic_launcher_background.xml b/android/app/src/main/res/values/ic_launcher_background.xml new file mode 100644 index 0000000..c5d5899 --- /dev/null +++ b/android/app/src/main/res/values/ic_launcher_background.xml @@ -0,0 +1,4 @@ + + + #FFFFFF + \ No newline at end of file diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 2217ac4..33feadc 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -1,3 +1,3 @@ - learningisfun + Learn by Playing diff --git a/ios/learningisfun.xcodeproj/project.pbxproj b/ios/learningisfun.xcodeproj/project.pbxproj index 3d1e461..89ffc37 100644 --- a/ios/learningisfun.xcodeproj/project.pbxproj +++ b/ios/learningisfun.xcodeproj/project.pbxproj @@ -19,7 +19,7 @@ /* Begin PBXFileReference section */ 062168332AB69E94003B86BB /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; - 13B07F961A680F5B00A75B9A /* learningisfun.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = learningisfun.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 13B07F961A680F5B00A75B9A /* Learn by Playing.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Learn by Playing.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07FAF1A68108700A75B9A /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = learningisfun/AppDelegate.h; sourceTree = ""; }; 13B07FB01A68108700A75B9A /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = learningisfun/AppDelegate.mm; sourceTree = ""; }; 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = learningisfun/Images.xcassets; sourceTree = ""; }; @@ -95,7 +95,7 @@ 83CBBA001A601CBA00E9B192 /* Products */ = { isa = PBXGroup; children = ( - 13B07F961A680F5B00A75B9A /* learningisfun.app */, + 13B07F961A680F5B00A75B9A /* Learn by Playing.app */, ); name = Products; sourceTree = ""; @@ -158,7 +158,7 @@ ); name = learningisfun; productName = learningisfun; - productReference = 13B07F961A680F5B00A75B9A /* learningisfun.app */; + productReference = 13B07F961A680F5B00A75B9A /* Learn by Playing.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ @@ -364,6 +364,7 @@ ); INFOPLIST_FILE = learningisfun/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "Learning By Playing"; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.education"; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -377,7 +378,7 @@ ); OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; PRODUCT_BUNDLE_IDENTIFIER = org.name.learningisfun; - PRODUCT_NAME = learningisfun; + PRODUCT_NAME = "Learn by Playing"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; @@ -393,6 +394,7 @@ CURRENT_PROJECT_VERSION = 1; INFOPLIST_FILE = learningisfun/Info.plist; INFOPLIST_KEY_CFBundleDisplayName = "Learning By Playing"; + INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.education"; IPHONEOS_DEPLOYMENT_TARGET = 13.0; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -406,7 +408,7 @@ ); OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = org.name.learningisfun; - PRODUCT_NAME = learningisfun; + PRODUCT_NAME = "Learn by Playing"; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; }; diff --git a/ios/learningisfun/Images.xcassets/AppIcon.appiconset/App Store 1024pt.png b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/App Store 1024pt.png index 15c16f9..ce8101a 100644 Binary files a/ios/learningisfun/Images.xcassets/AppIcon.appiconset/App Store 1024pt.png and b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/App Store 1024pt.png differ diff --git a/ios/learningisfun/Images.xcassets/AppIcon.appiconset/Contents.json b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/Contents.json index 2a3cf3b..af6188d 100644 --- a/ios/learningisfun/Images.xcassets/AppIcon.appiconset/Contents.json +++ b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/Contents.json @@ -1,5 +1,110 @@ { "images" : [ + { + "filename" : "iPhone Notifications 20pt@2x.png", + "idiom" : "universal", + "platform" : "ios", + "scale" : "2x", + "size" : "20x20" + }, + { + "filename" : "iPhone Notifications 20pt@3x.png", + "idiom" : "universal", + "platform" : "ios", + "scale" : "3x", + "size" : "20x20" + }, + { + "filename" : "iPhone Settings 29pt@2x.png", + "idiom" : "universal", + "platform" : "ios", + "scale" : "2x", + "size" : "29x29" + }, + { + "filename" : "iPhone Settings 29pt@3x.png", + "idiom" : "universal", + "platform" : "ios", + "scale" : "3x", + "size" : "29x29" + }, + { + "filename" : "iPad Notifications 38pt.png", + "idiom" : "universal", + "platform" : "ios", + "scale" : "2x", + "size" : "38x38" + }, + { + "filename" : "iPad Notifications 38pt@2x 1.png", + "idiom" : "universal", + "platform" : "ios", + "scale" : "3x", + "size" : "38x38" + }, + { + "filename" : "iPad Spotlight 40pt@2x.png", + "idiom" : "universal", + "platform" : "ios", + "scale" : "2x", + "size" : "40x40" + }, + { + "filename" : "iPhone Spotlight 40pt@3x.png", + "idiom" : "universal", + "platform" : "ios", + "scale" : "3x", + "size" : "40x40" + }, + { + "filename" : "iPhone App 60pt@2x.png", + "idiom" : "universal", + "platform" : "ios", + "scale" : "2x", + "size" : "60x60" + }, + { + "filename" : "iPhone App 60pt@3x.png", + "idiom" : "universal", + "platform" : "ios", + "scale" : "3x", + "size" : "60x60" + }, + { + "filename" : "iPad Notifications 64pt.png", + "idiom" : "universal", + "platform" : "ios", + "scale" : "2x", + "size" : "64x64" + }, + { + "filename" : "iPad Notifications 64pt@2x.png", + "idiom" : "universal", + "platform" : "ios", + "scale" : "3x", + "size" : "64x64" + }, + { + "filename" : "iPad Notifications 68pt.png", + "idiom" : "universal", + "platform" : "ios", + "scale" : "2x", + "size" : "68x68" + }, + { + "filename" : "iPad App 76pt@2x.png", + "idiom" : "universal", + "platform" : "ios", + "scale" : "2x", + "size" : "76x76" + }, + { + "filename" : "iPad Pro App 83.5pt@2x.png", + "idiom" : "universal", + "platform" : "ios", + "scale" : "2x", + "size" : "83.5x83.5" + }, { "filename" : "App Store 1024pt.png", "idiom" : "universal", diff --git a/ios/learningisfun/Images.xcassets/SplashScreen.imageset/iPad App 76pt@2x 1.png b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPad App 76pt@2x.png similarity index 100% rename from ios/learningisfun/Images.xcassets/SplashScreen.imageset/iPad App 76pt@2x 1.png rename to ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPad App 76pt@2x.png diff --git a/ios/learningisfun/Images.xcassets/SplashScreen.imageset/iPad Notifications 38pt.png b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPad Notifications 38pt.png similarity index 100% rename from ios/learningisfun/Images.xcassets/SplashScreen.imageset/iPad Notifications 38pt.png rename to ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPad Notifications 38pt.png diff --git a/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPad Notifications 38pt@2x 1.png b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPad Notifications 38pt@2x 1.png new file mode 100644 index 0000000..3d44b3e Binary files /dev/null and b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPad Notifications 38pt@2x 1.png differ diff --git a/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPad Notifications 64pt.png b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPad Notifications 64pt.png new file mode 100644 index 0000000..fc13edb Binary files /dev/null and b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPad Notifications 64pt.png differ diff --git a/ios/learningisfun/Images.xcassets/SplashScreen.imageset/iPad Notifications 64pt@2x.png b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPad Notifications 64pt@2x.png similarity index 100% rename from ios/learningisfun/Images.xcassets/SplashScreen.imageset/iPad Notifications 64pt@2x.png rename to ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPad Notifications 64pt@2x.png diff --git a/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPad Notifications 68pt.png b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPad Notifications 68pt.png new file mode 100644 index 0000000..44d95fd Binary files /dev/null and b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPad Notifications 68pt.png differ diff --git a/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPad Pro App 83.5pt@2x.png b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPad Pro App 83.5pt@2x.png new file mode 100644 index 0000000..a60958d Binary files /dev/null and b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPad Pro App 83.5pt@2x.png differ diff --git a/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPad Spotlight 40pt@2x.png b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPad Spotlight 40pt@2x.png new file mode 100644 index 0000000..97370c8 Binary files /dev/null and b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPad Spotlight 40pt@2x.png differ diff --git a/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPhone App 60pt@2x.png b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPhone App 60pt@2x.png new file mode 100644 index 0000000..ae0e74a Binary files /dev/null and b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPhone App 60pt@2x.png differ diff --git a/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPhone App 60pt@3x.png b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPhone App 60pt@3x.png new file mode 100644 index 0000000..37c314f Binary files /dev/null and b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPhone App 60pt@3x.png differ diff --git a/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPhone Notifications 20pt@2x.png b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPhone Notifications 20pt@2x.png new file mode 100644 index 0000000..db8aa47 Binary files /dev/null and b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPhone Notifications 20pt@2x.png differ diff --git a/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPhone Notifications 20pt@3x.png b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPhone Notifications 20pt@3x.png new file mode 100644 index 0000000..5223dcf Binary files /dev/null and b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPhone Notifications 20pt@3x.png differ diff --git a/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPhone Settings 29pt@2x.png b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPhone Settings 29pt@2x.png new file mode 100644 index 0000000..cff7eb4 Binary files /dev/null and b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPhone Settings 29pt@2x.png differ diff --git a/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPhone Settings 29pt@3x.png b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPhone Settings 29pt@3x.png new file mode 100644 index 0000000..3599aaf Binary files /dev/null and b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPhone Settings 29pt@3x.png differ diff --git a/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPhone Spotlight 40pt@3x.png b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPhone Spotlight 40pt@3x.png new file mode 100644 index 0000000..ae0e74a Binary files /dev/null and b/ios/learningisfun/Images.xcassets/AppIcon.appiconset/iPhone Spotlight 40pt@3x.png differ diff --git a/ios/learningisfun/Images.xcassets/SplashScreen.imageset/App Store 1024pt 1.png b/ios/learningisfun/Images.xcassets/SplashScreen.imageset/App Store 1024pt 1.png new file mode 100644 index 0000000..15c16f9 Binary files /dev/null and b/ios/learningisfun/Images.xcassets/SplashScreen.imageset/App Store 1024pt 1.png differ diff --git a/ios/learningisfun/Images.xcassets/SplashScreen.imageset/App Store 1024pt 2.png b/ios/learningisfun/Images.xcassets/SplashScreen.imageset/App Store 1024pt 2.png new file mode 100644 index 0000000..15c16f9 Binary files /dev/null and b/ios/learningisfun/Images.xcassets/SplashScreen.imageset/App Store 1024pt 2.png differ diff --git a/ios/learningisfun/Images.xcassets/SplashScreen.imageset/App Store 1024pt.png b/ios/learningisfun/Images.xcassets/SplashScreen.imageset/App Store 1024pt.png new file mode 100644 index 0000000..15c16f9 Binary files /dev/null and b/ios/learningisfun/Images.xcassets/SplashScreen.imageset/App Store 1024pt.png differ diff --git a/ios/learningisfun/Images.xcassets/SplashScreen.imageset/Contents.json b/ios/learningisfun/Images.xcassets/SplashScreen.imageset/Contents.json index 85907f6..eda27a7 100644 --- a/ios/learningisfun/Images.xcassets/SplashScreen.imageset/Contents.json +++ b/ios/learningisfun/Images.xcassets/SplashScreen.imageset/Contents.json @@ -1,17 +1,17 @@ { "images" : [ { - "filename" : "iPad Notifications 38pt.png", + "filename" : "App Store 1024pt.png", "idiom" : "universal", "scale" : "1x" }, { - "filename" : "iPad Notifications 64pt@2x.png", + "filename" : "App Store 1024pt 1.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "iPad App 76pt@2x 1.png", + "filename" : "App Store 1024pt 2.png", "idiom" : "universal", "scale" : "3x" } diff --git a/ios/learningisfun/Info.plist b/ios/learningisfun/Info.plist index 0a2a4df..db123b9 100644 --- a/ios/learningisfun/Info.plist +++ b/ios/learningisfun/Info.plist @@ -12,6 +12,8 @@ 6.0 CFBundleName $(PRODUCT_NAME) + CBBundleDisplayName + Learn by playing CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleSignature diff --git a/ios/learningisfun/SplashScreen.storyboard b/ios/learningisfun/SplashScreen.storyboard index 24eec3d..1375e46 100644 --- a/ios/learningisfun/SplashScreen.storyboard +++ b/ios/learningisfun/SplashScreen.storyboard @@ -1,91 +1,48 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/package.json b/package.json index 20c2343..dcdaac6 100644 --- a/package.json +++ b/package.json @@ -7,9 +7,10 @@ "android": "expo run:android", "reinstall": "rm -rf node_modules/ && yarn install", "clean:android": "cd android && ./gradlew clean && cd ..", + "keystore": "cd android/app && [ ! -f learningisfun.keystore ] && keytool -genkeypair -v -storetype PKCS12 -keystore learningisfun.keystore -alias learningisfun -keyalg RSA -keysize 2048 -validity 10000 -noprompt -storepass Test@123 -keypass Test@123 -dname \"CN=Unknown, OU=james, O=james, L=São Paulo, S=São Paulo, C=BR\" || echo \"com.learningisfun\" && cd ../..", "build:ios": "react-native bundle --entry-file='index.js' --bundle-output='./ios/main.jsbundle' --dev=false --platform='ios' --assets-dest='./ios/learningisfun'", "build:apk": "cd android && ./gradlew assembleRelease && cd .. && yarn install:apk", - "build:android:production": "yarn reinstall && yarn clean:android && yarn build:apk", + "build:android:production": "yarn keystore && yarn reinstall && yarn clean:android && yarn build:apk", "ios": "expo run:ios", "web": "expo start --web", "install:apk": "adb install ./android/app/build/outputs/apk/release/app-release.apk" diff --git a/src/assets/icons/alert-circle.svg b/src/assets/icons/alert-circle.svg new file mode 100644 index 0000000..8d02b7d --- /dev/null +++ b/src/assets/icons/alert-circle.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/icons/tail.svg b/src/assets/icons/tail.svg new file mode 100644 index 0000000..1313bc4 --- /dev/null +++ b/src/assets/icons/tail.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/main/routes/enums/Routes.tsx b/src/main/routes/enums/Routes.tsx index b8025ca..a500687 100644 --- a/src/main/routes/enums/Routes.tsx +++ b/src/main/routes/enums/Routes.tsx @@ -1,4 +1,5 @@ export enum Routes { Welcome = "Welcome", Exercises = "Exercises", + Finished = "FinishedExercises", } diff --git a/src/main/routes/index.routes.tsx b/src/main/routes/index.routes.tsx index e213275..64e9672 100644 --- a/src/main/routes/index.routes.tsx +++ b/src/main/routes/index.routes.tsx @@ -8,8 +8,11 @@ import { createStackNavigator, } from "@react-navigation/stack"; import { Routes as RoutesEnum } from "./enums/Routes"; -import { ManufactureWelcomeScreen } from "../screens"; -import { ManufactureExercisesScreen } from "../screens/exercises"; +import { + ManufactureFinishedScreen, + ManufactureWelcomeScreen, + ManufactureExercisesScreen, +} from "../screens"; export const navigationRef = React.createRef>(); @@ -34,6 +37,11 @@ export const Routes: React.FC = () => { component={ManufactureExercisesScreen} options={{ headerShown: false }} /> + ); diff --git a/src/main/screens/finished/index.tsx b/src/main/screens/finished/index.tsx new file mode 100644 index 0000000..72a45ae --- /dev/null +++ b/src/main/screens/finished/index.tsx @@ -0,0 +1,4 @@ +import React from "react"; +import { Finished } from "@/presentation"; + +export const ManufactureFinishedScreen = () => ; diff --git a/src/main/screens/index.tsx b/src/main/screens/index.tsx index 9e049fc..a7904c1 100644 --- a/src/main/screens/index.tsx +++ b/src/main/screens/index.tsx @@ -1 +1,3 @@ export * from "./welcome"; +export * from "./exercises"; +export * from "./finished"; diff --git a/src/presentation/components/alert/index.tsx b/src/presentation/components/alert/index.tsx new file mode 100644 index 0000000..afdd5eb --- /dev/null +++ b/src/presentation/components/alert/index.tsx @@ -0,0 +1,16 @@ +import React from "react"; +import ErrorSVG from "@assets/icons/alert-circle.svg"; +import { Container, ErrorMessage } from "./styles"; +import { AlertProps } from "./props"; + +export const Alert: React.FC = ({ + message = "Message default", + type = "error", +}) => { + return ( + + + {message} + + ); +}; diff --git a/src/presentation/components/alert/props.tsx b/src/presentation/components/alert/props.tsx new file mode 100644 index 0000000..c5a082f --- /dev/null +++ b/src/presentation/components/alert/props.tsx @@ -0,0 +1,7 @@ +export interface AlertProps { + message?: string; + type?: "error" | "success" | "warning" | "caution"; +} +export interface AlertStyleProps { + type?: "error" | "success" | "warning" | "caution"; +} diff --git a/src/presentation/components/alert/styles.tsx b/src/presentation/components/alert/styles.tsx new file mode 100644 index 0000000..ee94ff8 --- /dev/null +++ b/src/presentation/components/alert/styles.tsx @@ -0,0 +1,24 @@ +import styled from "styled-components/native"; +import { Dimension, scale } from "@/shared/styles"; +import { AlertStyleProps } from "./props"; + +export const Container = styled.View` + flex: 1; + flex-direction: row; + overflow: hidden; + position: absolute; + bottom: ${({ theme }) => theme.moderateSize.xmLarge}; + margin: 0 ${({ theme }) => theme.moderateSize.large}; + background-color: ${({ theme }) => theme.colors.primary.red}; + border-width: 0.3px; + border-color: ${({ theme }) => theme.colors.primary.white}; + align-items: center; + padding: ${({ theme }) => theme.moderateSize.small}; + border-radius: ${({ theme }) => theme.moderateSize.small}; + width: ${Dimension.screenWidth - scale(48)}px; +`; + +export const ErrorMessage = styled.Text` + margin-left: ${({ theme }) => theme.moderateSize.medium}; + color: ${({ theme }) => theme.colors.primary.white}; +`; diff --git a/src/presentation/components/global-components/index.tsx b/src/presentation/components/global-components/index.tsx new file mode 100644 index 0000000..0672caa --- /dev/null +++ b/src/presentation/components/global-components/index.tsx @@ -0,0 +1,15 @@ +import React from "react"; +import { Alert } from "../alert"; +import { useAlert } from "@/presentation/hooks/methods/alert"; + +export const GlobalComponents: React.FC = () => { + const { alertData } = useAlert(); + + return ( + <> + {alertData?.message && ( + + )} + + ); +}; diff --git a/src/presentation/components/index.tsx b/src/presentation/components/index.tsx index 98d55ac..97b643e 100644 --- a/src/presentation/components/index.tsx +++ b/src/presentation/components/index.tsx @@ -1 +1,4 @@ export * from "./button"; +export * from "./word"; +export * from "./sentenceLine"; +export * from "./wordList"; diff --git a/src/presentation/components/sentenceLine/index.tsx b/src/presentation/components/sentenceLine/index.tsx new file mode 100644 index 0000000..24b98f1 --- /dev/null +++ b/src/presentation/components/sentenceLine/index.tsx @@ -0,0 +1,118 @@ +import React, { useState } from "react"; + +import { + SentenceToTranslate, + SpaceForSelectedWord, + SentenceTranslatedWrapper, + SentenceIsolateWordAndTooltip, + SentenceWordWrapper, + TooltipWrapper, + TooltipWord, + WrapperWordAndTooltip, + Tail, +} from "./styles"; +import { WordComponent } from "../word"; +import { SentenceLineComponentProps } from "./props"; + +export const SentenceLineComponent: React.FC = ({ + sentence, + selectedWord, + onPress, + wordsMatch, + wordToReplace, + exerciseStatus = "waiting", +}) => { + const [isPressing, setIsPressing] = useState({ isActive: false, word: "" }); + + const wordTranslated = wordsMatch?.filter( + (item) => item.origin === wordToReplace, + )?.[0]; + const beforeWordSentence = sentence + ?.split(wordTranslated?.translation!)?.[0] + .split(" "); + const afterWordSentence = sentence + ?.split(wordTranslated?.translation!)?.[1] + ?.split(" "); + + const handleMatchStrings = (str1: string, str2: string) => { + return ( + str1.toLowerCase().replace(",", "") === + str2.toLowerCase().replace(",", "") + ); + }; + + return ( + <> + + {beforeWordSentence + ?.filter((item) => item !== "") + ?.map((word, index) => { + const toolTipWord = wordsMatch?.filter((item) => + handleMatchStrings(item.translation, word), + )?.[0]?.origin; + const active = isPressing.word === toolTipWord; + return ( + + + {toolTipWord} + + + { + setIsPressing({ isActive: true, word: toolTipWord! }); + }} + onPressOut={() => + setIsPressing({ isActive: false, word: "" }) + } + > + + {word} + + + + ); + })} + + {selectedWord && ( + + )} + + {afterWordSentence + ?.filter((item) => item !== "") + ?.map((word, index) => { + const toolTipWord = wordsMatch?.filter((item) => + handleMatchStrings(item.translation, word), + )?.[0]?.origin; + const active = isPressing.word === toolTipWord; + + return ( + + + {toolTipWord} + + + { + setIsPressing({ isActive: true, word: toolTipWord! }); + }} + onPressOut={() => + setIsPressing({ isActive: false, word: "" }) + } + > + + {word} + + + + ); + })} + + + ); +}; diff --git a/src/presentation/components/sentenceLine/props.tsx b/src/presentation/components/sentenceLine/props.tsx new file mode 100644 index 0000000..82fbe44 --- /dev/null +++ b/src/presentation/components/sentenceLine/props.tsx @@ -0,0 +1,10 @@ +import { ViewProps } from "react-native"; + +export interface SentenceLineComponentProps extends ViewProps { + sentence?: string; + wordToReplace?: string; + wordsMatch?: { origin: string; translation: string }[]; + onPress: () => void; + selectedWord?: string; + exerciseStatus?: "waiting" | "disabled" | "contrast" | "active" | "error"; +} diff --git a/src/presentation/components/sentenceLine/styles.tsx b/src/presentation/components/sentenceLine/styles.tsx new file mode 100644 index 0000000..6cdfac4 --- /dev/null +++ b/src/presentation/components/sentenceLine/styles.tsx @@ -0,0 +1,92 @@ +import { scale } from "@/shared/styles"; +import styled, { css } from "styled-components/native"; +import TailSVG from "@assets/icons/tail.svg"; +export const SentenceIsolateWordAndTooltip = styled.TouchableOpacity` + overflow: hidden; +`; + +export const SentenceTranslatedWrapper = styled.View` + flex-direction: row; +`; + +export const WrapperWordAndTooltip = styled.View` + align-items: center; + margin-top: ${({ theme }) => theme.moderateSize.small}; +`; + +export const SentenceWordWrapper = styled.View.attrs({ + style: { + borderStyle: "dotted", + borderRadius: 1, + borderWidth: 1, + }, +})` + border-style: dotted; + border-width: 2px; + border-color: ${({ theme }) => theme.colors.primary.blue}; + margin: -${scale(2)}px; + margin-bottom: 0; + align-items: center; +`; + +export const TooltipWrapper = styled.View<{ active: boolean }>` + ${({ theme }) => css` + max-height: ${({ theme }) => theme.moderateSize.xxLarge}; + border-radius: ${theme.moderateSize.regular}; + margin-bottom: ${({ theme }) => theme.moderateSize.medium}; + align-items: center; + background-color: ${theme.colors.primary.white}; + `} +`; + +export const TooltipWord = styled.Text<{ active: boolean }>` + ${({ theme }) => css` + padding: ${theme.moderateSize.small} ${theme.moderateSize.regular}; + ${theme.text.inter.medium} + color: ${theme.colors.primary.blue}; + font-size: ${theme.moderateSize.xRegular}; + `} + + ${({ active, theme }) => + !active && + css` + background-color: ${theme.colors.primary.blueDark}; + color: ${theme.colors.primary.blueDark}; + `} +`; + +export const Tail = styled(TailSVG).attrs<{ active: boolean }>( + ({ theme, active }) => ({ + fill: active ? theme.colors.primary.white : theme.colors.primary.blueDark, + }), +)<{ active: boolean }>` + position: absolute; + bottom: -10px; +`; + +export const SentenceToTranslate = styled.Text` + ${({ theme }) => css` + ${theme.text.inter.medium} + color: ${theme.colors.primary.white}; + font-size: ${theme.moderateSize.xMedium}; + line-height: ${theme.moderateSize.large}; + `} +`; + +export const SpaceForSelectedWord = styled.TouchableOpacity<{ + selected: boolean; +}>` + ${({ theme, selected }) => css` + border-bottom-color: ${theme.colors.primary.white}; + width: ${theme.moderateSize.xmLarge}; + border-bottom-width: ${selected ? 0 : 1}px; + justify-content: flex-end; + `} + + ${({ selected }) => + selected && + css` + margin-bottom: -${scale(8)}px; + width: auto; + `} +`; diff --git a/src/presentation/components/word/index.tsx b/src/presentation/components/word/index.tsx new file mode 100644 index 0000000..2b472ae --- /dev/null +++ b/src/presentation/components/word/index.tsx @@ -0,0 +1,28 @@ +import React from "react"; + +import { WordButton, Word, WordTitle } from "./styles"; +import { WordComponentProps } from "./props"; + +export const WordComponent: React.FC = ({ + selected, + word, + type = "primary", + styleType = "waiting", + ...rest +}) => { + return ( + + + + {word} + + + + ); +}; diff --git a/src/presentation/components/word/props.tsx b/src/presentation/components/word/props.tsx new file mode 100644 index 0000000..19a8ee3 --- /dev/null +++ b/src/presentation/components/word/props.tsx @@ -0,0 +1,14 @@ +import { TouchableOpacityProps } from "react-native"; + +export interface WordComponentProps extends TouchableOpacityProps { + selected: boolean; + word: string; + type?: "primary" | "secondary" | "disabled"; + styleType?: "waiting" | "disabled" | "contrast" | "active" | "error"; +} + +export interface WordComponentStyleProps { + type: "primary" | "secondary" | "disabled"; + selected: boolean; + styleType: "waiting" | "disabled" | "contrast" | "active" | "error"; +} diff --git a/src/presentation/components/word/styles.tsx b/src/presentation/components/word/styles.tsx new file mode 100644 index 0000000..d4306a7 --- /dev/null +++ b/src/presentation/components/word/styles.tsx @@ -0,0 +1,88 @@ +import { scale } from "@/shared/styles"; +import styled, { css } from "styled-components/native"; +import { WordComponentStyleProps } from "./props"; + +export const Word = styled.View.attrs({ + //@ts-expect-error + shadowColor: "rgb(0, 0, 0)", + shadowOffset: { + width: 0, + height: 5, + }, + shadowOpacity: 0.53, + shadowRadius: 5.97, + elevation: 21, +})` + ${({ theme, selected }) => css` + height: ${scale(43)}px; + background-color: ${selected + ? theme.colors.button.disabled + : theme.colors.primary.white}; + align-items: center; + justify-content: center; + padding: ${theme.moderateSize.regular} ${theme.moderateSize.medium}; + margin-right: ${theme.moderateSize.medium}; + border-radius: ${theme.moderateSize.medium}; + `} + + ${({ type }) => + type === "secondary" && + css` + margin-right: 0; + `} + + ${({ theme, type }) => + type === "disabled" && + css` + background-color: ${theme.colors.button.disabled}; + `} + + ${({ theme, styleType }) => + styleType === "error" && + css` + background-color: ${theme.colors.primary.red}; + `} + + ${({ theme, styleType }) => + styleType === "contrast" && + css` + background-color: ${theme.colors.primary.blueLight}; + `} +`; + +export const WordButton = styled.TouchableOpacity.attrs({ + activeOpacity: 0.7, +})` + height: ${scale(43)}px; + margin-bottom: ${({ theme }) => theme.moderateSize.medium}; + + ${({ type }) => + type === "secondary" && + css` + margin-bottom: 0; + `} +`; + +export const WordTitle = styled.Text` + ${({ theme, selected }) => css` + ${theme.text.inter.semiBold} + color: ${selected ? "transparent" : theme.colors.primary.blueDark}; + font-size: ${theme.moderateSize.xRegular}; + `} + + ${({ theme, type }) => + type === "disabled" && + css` + color: ${theme.colors.text.disabled}; + `} + ${({ theme, styleType }) => + styleType === "error" && + css` + color: ${theme.colors.primary.white}; + `} + ${({ theme, styleType }) => + styleType === "contrast" && + css` + color: ${theme.colors.primary.white}; + `} +`; diff --git a/src/presentation/components/wordList/index.tsx b/src/presentation/components/wordList/index.tsx new file mode 100644 index 0000000..928130a --- /dev/null +++ b/src/presentation/components/wordList/index.tsx @@ -0,0 +1,30 @@ +import React from "react"; + +import { WordListComponentProps } from "./props"; +import { Words } from "./styles"; +import { WordComponent } from "../word"; + +export const WordListComponent: React.FC = ({ + exercise, + type, + setSelectedWord, + selectedWord, + setCurrentStatus, +}) => { + return ( + + {exercise?.answerOptions?.map((item, index) => ( + { + setSelectedWord(item); + setCurrentStatus("active"); + }} + word={item} + selected={selectedWord === item} + type={type} + /> + ))} + + ); +}; diff --git a/src/presentation/components/wordList/props.tsx b/src/presentation/components/wordList/props.tsx new file mode 100644 index 0000000..9267cee --- /dev/null +++ b/src/presentation/components/wordList/props.tsx @@ -0,0 +1,13 @@ +import { ISentencesModel } from "@/domain"; + +export interface WordListComponentProps { + exercise: ISentencesModel; + setSelectedWord: (value: React.SetStateAction) => void; + setCurrentStatus: React.Dispatch< + React.SetStateAction< + "waiting" | "disabled" | "contrast" | "active" | "error" | undefined + > + >; + selectedWord?: string; + type?: "disabled" | "primary" | "secondary"; +} diff --git a/src/presentation/components/wordList/styles.tsx b/src/presentation/components/wordList/styles.tsx new file mode 100644 index 0000000..d534d81 --- /dev/null +++ b/src/presentation/components/wordList/styles.tsx @@ -0,0 +1,10 @@ +import styled from "styled-components/native"; + +export const Words = styled.View` + flex: 1; + flex-direction: row; + flex-wrap: wrap; + margin-top: ${({ theme }) => theme.moderateSize.largest}; + padding: 0 ${({ theme }) => theme.moderateSize.xmLarge}; + justify-content: center; +`; diff --git a/src/presentation/hooks/methods/alert/index.tsx b/src/presentation/hooks/methods/alert/index.tsx new file mode 100644 index 0000000..172fa15 --- /dev/null +++ b/src/presentation/hooks/methods/alert/index.tsx @@ -0,0 +1,44 @@ +import React, { createContext, useCallback, useContext, useState } from "react"; + +import { GlobalAlert, ContextData, ContextAlertProps } from "./props"; + +const AlertContext = createContext({} as ContextData); + +const AlertProvider: React.FC = ({ + children, +}: ContextAlertProps) => { + const [alertData, setAlertData] = useState({} as GlobalAlert); + + const alert = useCallback((data: GlobalAlert) => { + setAlertData(data); + setTimeout(() => { + setAlertData({}); + }, 5000); + }, []); + + const dismiss = useCallback(() => setAlertData({}), []); + + return ( + + {children} + + ); +}; + +function useAlert(): ContextData { + const context = useContext(AlertContext); + + if (!context) { + throw new Error("useAlert must be used within an AlertProvider."); + } + + return context; +} + +export { AlertProvider, useAlert }; diff --git a/src/presentation/hooks/methods/alert/props.tsx b/src/presentation/hooks/methods/alert/props.tsx new file mode 100644 index 0000000..74ed893 --- /dev/null +++ b/src/presentation/hooks/methods/alert/props.tsx @@ -0,0 +1,14 @@ +export type ContextData = { + alertData: GlobalAlert; + alert(alertData: GlobalAlert): void; + dismiss(): void; +}; + +export type GlobalAlert = { + type?: "error" | "success" | "warning" | "caution"; + message?: string; +}; + +export type ContextAlertProps = { + children: React.ReactNode; +}; diff --git a/src/presentation/hooks/providers/index.tsx b/src/presentation/hooks/providers/index.tsx index 99fbc5d..1311f2d 100644 --- a/src/presentation/hooks/providers/index.tsx +++ b/src/presentation/hooks/providers/index.tsx @@ -2,6 +2,8 @@ import React from "react"; import { AppThemeProvider } from "./theme"; import { NavigationProvider } from "./navigation"; import { ExercisesProvider } from "./exercises"; +import { AlertProvider } from "../methods/alert"; +import { GlobalComponents } from "@/presentation/components/global-components"; interface ApplicationContextProviderManagementProps { children: React.ReactNode; @@ -12,9 +14,16 @@ export const ApplicationContextProviderManagement: React.FC< > = ({ children }) => { return ( - - {children} - + + + + <> + {children} + + + + + ); }; diff --git a/src/presentation/jsx/exercises/index.tsx b/src/presentation/jsx/exercises/index.tsx index 362993a..afacaf1 100644 --- a/src/presentation/jsx/exercises/index.tsx +++ b/src/presentation/jsx/exercises/index.tsx @@ -1,5 +1,16 @@ -import React, { useEffect, useState } from "react"; +import React, { useEffect, useMemo, useState } from "react"; +import { ActivityIndicator } from "react-native"; +import { useNavigation, useRoute } from "@react-navigation/native"; +import { useSharedValue } from "react-native-reanimated"; +import FlagSvg from "@assets/icons/flag.svg"; +import { useExercices } from "@/presentation/hooks"; +import { ButtonComponentProps } from "@/presentation/components/button/props"; +import { + SentenceLineComponent, + WordComponent, + WordListComponent, +} from "@/presentation/components"; import { ButtonFeedbackContainer, Container, @@ -8,32 +19,29 @@ import { FocusedWord, HowToPlay, MainSentence, - SentenceToTranslate, - SentenceTranslatedWrapper, - SpaceForSelectedWord, Status, - Word, - WordButton, - WordTitle, Words, Wrapper, } from "./styles"; -import { useRoute } from "@react-navigation/native"; import { ButtonTitle, ExercisesRoutesProps } from "./props"; -import { useExercices } from "@/presentation/hooks"; -import { ActivityIndicator } from "react-native"; -import FlagSvg from "@assets/icons/flag.svg"; -import { ButtonComponentProps } from "@/presentation/components/button/props"; +import { useAlert } from "@/presentation/hooks/methods/alert"; +import { Routes } from "@/main"; + export const ExercisesScreen = () => { const params = useRoute().params as ExercisesRoutesProps; + const { alert } = useAlert(); + const { goBack, navigate } = useNavigation(); const [isLoading, setIsLoading] = useState(true); const [currentPosition, setCurrentPosition] = useState(0); const { sentences, handleGetSentences } = useExercices(); - const exercise = sentences?.at(currentPosition); const [selectedWord, setSelectedWord] = useState(); const [currentStatus, setCurrentStatus] = useState("waiting"); + const exercise = useMemo(() => { + return sentences?.at(currentPosition); + }, [currentPosition, sentences]); + const handleFetchSentences = async () => { try { await handleGetSentences({ @@ -41,6 +49,8 @@ export const ExercisesScreen = () => { translation: params.translation, }); } catch (error) { + alert({ message: "We can't find any exercises.", type: "error" }); + goBack(); setIsLoading(false); } finally { setIsLoading(false); @@ -59,53 +69,19 @@ export const ExercisesScreen = () => { ); }; - const renderWords = () => { - return ( - - {exercise?.answerOptions?.map((item) => ( - { - setSelectedWord(item); - setCurrentStatus("active"); - }} - > - - {item} - - - ))} - - ); - }; - const renderSentenceTranslated = () => { - const wordTranslated = exercise?.wordsMatch.filter( - (item) => item.origin === exercise.choosedWord, - )?.[0]?.translation; - - const sentenceSplited = exercise?.sentenceTranslated?.split( - wordTranslated!, - )!; - return ( - - {sentenceSplited?.[0]} - { - setSelectedWord(undefined); - setCurrentStatus("waiting"); - }} - > - {selectedWord && ( - - {selectedWord} - - )} - - {sentenceSplited?.[1]} - + { + setSelectedWord(undefined); + setCurrentStatus("waiting"); + }} + selectedWord={selectedWord} + exerciseStatus={currentStatus} + /> ); }; @@ -115,7 +91,7 @@ export const ExercisesScreen = () => { )?.[0]?.translation; try { if (!selectedWord) { - return; + throw new Error("Word not selected"); } if (currentStatus === "active") { if (selectedWord === wordTranslated) { @@ -126,7 +102,8 @@ export const ExercisesScreen = () => { } else { setCurrentPosition((prevState) => { if (sentences?.length && sentences.length <= prevState + 1) { - return 0; + navigate(Routes.Finished); + return prevState; } else { return prevState + 1; } @@ -134,7 +111,9 @@ export const ExercisesScreen = () => { setSelectedWord(undefined); setCurrentStatus("waiting"); } - } catch (error) {} + } catch (error) { + alert({ message: "Choose a word to continue.", type: "error" }); + } }; useEffect(() => { @@ -151,7 +130,17 @@ export const ExercisesScreen = () => { <> {renderMainSentence()} {renderSentenceTranslated()} - {renderWords()} + )} diff --git a/src/presentation/jsx/exercises/styles.tsx b/src/presentation/jsx/exercises/styles.tsx index 8736d10..efb0802 100644 --- a/src/presentation/jsx/exercises/styles.tsx +++ b/src/presentation/jsx/exercises/styles.tsx @@ -42,33 +42,10 @@ export const FocusedWord = styled.Text` text-decoration-color: ${({ theme }) => theme.colors.primary.white}; `; -export const SentenceTranslatedWrapper = styled.View` - flex-direction: row; -`; - export const Hint = styled.View``; export const HintText = styled.Text``; -export const SentenceToTranslate = styled.Text` - ${({ theme }) => theme.text.inter.medium} - margin-top: ${({ theme }) => theme.moderateSize.xmLarge}; - color: ${({ theme }) => theme.colors.primary.white}; - font-size: ${({ theme }) => theme.moderateSize.xMedium}; -`; - -export const SpaceForSelectedWord = styled.TouchableOpacity<{ - selected: boolean; -}>` - border-bottom-color: ${({ theme }) => theme.colors.primary.white}; - width: ${({ theme, selected }) => - selected ? undefined : theme.moderateSize.xmLarge}; - border-bottom-width: ${({ selected }) => (selected ? 0 : 1)}px; - margin: 0 ${({ theme }) => theme.moderateSize.small}; - justify-content: flex-end; - margin-bottom: -${({ selected }) => (selected ? scale(8) : 0)}px; -`; - export const Words = styled.View` flex: 1; flex-direction: row; @@ -78,44 +55,6 @@ export const Words = styled.View` justify-content: center; `; -export const Word = styled.View.attrs({ - shadowColor: "rgb(0, 0, 0)", - shadowOffset: { - width: 0, - height: 5, - }, - shadowOpacity: 0.53, - shadowRadius: 5.97, - elevation: 21, -})<{ selected: boolean }>` - ${({ theme, selected }) => css` - height: ${scale(43)}px; - background-color: ${selected - ? theme.colors.button.disabled - : theme.colors.primary.white}; - align-items: center; - justify-content: center; - padding: ${theme.moderateSize.regular} ${theme.moderateSize.medium}; - margin-right: ${theme.moderateSize.medium}; - border-radius: ${theme.moderateSize.medium}; - `} -`; - -export const WordButton = styled.TouchableOpacity.attrs({ - activeOpacity: 0.7, -})` - height: ${scale(43)}px; - margin-bottom: ${({ theme }) => theme.moderateSize.medium}; -`; - -export const WordTitle = styled.Text<{ selected: boolean }>` - ${({ theme, selected }) => css` - ${theme.text.inter.semiBold} - color: ${selected ? "transparent" : theme.colors.primary.blueDark}; - font-size: ${theme.moderateSize.xRegular}; - `} -`; - export const Continue = styled(ButtonComponent).attrs(({ theme }) => ({ elements: { buttonContainer: { diff --git a/src/presentation/jsx/finished/index.tsx b/src/presentation/jsx/finished/index.tsx new file mode 100644 index 0000000..4b54b81 --- /dev/null +++ b/src/presentation/jsx/finished/index.tsx @@ -0,0 +1,20 @@ +import React, { useEffect } from "react"; + +import { Container, FinishedText } from "./styles"; +import { useNavigation } from "@react-navigation/native"; +import { Routes } from "@/main"; + +export const Finished = () => { + const { navigate } = useNavigation(); + useEffect(() => { + setTimeout(() => { + navigate(Routes.Welcome); + }, 3000); + }, []); + + return ( + + Congrats!{"\n"}You finished your exercises. + + ); +}; diff --git a/src/presentation/jsx/finished/styles.tsx b/src/presentation/jsx/finished/styles.tsx new file mode 100644 index 0000000..8b2f197 --- /dev/null +++ b/src/presentation/jsx/finished/styles.tsx @@ -0,0 +1,17 @@ +import styled, { css } from "styled-components/native"; + +export const Container = styled.View` + flex: 1; + background-color: ${({ theme }) => theme.colors.primary.green}; + flex-direction: column-reverse; + padding: ${({ theme }) => theme.moderateSize.large}; +`; + +export const FinishedText = styled.Text` + ${({ theme }) => css` + ${theme.text.inter.bold} + color: ${theme.colors.text.active}; + font-size: ${theme.moderateSize.xLarge}; + margin-bottom: ${({ theme }) => theme.moderateSize.largest}; + `} +`; diff --git a/src/presentation/jsx/index.tsx b/src/presentation/jsx/index.tsx index 63983cd..a7904c1 100644 --- a/src/presentation/jsx/index.tsx +++ b/src/presentation/jsx/index.tsx @@ -1,2 +1,3 @@ export * from "./welcome"; export * from "./exercises"; +export * from "./finished"; diff --git a/src/shared/styles/colors.ts b/src/shared/styles/colors.ts index c00a341..3ce4769 100644 --- a/src/shared/styles/colors.ts +++ b/src/shared/styles/colors.ts @@ -7,6 +7,7 @@ export const Colors = { blue: "#2B4B5D", white: "#FFFFFF", title: "#EFEFEF", + green: "#63A66A", }, button: { active: "#16E3E7", @@ -19,7 +20,7 @@ export const Colors = { active: "#FFFFFF", contrast: "#00E1E8", waiting: "#FFFFFF", - disabled: "#FF7C89", + disabled: "#668191", error: "#FF7C89", }, };