diff --git a/README.md b/README.md index d4ef8d5d..be132860 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,27 @@ -[![CodeQL](https://github.com/neuland-ingolstadt/neuland.app-native/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/neuland-ingolstadt/neuland.app-native/actions/workflows/codeql-analysis.yml) +[![CodeQL](https://github.com/neuland-ingolstadt/neuland.app-native/actions/workflows/codeql.yml/badge.svg)](https://github.com/neuland-ingolstadt/neuland.app-native/actions/workflows/codeql.yml) [![CI](https://github.com/neuland-ingolstadt/neuland.app-native/actions/workflows/lint.yml/badge.svg)](https://github.com/neuland-ingolstadt/neuland.app-native/actions/workflows/lint.yml) # Neuland Next - native version of neuland.app -An open source, mobile app developed using React Native and Expo, serving as a replacement for the official Technische Hochschule Ingolstadt (THI) app. +An open source, mobile app developed using React Native, serving as a replacement for the official Technische Hochschule Ingolstadt (THI) app. It features a modern user interface and utilizes the Expo framework for easy development and deployment. +## Beta Testing + +Click on the link below to join the beta testing of the app: + +- iOS: [TestFlight](https://testflight.apple.com/join/PABWZys2) +- Android: [Google Play](https://play.google.com/store/apps/details?id=app.neuland) + +> [!IMPORTANT] +> Please let us know about any bugs and send us ideas for improvement so that we can improve the app. + ## About ### App The app aims at implementing all important features of the official app as free and open source software with a modern UI and native features. -To achieve this, the existing React backend is adapted and the API of the neuland.app is used. +To achieve this, the existing React backend was adapted and the Neuland GraphQL API was created. ### Contributing @@ -20,7 +30,4 @@ Check out the [contributing guidelines](.github/CONTRIBUTING.md) to get started. ### Current State -> **Warning** -> The app is in early development and not yet publicly available. - -We are currently doing an internal alpha test with the goal of releasing the app for iOS and Android later this year. +The app is in development and not yet publicly available. diff --git a/android/app/build.gradle b/android/app/build.gradle index 43b48ee8..8e193ebc 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -88,8 +88,8 @@ android { applicationId 'app.neuland' minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 138 - versionName "0.8.3" + versionCode 145 + versionName "0.9.0" } signingConfigs { debug { diff --git a/app.config.json b/app.config.json index f746335f..deef019f 100644 --- a/app.config.json +++ b/app.config.json @@ -10,7 +10,7 @@ "userInterfaceStyle": "automatic", "ios": { "bundleIdentifier": "de.neuland-ingolstadt.neuland-app", - "buildNumber": "71", + "buildNumber": "82", "supportsTablet": true, "userInterfaceStyle": "automatic", "associatedDomains": [ @@ -49,7 +49,7 @@ "android": { "package": "app.neuland", "userInterfaceStyle": "automatic", - "versionCode": 138, + "versionCode": 145, "splash": { "image": "./src/assets/splash/splashLight.png", "resizeMode": "contain", diff --git a/bun.lockb b/bun.lockb index 90f1e447..9c7ea3e0 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/ios/NeulandNext.xcodeproj/project.pbxproj b/ios/NeulandNext.xcodeproj/project.pbxproj index 6c31308a..3d19177f 100644 --- a/ios/NeulandNext.xcodeproj/project.pbxproj +++ b/ios/NeulandNext.xcodeproj/project.pbxproj @@ -13,7 +13,7 @@ 3E461D99554A48A4959DE609 /* SplashScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */; }; 5EA579CB98A042F5873E8D2B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 15D289C40A50492AA788F5C8 /* InfoPlist.strings */; }; 79A805BC94BC0AD1674AEE08 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 2DE9A45D19FFF21A2FC7974A /* PrivacyInfo.xcprivacy */; }; - 8F67CB1D1CD0F80933516397 /* libPods-NeulandNext.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DF16343C6EDDD0DDB9165116 /* libPods-NeulandNext.a */; }; + 9CBC5675703C8414204AE0D6 /* libPods-NeulandNext.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 2A55F8206E720C1FFA673054 /* libPods-NeulandNext.a */; }; B18059E884C0ABDD17F3DC3D /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */; }; B7E3797A2C54A52E006A4193 /* MapLibre in Frameworks */ = {isa = PBXBuildFile; productRef = EC742494CB1CE25F860AF0D3 /* MapLibre */; }; BB2F792D24A3F905000567C9 /* Expo.plist in Resources */ = {isa = PBXBuildFile; fileRef = BB2F792C24A3F905000567C9 /* Expo.plist */; }; @@ -29,16 +29,16 @@ 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = NeulandNext/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = NeulandNext/main.m; sourceTree = ""; }; 15D289C40A50492AA788F5C8 /* InfoPlist.strings */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = text.plist.strings; name = InfoPlist.strings; path = "de-DE.lproj/InfoPlist.strings"; sourceTree = ""; }; + 18640A5779FCF601B7624EA6 /* Pods-NeulandNext.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NeulandNext.debug.xcconfig"; path = "Target Support Files/Pods-NeulandNext/Pods-NeulandNext.debug.xcconfig"; sourceTree = ""; }; + 2A55F8206E720C1FFA673054 /* libPods-NeulandNext.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-NeulandNext.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 2D4A762513EF4F1B924A16CC /* noop-file.swift */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.swift; name = "noop-file.swift"; path = "NeulandNext/noop-file.swift"; sourceTree = ""; }; 2DE9A45D19FFF21A2FC7974A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = NeulandNext/PrivacyInfo.xcprivacy; sourceTree = ""; }; 4F50E0A33A0E4558A8B767F1 /* NeulandNext-Bridging-Header.h */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = sourcecode.c.h; name = "NeulandNext-Bridging-Header.h"; path = "NeulandNext/NeulandNext-Bridging-Header.h"; sourceTree = ""; }; - 83AB1D9E2FAA015F64BDF1B1 /* Pods-NeulandNext.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NeulandNext.release.xcconfig"; path = "Target Support Files/Pods-NeulandNext/Pods-NeulandNext.release.xcconfig"; sourceTree = ""; }; AA286B85B6C04FC6940260E9 /* SplashScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = SplashScreen.storyboard; path = NeulandNext/SplashScreen.storyboard; sourceTree = ""; }; AF143DA9DAE546BAA252E633 /* InfoPlist.strings */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 4; includeInIndex = 0; lastKnownFileType = text.plist.strings; name = InfoPlist.strings; path = "en-US.lproj/InfoPlist.strings"; sourceTree = ""; }; B7A252912C646BAE009CD149 /* NeulandNextRelease.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = NeulandNextRelease.entitlements; path = NeulandNext/NeulandNextRelease.entitlements; sourceTree = ""; }; BB2F792C24A3F905000567C9 /* Expo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Expo.plist; sourceTree = ""; }; - CA782F3247ED429475C0817A /* Pods-NeulandNext.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NeulandNext.debug.xcconfig"; path = "Target Support Files/Pods-NeulandNext/Pods-NeulandNext.debug.xcconfig"; sourceTree = ""; }; - DF16343C6EDDD0DDB9165116 /* libPods-NeulandNext.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-NeulandNext.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + ECA138895E66620CAA8C8A6F /* Pods-NeulandNext.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NeulandNext.release.xcconfig"; path = "Target Support Files/Pods-NeulandNext/Pods-NeulandNext.release.xcconfig"; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; FAC715A2D49A985799AEE119 /* ExpoModulesProvider.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ExpoModulesProvider.swift; path = "Pods/Target Support Files/Pods-NeulandNext/ExpoModulesProvider.swift"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -49,7 +49,7 @@ buildActionMask = 2147483647; files = ( B7E3797A2C54A52E006A4193 /* MapLibre in Frameworks */, - 8F67CB1D1CD0F80933516397 /* libPods-NeulandNext.a in Frameworks */, + 9CBC5675703C8414204AE0D6 /* libPods-NeulandNext.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -78,7 +78,7 @@ isa = PBXGroup; children = ( ED297162215061F000B7C4FE /* JavaScriptCore.framework */, - DF16343C6EDDD0DDB9165116 /* libPods-NeulandNext.a */, + 2A55F8206E720C1FFA673054 /* libPods-NeulandNext.a */, ); name = Frameworks; sourceTree = ""; @@ -143,8 +143,8 @@ D65327D7A22EEC0BE12398D9 /* Pods */ = { isa = PBXGroup; children = ( - CA782F3247ED429475C0817A /* Pods-NeulandNext.debug.xcconfig */, - 83AB1D9E2FAA015F64BDF1B1 /* Pods-NeulandNext.release.xcconfig */, + 18640A5779FCF601B7624EA6 /* Pods-NeulandNext.debug.xcconfig */, + ECA138895E66620CAA8C8A6F /* Pods-NeulandNext.release.xcconfig */, ); path = Pods; sourceTree = ""; @@ -172,16 +172,15 @@ isa = PBXNativeTarget; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "NeulandNext" */; buildPhases = ( - FEE37F9A8B5F91F5E82374E8 /* [CP] Check Pods Manifest.lock */, + 6B4CBBE1BB9EC5DA17456302 /* [CP] Check Pods Manifest.lock */, 910811D19BBBDAE542453C80 /* [Expo] Configure project */, 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, - B5D7FBC2AB8C412844A0CF8B /* [CP] Embed Pods Frameworks */, - AA761E64C35603CEBB2FA769 /* [CP] Copy Pods Resources */, - C6874FEF2F234D4A988A9C56 /* Remove signature files (Xcode 15 workaround) */, - FC608338A6A74B469AA88597 /* Remove signature files (Xcode 15 workaround) */, + EBB7C3317B6D4599B5A27BB5 /* Remove signature files (Xcode 15 workaround) */, + DFB20D84C6934C71E5F3D6AB /* [CP] Embed Pods Frameworks */, + CB7B13BCD03CEF4A250FB35D /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -261,6 +260,28 @@ shellPath = /bin/sh; shellScript = "if [[ -f \"$PODS_ROOT/../.xcode.env\" ]]; then\n source \"$PODS_ROOT/../.xcode.env\"\nfi\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n# The project root by default is one level up from the ios directory\nexport PROJECT_ROOT=\"$PROJECT_DIR\"/..\n\nif [[ \"$CONFIGURATION\" = *Debug* ]]; then\n export SKIP_BUNDLING=1\nfi\nif [[ -z \"$ENTRY_FILE\" ]]; then\n # Set the entry JS file using the bundler's entry resolution.\n export ENTRY_FILE=\"$(\"$NODE_BINARY\" -e \"require('expo/scripts/resolveAppEntry')\" \"$PROJECT_ROOT\" ios absolute | tail -n 1)\"\nfi\n\nif [[ -z \"$CLI_PATH\" ]]; then\n # Use Expo CLI\n export CLI_PATH=\"$(\"$NODE_BINARY\" --print \"require.resolve('@expo/cli', { paths: [require.resolve('expo/package.json')] })\")\"\nfi\nif [[ -z \"$BUNDLE_COMMAND\" ]]; then\n # Default Expo CLI command for bundling\n export BUNDLE_COMMAND=\"export:embed\"\nfi\n\n# Source .xcode.env.updates if it exists to allow\n# SKIP_BUNDLING to be unset if needed\nif [[ -f \"$PODS_ROOT/../.xcode.env.updates\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.updates\"\nfi\n# Source local changes to allow overrides\n# if needed\nif [[ -f \"$PODS_ROOT/../.xcode.env.local\" ]]; then\n source \"$PODS_ROOT/../.xcode.env.local\"\nfi\n\n`\"$NODE_BINARY\" --print \"require('path').dirname(require.resolve('react-native/package.json')) + '/scripts/react-native-xcode.sh'\"`\n\n"; }; + 6B4CBBE1BB9EC5DA17456302 /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-NeulandNext-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; + }; 910811D19BBBDAE542453C80 /* [Expo] Configure project */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -280,7 +301,7 @@ shellPath = /bin/sh; shellScript = "# This script configures Expo modules and generates the modules provider file.\nbash -l -c \"./Pods/Target\\ Support\\ Files/Pods-NeulandNext/expo-configure-project.sh\"\n"; }; - AA761E64C35603CEBB2FA769 /* [CP] Copy Pods Resources */ = { + CB7B13BCD03CEF4A250FB35D /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -316,7 +337,7 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NeulandNext/Pods-NeulandNext-resources.sh\"\n"; showEnvVarsInLog = 0; }; - B5D7FBC2AB8C412844A0CF8B /* [CP] Embed Pods Frameworks */ = { + DFB20D84C6934C71E5F3D6AB /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -334,21 +355,7 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NeulandNext/Pods-NeulandNext-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - C6874FEF2F234D4A988A9C56 /* Remove signature files (Xcode 15 workaround) */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Remove signature files (Xcode 15 workaround)"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "if [ \"$XCODE_VERSION_MAJOR\" = \"1500\" ]; then\n echo \"Remove signature files (Xcode 15 workaround)\";\n rm -rf \"$CONFIGURATION_BUILD_DIR/MapLibre.xcframework-ios.signature\";\n fi\n"; - }; - FC608338A6A74B469AA88597 /* Remove signature files (Xcode 15 workaround) */ = { + EBB7C3317B6D4599B5A27BB5 /* Remove signature files (Xcode 15 workaround) */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -362,28 +369,6 @@ shellPath = /bin/sh; shellScript = "if [ \"$XCODE_VERSION_MAJOR\" = \"1500\" ]; then\n echo \"Remove signature files (Xcode 15 workaround)\";\n rm -rf \"$CONFIGURATION_BUILD_DIR/MapLibre.xcframework-ios.signature\";\n fi"; }; - FEE37F9A8B5F91F5E82374E8 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-NeulandNext-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; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -403,7 +388,7 @@ /* Begin XCBuildConfiguration section */ 13B07F941A680F5B00A75B9A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = CA782F3247ED429475C0817A /* Pods-NeulandNext.debug.xcconfig */; + baseConfigurationReference = 18640A5779FCF601B7624EA6 /* Pods-NeulandNext.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES; @@ -411,7 +396,7 @@ CODE_SIGN_ENTITLEMENTS = NeulandNext/NeulandNext.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 82; DEVELOPMENT_TEAM = FSXB76X6V2; ENABLE_BITCODE = NO; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -449,7 +434,7 @@ }; 13B07F951A680F5B00A75B9A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 83AB1D9E2FAA015F64BDF1B1 /* Pods-NeulandNext.release.xcconfig */; + baseConfigurationReference = ECA138895E66620CAA8C8A6F /* Pods-NeulandNext.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES; @@ -457,7 +442,7 @@ CODE_SIGN_ENTITLEMENTS = NeulandNext/NeulandNextRelease.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 82; DEVELOPMENT_TEAM = FSXB76X6V2; ENABLE_BITCODE = NO; "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = arm64; @@ -549,10 +534,7 @@ LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\""; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; - OTHER_LDFLAGS = ( - "$(inherited)", - " ", - ); + OTHER_LDFLAGS = "$(inherited) "; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; USE_HERMES = true; @@ -611,10 +593,7 @@ ); LIBRARY_SEARCH_PATHS = "$(SDKROOT)/usr/lib/swift\"$(inherited)\""; MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ( - "$(inherited)", - " ", - ); + OTHER_LDFLAGS = "$(inherited) "; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; USE_HERMES = true; diff --git a/ios/NeulandNext/Info.plist b/ios/NeulandNext/Info.plist index 07b27194..cb432f58 100644 --- a/ios/NeulandNext/Info.plist +++ b/ios/NeulandNext/Info.plist @@ -129,6 +129,8 @@ $(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route $(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route $(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route + $(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route + $(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route RCTAsyncStorageExcludeFromBackup diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 9bdf28ff..680ed0fe 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -10,18 +10,18 @@ PODS: - EXJSONUtils (0.13.1) - EXManifests (0.14.3): - ExpoModulesCore - - Expo (51.0.25): + - Expo (51.0.26): - ExpoModulesCore - - expo-dev-client (4.0.21): + - expo-dev-client (4.0.22): - EXManifests - expo-dev-launcher - expo-dev-menu - expo-dev-menu-interface - EXUpdatesInterface - - expo-dev-launcher (4.0.23): + - expo-dev-launcher (4.0.24): - DoubleConversion - EXManifests - - expo-dev-launcher/Main (= 4.0.23) + - expo-dev-launcher/Main (= 4.0.24) - expo-dev-menu - expo-dev-menu-interface - ExpoModulesCore @@ -47,7 +47,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - expo-dev-launcher/Main (4.0.23): + - expo-dev-launcher/Main (4.0.24): - DoubleConversion - EXManifests - expo-dev-launcher/Unsafe @@ -76,7 +76,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - expo-dev-launcher/Unsafe (4.0.23): + - expo-dev-launcher/Unsafe (4.0.24): - DoubleConversion - EXManifests - expo-dev-menu @@ -104,10 +104,10 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - expo-dev-menu (5.0.17): + - expo-dev-menu (5.0.18): - DoubleConversion - - expo-dev-menu/Main (= 5.0.17) - - expo-dev-menu/ReactNativeCompatibles (= 5.0.17) + - expo-dev-menu/Main (= 5.0.18) + - expo-dev-menu/ReactNativeCompatibles (= 5.0.18) - glog - hermes-engine - RCT-Folly (= 2024.01.01.00) @@ -128,7 +128,7 @@ PODS: - ReactCommon/turbomodule/core - Yoga - expo-dev-menu-interface (1.8.3) - - expo-dev-menu/Main (5.0.17): + - expo-dev-menu/Main (5.0.18): - DoubleConversion - EXManifests - expo-dev-menu-interface @@ -154,7 +154,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - expo-dev-menu/ReactNativeCompatibles (5.0.17): + - expo-dev-menu/ReactNativeCompatibles (5.0.18): - DoubleConversion - glog - hermes-engine @@ -175,7 +175,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - expo-dev-menu/SafeAreaView (5.0.17): + - expo-dev-menu/SafeAreaView (5.0.18): - DoubleConversion - ExpoModulesCore - glog @@ -197,7 +197,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - expo-dev-menu/Vendored (5.0.17): + - expo-dev-menu/Vendored (5.0.18): - DoubleConversion - expo-dev-menu/SafeAreaView - glog @@ -1956,10 +1956,10 @@ SPEC CHECKSUMS: EXConstants: 409690fbfd5afea964e5e9d6c4eb2c2b59222c59 EXJSONUtils: 30c17fd9cc364d722c0946a550dfbf1be92ef6a4 EXManifests: c1fab4c3237675e7b0299ea8df0bcb14baca4f42 - Expo: 88047e6d12a8113a18887b6ebd775fccfcdbf3c9 - expo-dev-client: 3a5d838e562927099488c094acba1818296c6bc6 - expo-dev-launcher: 0336379dae2faeb2da861c61977a6fbd02ab52f1 - expo-dev-menu: 11322d81c62f966399ec162383a8488b55cce366 + Expo: f3e39cddde295c79d206e972a59693cbb329ef46 + expo-dev-client: 05a436763435d5f50bbdbcc51adf8b0b55d8dabc + expo-dev-launcher: 140874617542fa32908b1710775bca3ff4bd66c6 + expo-dev-menu: 101ecf9a992bc3d51841b31e4301f4ca54600ad4 expo-dev-menu-interface: be32c09f1e03833050f0ee290dcc86b3ad0e73e4 ExpoAsset: 323700f291684f110fb55f0d4022a3362ea9f875 ExpoBlur: fa53f874e7b208bc3756d1bf07903c12e790beb1 diff --git a/ios/TestFlight/WhatToTest.en-US.txt b/ios/TestFlight/WhatToTest.en-US.txt index de82ae83..92c2e389 100644 --- a/ios/TestFlight/WhatToTest.en-US.txt +++ b/ios/TestFlight/WhatToTest.en-US.txt @@ -1 +1,3 @@ -- New quick links \ No newline at end of file +- New quick links card on the dashboard +- Performance improvements +- Bug fixes diff --git a/package.json b/package.json index 4344edde..3d5e6e04 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "@tanstack/react-query-persist-client": "^5.51.23", "@th3rdwave/react-navigation-bottom-sheet": "^0.3.2", "color": "^4.2.3", - "expo": "~51.0.25", + "expo": "~51.0.26", "expo-application": "~5.9.1", "expo-blur": "~13.0.2", "expo-brightness": "~12.0.1", @@ -52,7 +52,6 @@ "expo-navigation-bar": "~3.0.7", "expo-router": "~3.5.21", "expo-secure-store": "~13.0.2", - "expo-splash-screen": "~0.27.5", "expo-system-ui": "~3.0.7", "fuse.js": "^7.0.0", "graphql": "^16.9.0", @@ -99,7 +98,6 @@ "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@types/color": "^3.0.6", "@types/geojson": "^7946.0.14", - "@types/node": "^22.1.0", "@types/prop-types": "^15.7.12", "@types/react": "~18.2.79", "@types/sanitize-html": "^2.11.0", @@ -118,7 +116,7 @@ "eslint-plugin-react-hooks": "^4.6.2", "eslint-plugin-react-native": "^4.1.0", "expo-atlas": "^0.3.11", - "expo-dev-client": "~4.0.21", + "expo-dev-client": "~4.0.22", "husky": "^9.1.4", "lint-staged": "^15.2.8", "prettier": "3.2.5", diff --git a/src/api/thi-session-handler.ts b/src/api/thi-session-handler.ts index cd3e9106..2a7ba65e 100644 --- a/src/api/thi-session-handler.ts +++ b/src/api/thi-session-handler.ts @@ -149,7 +149,6 @@ export async function callWithSession( } catch (e) { throw new NoSessionError() } - return await method(session) } else { throw new NoSessionError() @@ -211,20 +210,18 @@ export async function forgetSession(): Promise { const session = load('session') if (session === null) { console.log('No session to forget') - return + } else { + try { + await API.logout(session) + } catch (e) { + console.error(e) + } } - try { - await API.logout(session) - } catch (e) { - console.error(e) - } await Promise.all([ SecureStore.deleteItemAsync('session'), SecureStore.deleteItemAsync('username'), SecureStore.deleteItemAsync('password'), - SecureStore.deleteItemAsync('userFullName'), - SecureStore.deleteItemAsync('userType'), ]) // clear all AsyncStorage data except analytics diff --git a/src/app/(flow)/onboarding.tsx b/src/app/(flow)/onboarding.tsx index a951347d..f65cfe6c 100644 --- a/src/app/(flow)/onboarding.tsx +++ b/src/app/(flow)/onboarding.tsx @@ -3,8 +3,8 @@ import WhatsNewBox from '@/components/Elements/Flow/WhatsnewBox' import LogoSVG from '@/components/Elements/Flow/svgs/logo' import LogoTextSVG from '@/components/Elements/Flow/svgs/logoText' import { type Colors } from '@/components/colors' -import { FlowContext, UserKindContext } from '@/components/contexts' -import { PRIVACY_URL, USER_GUEST } from '@/data/constants' +import { FlowContext } from '@/components/contexts' +import { PRIVACY_URL } from '@/data/constants' import { getContrastColor } from '@/utils/ui-utils' import { useTheme } from '@react-navigation/native' import * as Haptics from 'expo-haptics' @@ -34,7 +34,6 @@ import Shimmer from 'react-native-shimmer' export default function OnboardingScreen(): JSX.Element { const flow = React.useContext(FlowContext) - const userkind = React.useContext(UserKindContext) const { t } = useTranslation('flow') const data = [ @@ -82,13 +81,8 @@ export default function OnboardingScreen(): JSX.Element { flow.setOnboarded(true) flow.setUpdated(true) flow.setAnalyticsAllowed(true) - - if (userkind.userKind === USER_GUEST) { - router.navigate('login') - router.setParams({ fromOnboarding: 'true' }) - } else { - router.replace('(tabs)/(index)') - } + router.navigate('login') + router.setParams({ fromOnboarding: 'true' }) }} disabled={buttonDisabled} > diff --git a/src/app/(flow)/whatsnew.tsx b/src/app/(flow)/whatsnew.tsx index 9417c2e2..5d642eff 100644 --- a/src/app/(flow)/whatsnew.tsx +++ b/src/app/(flow)/whatsnew.tsx @@ -73,7 +73,7 @@ export default function WhatsNewScreen(): JSX.Element { setTimeout(() => { opacityValues.forEach((opacity, index) => { opacity.value = withDelay( - index * 440, + index * 400, withTiming(1, { duration: 800, easing: Easing.linear, @@ -84,7 +84,7 @@ export default function WhatsNewScreen(): JSX.Element { }, []) return ( - + { void Linking.openURL(STATUS_URL) diff --git a/src/app/(screens)/login.tsx b/src/app/(screens)/login.tsx index 6ff0a8da..9ee7ad63 100644 --- a/src/app/(screens)/login.tsx +++ b/src/app/(screens)/login.tsx @@ -96,6 +96,7 @@ export default function Login(): JSX.Element { }>() const navigateHome = (): void => { + console.log('navigateHome', fromOnboarding) if (fromOnboarding === 'true') { router.dismissAll() router.replace('(tabs)/(index)') diff --git a/src/app/(screens)/settings.tsx b/src/app/(screens)/settings.tsx index d34125c1..90929b4e 100644 --- a/src/app/(screens)/settings.tsx +++ b/src/app/(screens)/settings.tsx @@ -226,7 +226,7 @@ export default function Settings(): JSX.Element { ios: 'fork.knife', }, onPress: () => { - router.navigate('preferences') + router.navigate('foodPreferences') }, }, { diff --git a/src/app/(tabs)/(index)/_layout.tsx b/src/app/(tabs)/(index)/_layout.tsx index 7b2fdf95..4bffb387 100644 --- a/src/app/(tabs)/(index)/_layout.tsx +++ b/src/app/(tabs)/(index)/_layout.tsx @@ -36,8 +36,6 @@ export default function Layout(): JSX.Element { backgroundColor: colors.labelSecondaryColor, }, backdropComponent: renderBackdrop, - stackBehavior: 'replace', - enableDynamicSizing: true, }} /> ) diff --git a/src/app/(tabs)/_layout.tsx b/src/app/(tabs)/_layout.tsx index 106e001e..5b98911c 100644 --- a/src/app/(tabs)/_layout.tsx +++ b/src/app/(tabs)/_layout.tsx @@ -72,7 +72,6 @@ export default function HomeLayout(): JSX.Element { const prepare = async (): Promise => { const tabsPaths = ['/', '/timetable', '/map', '/food', '/links'] const isTab = tabsPaths.includes(pathname) - if (isOnboarded !== true) { await NavigationBar.setBackgroundColorAsync(colors.contrast) return diff --git a/src/components/Cards/LinkCard.tsx b/src/components/Cards/LinkCard.tsx index 9a58d0f3..719efa64 100644 --- a/src/components/Cards/LinkCard.tsx +++ b/src/components/Cards/LinkCard.tsx @@ -14,12 +14,17 @@ import BaseCard from './BaseCard' const LinkCard = (): JSX.Element => { const { t } = useTranslation('common') const colors = useTheme().colors as Colors - const { recentQuicklinks } = useContext(PreferencesContext) + const { recentQuicklinks, addRecentQuicklink } = + useContext(PreferencesContext) const userQuicklinks = recentQuicklinks .map((title) => quicklinks.find((quicklink) => quicklink.key === title)) .filter((quicklink) => quicklink !== undefined) - + const linkPress = async (key: string, url: string): Promise => { + addRecentQuicklink(key) + trackEvent('Quicklink', { link: key }) + await Linking.openURL(url) + } return ( @@ -28,8 +33,7 @@ const LinkCard = (): JSX.Element => { { - trackEvent('Quicklink', { link: link.key }) - void Linking.openURL(link.url) + void linkPress(link.key, link.url) }} style={{ backgroundColor: colors.cardButton, diff --git a/src/components/Cards/LoginCard.tsx b/src/components/Cards/LoginCard.tsx index 20ceb961..70dc82de 100644 --- a/src/components/Cards/LoginCard.tsx +++ b/src/components/Cards/LoginCard.tsx @@ -10,7 +10,6 @@ const LoginCard = (): JSX.Element => { const colors = useTheme().colors as Colors const { t } = useTranslation('navigation') - console.log('rendering LoginCard') return ( { const { colors, dark } = useTheme() - const darkIos = 'rgba(0, 0, 0, 0.45)' + const darkIos = 'rgba(0, 0, 0, 0.3)' const lightIos = 'rgba(255, 255, 255, 0.5)' return Platform.OS === 'ios' ? ( { ]} > diff --git a/src/components/Elements/Universal/LoginForm.tsx b/src/components/Elements/Universal/LoginForm.tsx index 117432a0..198049d1 100644 --- a/src/components/Elements/Universal/LoginForm.tsx +++ b/src/components/Elements/Universal/LoginForm.tsx @@ -41,8 +41,8 @@ const LoginForm = ({ const [password, setPassword] = useState('') const colors = useTheme().colors as Colors const isDark = useTheme().dark - const { userKind = USER_GUEST, toggleUserKind } = - React.useContext(UserKindContext) + // No guest fallback is provided, so the guest session will be created correctly + const { userKind, toggleUserKind } = React.useContext(UserKindContext) const [loading, setLoading] = useState(false) const { t } = useTranslation('flow') const { resetOrder } = useContext(DashboardContext) @@ -120,6 +120,8 @@ const LoginForm = ({ async function guestLogin(): Promise { setLoading(true) + setUsername('') + setPassword('') try { await createGuestSession(userKind !== USER_GUEST) @@ -129,6 +131,7 @@ const LoginForm = ({ toggleUserKind(undefined) navigateHome() + setLoading(false) } async function load(key: string): Promise { diff --git a/src/components/Elements/Universal/WorkaroundStack.tsx b/src/components/Elements/Universal/WorkaroundStack.tsx index 15951d4f..825ebadb 100644 --- a/src/components/Elements/Universal/WorkaroundStack.tsx +++ b/src/components/Elements/Universal/WorkaroundStack.tsx @@ -57,6 +57,7 @@ function WorkaroundStack({ // @ts-expect-error Type not checked titleKey ), + headerRight: headerRightElement as any, }} initialParams={params} /> diff --git a/src/data/changelog.json b/src/data/changelog.json index 8ca2ef5f..de8b645e 100644 --- a/src/data/changelog.json +++ b/src/data/changelog.json @@ -58,7 +58,7 @@ }, "icon": { "ios": "link", - "android": "link" + "android": "captive_portal" } }, { @@ -72,7 +72,7 @@ }, "icon": { "ios": "bolt", - "android": "bug_report" + "android": "bolt" } }, { diff --git a/src/data/licenses.json b/src/data/licenses.json index 853f0cb4..3eca82db 100644 --- a/src/data/licenses.json +++ b/src/data/licenses.json @@ -179,19 +179,13 @@ "licenseUrl": "https://github.com/expo/expo", "parents": "neuland" }, - "expo-splash-screen@0.27.5": { - "licenses": "MIT", - "repository": "https://github.com/expo/expo", - "licenseUrl": "https://github.com/expo/expo", - "parents": "neuland" - }, "expo-system-ui@3.0.7": { "licenses": "MIT", "repository": "https://github.com/expo/expo", "licenseUrl": "https://github.com/expo/expo", "parents": "neuland" }, - "expo@51.0.25": { + "expo@51.0.26": { "licenses": "MIT", "repository": "https://github.com/expo/expo", "licenseUrl": "https://github.com/expo/expo",