diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml new file mode 100644 index 00000000..3d70f6d3 --- /dev/null +++ b/.github/workflows/build-android.yml @@ -0,0 +1,68 @@ +# If setting a specific version, wrap it with single quotes like '12.0' +# to pass it as string because GitHub trimmes trailing .0 from numbers +# due to https://github.com/actions/runner/issues/849 + +name: build-and-ship-android +on: + push: + branches: + - 'main' +jobs: + build-and-ship-android: + runs-on: ubuntu-latest + env: + BUNDLE_GEMFILE: ${{ github.workspace }}/apps/skolplattformen-app/Gemfile + steps: + - name: Checkout code + uses: actions/checkout@v3 + with: + # changed this from GITHUB_PERSONAL_ACCESS_TOKEN_PATH to GITHUB_TOKEN + token: ${{ secrets.GITHUB_TOKEN }} + submodules: true + - name: Set up our JDK environment + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: 11 + - name: Setup Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.2.2' + bundler-cache: true + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: '18.13' + cache: 'npm' + cache-dependency-path: ${{ github.workspace }}/apps/skolplattformen-app/package-lock.json + - name: set npm version + run: npm install -g npm@9.6.0 && echo "secrets.GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} secrets.GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }} workspace= ${{ github.workspace }} secrets.MAPS_API_KEY=${{secrets.MAPS_API_KEY}}" + - run: cd apps/skolplattformen-app/android && bundle install + - name: install node modules + run: cd apps/skolplattformen-app && npm ci + - name: Setup local.properties + run: echo "MAPS_API_KEY=${{ env.MAPS_API_KEY }}" > ${{ github.workspace }}/apps/skolplattformen-app/android/local.properties + env: + MAPS_API_KEY: ${{ secrets.MAPS_API_KEY }} + - name: Setup key.json + run: echo "${KEY_JSON}" > ${{ github.workspace }}/apps/skolplattformen-app/android/key.json + env: + KEY_JSON: ${{ secrets.KEY_JSON }} + - run: cd apps/skolplattformen-app/android && bundle exec fastlane android beta + env: + SIGNING_STORE_PASSWORD: ${{ secrets.SIGNING_STORE_PASSWORD }} + ALIAS_KEY_PASSWORD: ${{ secrets.ALIAS_KEY_PASSWORD }} + - name: 'Store artifact native_debug_symbols.zip' + uses: actions/upload-artifact@v3 + if: ${{ failure() }} + with: + name: native_debug_symbols.zip + path: ${{ github.workspace }}/apps/skolplattformen-app/android/native_debug_symbols.zip + retention-days: 5 + - name: 'Store build mappings for difficult crashlytics traces' + uses: actions/upload-artifact@v3 + if: ${{ success() }} + with: + name: mapping.txt + path: ${{ github.workspace }}/apps/skolplattformen-app/android/app/build/outputs/mapping/release/mapping.txt + retention-days: 500 diff --git a/.github/workflows/build-ios.yaml b/.github/workflows/build-ios.yaml new file mode 100644 index 00000000..fb198b2a --- /dev/null +++ b/.github/workflows/build-ios.yaml @@ -0,0 +1,51 @@ +# If setting a specific version, wrap it with single quotes like '12.0' +# to pass it as string because GitHub trimmes trailing .0 from numbers +# due to https://github.com/actions/runner/issues/849 + +name: build-and-ship-ios +on: + push: + branches: + - 'main' +jobs: + build-and-ship-ios: + runs-on: macos-13 + env: + BUNDLE_GEMFILE: ${{ github.workspace }}/apps/skolplattformen-app-new/Gemfile + steps: + - uses: actions/checkout@v3 + with: + # changed this from GITHUB_PERSONAL_ACCESS_TOKEN_PATH to GITHUB_TOKEN + token: ${{ secrets.GITHUB_TOKEN }} + submodules: true + - uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: '14.3.1' + - uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.2.2' + bundler-cache: true + - uses: actions/setup-node@v3 + with: + node-version: '18.13' + cache: 'npm' + cache-dependency-path: ${{ github.workspace }}/apps/skolplattformen-app-new/package-lock.json + - uses: actions/cache@v3 + with: + path: ${{ github.workspace }}/apps/skolplattformen-app-new/ios/Pods + key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }} + restore-keys: | + ${{ runner.os }}-pods- + - name: set npm version + run: npm install -g npm@9.6.0 + - name: install node modules + run: cd apps/skolplattformen-app-new && npm ci + - run: cd apps/skolplattformen-app-new/ios && bundle install + - run: cd apps/skolplattformen-app-new/ios && npx pod-install + - run: cd apps/skolplattformen-app-new/ios && bundle exec pod update hermes-engine --no-repo-update + - run: cd apps/skolplattformen-app-new/ios && export && bundle exec fastlane ios beta version:patch + env: + ASCAPI_KEY_CONTENT: ${{ secrets.ASCAPI_KEY_CONTENT }} + MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} + MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.MATCH_GIT_BASIC_AUTHORIZATION }} + ENVFILE: ${{env.ENVFILE}} diff --git a/.github/workflows/pr_check_new.yml b/.github/workflows/pr_check_new.yml new file mode 100644 index 00000000..b47f7559 --- /dev/null +++ b/.github/workflows/pr_check_new.yml @@ -0,0 +1,39 @@ +name: Run tests on PR - new + +on: + pull_request: + branches: + - main +jobs: + test: + name: Run tests + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Setup Node + uses: actions/setup-node@v3 + with: + node-version: '18.17.0' + + - name: Setup timezone + uses: zcong1993/setup-timezone@master + with: + timezone: Europe/Stockholm + + - name: set npm version + run: npm install -g npm@10.2.0 + + - name: install node modules + run: cd apps/skolplattformen-app-new && npm ci + + - name: Run tests + run: cd apps/skolplattformen-app-new && npm test + env: + CI: true + + - name: Check linting + run: cd apps/skolplattformen-app-new && npm run lint + env: + CI: true diff --git a/README.md b/README.md index 5c912442..41b760c6 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ The respective README files there contain more detailed descriptions. * [Architecture](#architecture) * [Apps](#apps) * [skolplattformen](#skolplattformen) + * [skolplattformen dependency upgrade](#skolplattformen-dependency-upgrade) * [website](#website) * [Libs](#embedded-api) * [api](#api) @@ -58,6 +59,9 @@ We're starting small, with more features being added over time. For more information, check out the [source code](apps/skolplattformen-app). +#### skolplattformen dependency upgrade +A dependency upgrade is currently in the works. To navigate directly to the related readme, click [here](/apps/skolplattformen-app-new/README-NEW.md). + #### website The code for the website at https://skolplattformen.org/. It's built using Next.js. diff --git a/apps/skolplattformen-app/.babelrc b/apps/skolplattformen-app/.babelrc deleted file mode 100644 index d4b74b5b..00000000 --- a/apps/skolplattformen-app/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "presets": ["module:metro-react-native-babel-preset"] -} diff --git a/apps/skolplattformen-app/.buckconfig b/apps/skolplattformen-app/.buckconfig deleted file mode 100644 index 934256cb..00000000 --- a/apps/skolplattformen-app/.buckconfig +++ /dev/null @@ -1,6 +0,0 @@ - -[android] - target = Google Inc.:Google APIs:23 - -[maven_repositories] - central = https://repo1.maven.org/maven2 diff --git a/apps/skolplattformen-app/.bundle/config b/apps/skolplattformen-app/.bundle/config new file mode 100644 index 00000000..848943bb --- /dev/null +++ b/apps/skolplattformen-app/.bundle/config @@ -0,0 +1,2 @@ +BUNDLE_PATH: "vendor/bundle" +BUNDLE_FORCE_RUBY_PLATFORM: 1 diff --git a/apps/skolplattformen-app/.eslintrc.js b/apps/skolplattformen-app/.eslintrc.js new file mode 100644 index 00000000..072d9314 --- /dev/null +++ b/apps/skolplattformen-app/.eslintrc.js @@ -0,0 +1,7 @@ +module.exports = { + root: true, + extends: '@react-native', + rules: { + semi: ['warn', 'never'], + }, +} diff --git a/apps/skolplattformen-app/.eslintrc.json b/apps/skolplattformen-app/.eslintrc.json deleted file mode 100644 index a7fd39f6..00000000 --- a/apps/skolplattformen-app/.eslintrc.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "extends": [ - "@react-native-community", - "plugin:react-native-a11y/all", - "plugin:@nrwl/nx/react", - "../../.eslintrc.json" - ], - "ignorePatterns": ["!**/*", "public", ".cache", "node_modules"], - "overrides": [ - { - "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": {"no-console":"warn"} - }, - { - "files": ["*.ts", "*.tsx"], - "rules": { - "@typescript-eslint/ban-ts-comment": "off" - } - }, - { - "files": ["*.js", "*.jsx"], - "rules": { - "@typescript-eslint/no-var-requires": "off" - } - } - ] -} diff --git a/apps/skolplattformen-app/.flowconfig b/apps/skolplattformen-app/.flowconfig deleted file mode 100644 index 6009e737..00000000 --- a/apps/skolplattformen-app/.flowconfig +++ /dev/null @@ -1,70 +0,0 @@ -[ignore] -; We fork some components by platform -.*/*[.]android.js - -; Ignore "BUCK" generated dirs -/\.buckd/ - -; Ignore polyfills -node_modules/react-native/Libraries/polyfills/.* - -; These should not be required directly -; require from fbjs/lib instead: require('fbjs/lib/warning') -node_modules/warning/.* - -; Flow doesn't support platforms -.*/Libraries/Utilities/LoadingView.js - -[untyped] -.*/node_modules/@react-native-community/cli/.*/.* - -[include] - -[libs] -node_modules/react-native/interface.js -node_modules/react-native/flow/ - -[options] -emoji=true - -esproposal.optional_chaining=enable -esproposal.nullish_coalescing=enable - -module.file_ext=.js -module.file_ext=.json -module.file_ext=.ios.js - -munge_underscores=true - -module.name_mapper='^react-native/\(.*\)$' -> '/node_modules/react-native/\1' -module.name_mapper='^@?[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '/node_modules/react-native/Libraries/Image/RelativeImageStub' - -suppress_type=$FlowIssue -suppress_type=$FlowFixMe -suppress_type=$FlowFixMeProps -suppress_type=$FlowFixMeState - -[lints] -sketchy-null-number=warn -sketchy-null-mixed=warn -sketchy-number=warn -untyped-type-import=warn -nonstrict-import=warn -deprecated-type=warn -unsafe-getters-setters=warn -unnecessary-invariant=warn -signature-verification-failure=warn - -exact_by_default=true - -[strict] -deprecated-type -nonstrict-import -sketchy-null -unclear-type -unsafe-getters-setters -untyped-import -untyped-type-import - -[version] -^0.158.0 diff --git a/apps/skolplattformen-app/.gitattributes b/apps/skolplattformen-app/.gitattributes deleted file mode 100644 index d42ff183..00000000 --- a/apps/skolplattformen-app/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -*.pbxproj -text diff --git a/apps/skolplattformen-app/.gitignore b/apps/skolplattformen-app/.gitignore index 9055c4ed..0d4b6015 100644 --- a/apps/skolplattformen-app/.gitignore +++ b/apps/skolplattformen-app/.gitignore @@ -20,6 +20,7 @@ DerivedData *.hmap *.ipa *.xcuserstate +ios/.xcode.env.local # Android/IntelliJ # @@ -28,6 +29,10 @@ build/ .gradle local.properties *.iml +*.hprof +.cxx/ +!debug.keystore + # node.js # @@ -35,10 +40,6 @@ node_modules/ npm-debug.log yarn-error.log -# BUCK -buck-out/ -\.buckd/ - # fastlane # # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the @@ -46,14 +47,25 @@ buck-out/ # For more information about the recommended setup visit: # https://docs.fastlane.tools/best-practices/source-control/ -*/fastlane/report.xml -*/fastlane/Preview.html -*/fastlane/screenshots +**/fastlane/report.xml +**/fastlane/Preview.html +**/fastlane/screenshots +**/fastlane/test_output # Bundle artifact *.jsbundle -# CocoaPods +# Ruby / CocoaPods /ios/Pods/ +/vendor/bundle/ -libraries.json \ No newline at end of file +# Temporary files created by Metro to check the health of the file watcher +.metro-health-check* + +# testing +/coverage + + +libraries.json + +keys.json \ No newline at end of file diff --git a/apps/skolplattformen-app/.nvmrc b/apps/skolplattformen-app/.nvmrc deleted file mode 100644 index 9a0c3d3f..00000000 --- a/apps/skolplattformen-app/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v14.15.4 diff --git a/apps/skolplattformen-app/.watchmanconfig b/apps/skolplattformen-app/.watchmanconfig index 9e26dfee..0967ef42 100644 --- a/apps/skolplattformen-app/.watchmanconfig +++ b/apps/skolplattformen-app/.watchmanconfig @@ -1 +1 @@ -{} \ No newline at end of file +{} diff --git a/apps/skolplattformen-app/App.tsx b/apps/skolplattformen-app/App.tsx index df692246..80500a95 100644 --- a/apps/skolplattformen-app/App.tsx +++ b/apps/skolplattformen-app/App.tsx @@ -1,6 +1,6 @@ import * as eva from '@eva-design/eva' import AsyncStorage from '@react-native-async-storage/async-storage' -import { ApiProvider, Reporter } from '@skolplattformen/hooks' +import { ApiProvider, Reporter } from './libs/hooks/src' import { ApplicationProvider, IconRegistry, Text } from '@ui-kitten/components' import { EvaIconsPack } from '@ui-kitten/eva-icons' import React from 'react' @@ -15,6 +15,7 @@ import { default as customMapping } from './design/mapping.json' import { darkTheme, lightTheme } from './design/themes' import useSettingsStorage from './hooks/useSettingsStorage' import { translations } from './utils/translation' +import { GestureHandlerRootView } from 'react-native-gesture-handler' const reporter: Reporter | undefined = __DEV__ ? { @@ -24,7 +25,6 @@ const reporter: Reporter | undefined = __DEV__ : undefined if (__DEV__) { - // eslint-disable-next-line @typescript-eslint/no-var-requires const DevMenu = require('react-native-dev-menu') DevMenu.addItem('Clear AsyncStorage from all contents', () => AsyncStorage.clear().then(() => logAsyncStorage()) @@ -66,12 +66,13 @@ export default () => { const platform = schoolPlatforms.find((pf) => pf.id === currentSchoolPlatform) - if (!platform) + if (!platform) { return ( ERROR ) + } return ( @@ -97,7 +98,9 @@ export default () => { theme={colorScheme === 'dark' ? darkTheme : lightTheme} > - + + + diff --git a/apps/skolplattformen-app/Gemfile b/apps/skolplattformen-app/Gemfile new file mode 100644 index 00000000..c8af24aa --- /dev/null +++ b/apps/skolplattformen-app/Gemfile @@ -0,0 +1,9 @@ +source 'https://rubygems.org' + +# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version +ruby ">= 3.2.2" + +gem 'bundler' +gem 'cocoapods', '~> 1.12' +gem 'fastlane' +gem 'dotenv' diff --git a/apps/skolplattformen-app/Gemfile.lock b/apps/skolplattformen-app/Gemfile.lock new file mode 100644 index 00000000..6df4a8c1 --- /dev/null +++ b/apps/skolplattformen-app/Gemfile.lock @@ -0,0 +1,297 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (3.0.6) + rexml + activesupport (7.1.1) + base64 + bigdecimal + concurrent-ruby (~> 1.0, >= 1.0.2) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + minitest (>= 5.1) + mutex_m + tzinfo (~> 2.0) + addressable (2.8.5) + public_suffix (>= 2.0.2, < 6.0) + algoliasearch (1.27.5) + httpclient (~> 2.8, >= 2.8.3) + json (>= 1.5.1) + artifactory (3.0.15) + atomos (0.1.3) + aws-eventstream (1.2.0) + aws-partitions (1.841.0) + aws-sdk-core (3.185.1) + aws-eventstream (~> 1, >= 1.0.2) + aws-partitions (~> 1, >= 1.651.0) + aws-sigv4 (~> 1.5) + jmespath (~> 1, >= 1.6.1) + aws-sdk-kms (1.72.0) + aws-sdk-core (~> 3, >= 3.184.0) + aws-sigv4 (~> 1.1) + aws-sdk-s3 (1.136.0) + aws-sdk-core (~> 3, >= 3.181.0) + aws-sdk-kms (~> 1) + aws-sigv4 (~> 1.6) + aws-sigv4 (1.6.0) + aws-eventstream (~> 1, >= 1.0.2) + babosa (1.0.4) + base64 (0.1.1) + bigdecimal (3.1.4) + claide (1.1.0) + cocoapods (1.13.0) + addressable (~> 2.8) + claide (>= 1.0.2, < 2.0) + cocoapods-core (= 1.13.0) + cocoapods-deintegrate (>= 1.0.3, < 2.0) + cocoapods-downloader (>= 1.6.0, < 2.0) + cocoapods-plugins (>= 1.0.0, < 2.0) + cocoapods-search (>= 1.0.0, < 2.0) + cocoapods-trunk (>= 1.6.0, < 2.0) + cocoapods-try (>= 1.1.0, < 2.0) + colored2 (~> 3.1) + escape (~> 0.0.4) + fourflusher (>= 2.3.0, < 3.0) + gh_inspector (~> 1.0) + molinillo (~> 0.8.0) + nap (~> 1.0) + ruby-macho (>= 2.3.0, < 3.0) + xcodeproj (>= 1.23.0, < 2.0) + cocoapods-core (1.13.0) + activesupport (>= 5.0, < 8) + addressable (~> 2.8) + algoliasearch (~> 1.0) + concurrent-ruby (~> 1.1) + fuzzy_match (~> 2.0.4) + nap (~> 1.0) + netrc (~> 0.11) + public_suffix (~> 4.0) + typhoeus (~> 1.0) + cocoapods-deintegrate (1.0.5) + cocoapods-downloader (1.6.3) + cocoapods-plugins (1.0.0) + nap + cocoapods-search (1.0.1) + cocoapods-trunk (1.6.0) + nap (>= 0.8, < 2.0) + netrc (~> 0.11) + cocoapods-try (1.2.0) + colored (1.2) + colored2 (3.1.2) + commander (4.6.0) + highline (~> 2.0.0) + concurrent-ruby (1.2.2) + connection_pool (2.4.1) + declarative (0.0.20) + digest-crc (0.6.5) + rake (>= 12.0.0, < 14.0.0) + domain_name (0.5.20190701) + unf (>= 0.0.5, < 1.0.0) + dotenv (2.8.1) + drb (2.1.1) + ruby2_keywords + emoji_regex (3.2.3) + escape (0.0.4) + ethon (0.16.0) + ffi (>= 1.15.0) + excon (0.104.0) + faraday (1.10.3) + faraday-em_http (~> 1.0) + faraday-em_synchrony (~> 1.0) + faraday-excon (~> 1.1) + faraday-httpclient (~> 1.0) + faraday-multipart (~> 1.0) + faraday-net_http (~> 1.0) + faraday-net_http_persistent (~> 1.0) + faraday-patron (~> 1.0) + faraday-rack (~> 1.0) + faraday-retry (~> 1.0) + ruby2_keywords (>= 0.0.4) + faraday-cookie_jar (0.0.7) + faraday (>= 0.8.0) + http-cookie (~> 1.0.0) + faraday-em_http (1.0.0) + faraday-em_synchrony (1.0.0) + faraday-excon (1.1.0) + faraday-httpclient (1.0.1) + faraday-multipart (1.0.4) + multipart-post (~> 2) + faraday-net_http (1.0.1) + faraday-net_http_persistent (1.2.0) + faraday-patron (1.0.0) + faraday-rack (1.0.0) + faraday-retry (1.0.3) + faraday_middleware (1.2.0) + faraday (~> 1.0) + fastimage (2.2.7) + fastlane (2.216.0) + CFPropertyList (>= 2.3, < 4.0.0) + addressable (>= 2.8, < 3.0.0) + artifactory (~> 3.0) + aws-sdk-s3 (~> 1.0) + babosa (>= 1.0.3, < 2.0.0) + bundler (>= 1.12.0, < 3.0.0) + colored + commander (~> 4.6) + dotenv (>= 2.1.1, < 3.0.0) + emoji_regex (>= 0.1, < 4.0) + excon (>= 0.71.0, < 1.0.0) + faraday (~> 1.0) + faraday-cookie_jar (~> 0.0.6) + faraday_middleware (~> 1.0) + fastimage (>= 2.1.0, < 3.0.0) + gh_inspector (>= 1.1.2, < 2.0.0) + google-apis-androidpublisher_v3 (~> 0.3) + google-apis-playcustomapp_v1 (~> 0.1) + google-cloud-storage (~> 1.31) + highline (~> 2.0) + http-cookie (~> 1.0.5) + json (< 3.0.0) + jwt (>= 2.1.0, < 3) + mini_magick (>= 4.9.4, < 5.0.0) + multipart-post (>= 2.0.0, < 3.0.0) + naturally (~> 2.2) + optparse (~> 0.1.1) + plist (>= 3.1.0, < 4.0.0) + rubyzip (>= 2.0.0, < 3.0.0) + security (= 0.1.3) + simctl (~> 1.6.3) + terminal-notifier (>= 2.0.0, < 3.0.0) + terminal-table (~> 3) + tty-screen (>= 0.6.3, < 1.0.0) + tty-spinner (>= 0.8.0, < 1.0.0) + word_wrap (~> 1.0.0) + xcodeproj (>= 1.13.0, < 2.0.0) + xcpretty (~> 0.3.0) + xcpretty-travis-formatter (>= 0.0.3) + ffi (1.16.3) + fourflusher (2.3.1) + fuzzy_match (2.0.4) + gh_inspector (1.1.3) + google-apis-androidpublisher_v3 (0.51.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-core (0.11.1) + addressable (~> 2.5, >= 2.5.1) + googleauth (>= 0.16.2, < 2.a) + httpclient (>= 2.8.1, < 3.a) + mini_mime (~> 1.0) + representable (~> 3.0) + retriable (>= 2.0, < 4.a) + rexml + webrick + google-apis-iamcredentials_v1 (0.17.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-playcustomapp_v1 (0.13.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-storage_v1 (0.19.0) + google-apis-core (>= 0.9.0, < 2.a) + google-cloud-core (1.6.0) + google-cloud-env (~> 1.0) + google-cloud-errors (~> 1.0) + google-cloud-env (1.6.0) + faraday (>= 0.17.3, < 3.0) + google-cloud-errors (1.3.1) + google-cloud-storage (1.44.0) + addressable (~> 2.8) + digest-crc (~> 0.4) + google-apis-iamcredentials_v1 (~> 0.1) + google-apis-storage_v1 (~> 0.19.0) + google-cloud-core (~> 1.6) + googleauth (>= 0.16.2, < 2.a) + mini_mime (~> 1.0) + googleauth (1.8.1) + faraday (>= 0.17.3, < 3.a) + jwt (>= 1.4, < 3.0) + multi_json (~> 1.11) + os (>= 0.9, < 2.0) + signet (>= 0.16, < 2.a) + highline (2.0.3) + http-cookie (1.0.5) + domain_name (~> 0.5) + httpclient (2.8.3) + i18n (1.14.1) + concurrent-ruby (~> 1.0) + jmespath (1.6.2) + json (2.6.3) + jwt (2.7.1) + mini_magick (4.12.0) + mini_mime (1.1.5) + minitest (5.20.0) + molinillo (0.8.0) + multi_json (1.15.0) + multipart-post (2.3.0) + mutex_m (0.1.2) + nanaimo (0.3.0) + nap (1.1.0) + naturally (2.2.1) + netrc (0.11.0) + optparse (0.1.1) + os (1.1.4) + plist (3.7.0) + public_suffix (4.0.7) + rake (13.0.6) + representable (3.2.0) + declarative (< 0.1.0) + trailblazer-option (>= 0.1.1, < 0.2.0) + uber (< 0.2.0) + retriable (3.1.2) + rexml (3.2.6) + rouge (2.0.7) + ruby-macho (2.5.1) + ruby2_keywords (0.0.5) + rubyzip (2.3.2) + security (0.1.3) + signet (0.18.0) + addressable (~> 2.8) + faraday (>= 0.17.5, < 3.a) + jwt (>= 1.5, < 3.0) + multi_json (~> 1.10) + simctl (1.6.10) + CFPropertyList + naturally + terminal-notifier (2.0.0) + terminal-table (3.0.2) + unicode-display_width (>= 1.1.1, < 3) + trailblazer-option (0.1.2) + tty-cursor (0.7.1) + tty-screen (0.8.1) + tty-spinner (0.9.3) + tty-cursor (~> 0.7) + typhoeus (1.4.0) + ethon (>= 0.9.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + uber (0.1.0) + unf (0.1.4) + unf_ext + unf_ext (0.0.8.2) + unicode-display_width (2.5.0) + webrick (1.8.1) + word_wrap (1.0.0) + xcodeproj (1.23.0) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.3) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.3.0) + rexml (~> 3.2.4) + xcpretty (0.3.0) + rouge (~> 2.0.7) + xcpretty-travis-formatter (1.0.1) + xcpretty (~> 0.2, >= 0.0.7) + +PLATFORMS + ruby + +DEPENDENCIES + bundler + cocoapods (~> 1.12) + dotenv + fastlane + +RUBY VERSION + ruby 3.2.2p53 + +BUNDLED WITH + 2.4.21 diff --git a/apps/skolplattformen-app/README-NEW.md b/apps/skolplattformen-app/README-NEW.md new file mode 100644 index 00000000..3373ca77 --- /dev/null +++ b/apps/skolplattformen-app/README-NEW.md @@ -0,0 +1,102 @@ +# Skolplattformen React Native Project + +Welcome to this new [**React Native**](https://reactnative.dev) project, initiated using [`@react-native-community/cli`](https://github.com/react-native-community/cli). + +## Pre-requisites + +> **Important**: Make sure you have gone through the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) guide up to the "Creating a new application" step before moving forward. + +## Initial Setup + +### Required Software + +1. [Git](https://git-scm.com/) +2. [Node](https://nodejs.org/en/) +3. [NPM](https://docs.npmjs.com/cli/v8/commands/npm-install) + +### Minimum Node Version +Ensure you are using Node version 16 or higher. + +### Cloning the Repository + +```bash +git clone https://github.com/Home-Biz-LLS/skolplattformen-react-native +``` + +### Installing Dependencies + +```bash +cd apps/skolplattformen-app-new/ && npm i +``` + +--- + +## Running the App + +### For iOS + +**Note**: Running the iOS app requires a Mac with native support. Windows/Linux are currently not supported. + +#### Essential Guides and Tools + +* [Mac OS Setup Guide](https://reactnative.dev/docs/environment-setup) + +#### Step-by-Step Instructions + +1. **Install Xcode**: Ensure Xcode is installed on your system. + +2. **Install CocoaPods**: If not already installed, you can do this easily using Homebrew. + - [Homebrew Install Guide for CocoaPods](https://formulae.brew.sh/formula/cocoapods) + - [Official CocoaPods Guide](https://guides.cocoapods.org/using/getting-started.html) + +3. **Install Pods** + ```bash + cd apps/skolplattformen-app-new/ios && pod install + ``` + +#### Running the iOS App + + +* Option 1: Using Metro Bundler + + ![metro bundler example](/apps/skolplattformen-app-new/docs/assets/MetroBundlerExample.png) + ```bash + cd apps/skolplattformen-app-new && npm run start + ``` + then type + ```bash + i + ``` + +* Option 2: Running Directly + ```bash + npm run ios + ``` + +--- + +### For Android + +**Note**: Choose an appropriate guide based on your operating system: + +* [Mac OS](/apps/skolplattformen-app-new/docs/android_mac.md) +* [Windows](/apps/skolplattformen-app-new//docs/android_windows.md) +* [Linux](/apps/skolplattformen-app-new//docs/android_linux.md) + +#### Running the Android App + +* Option 1: Using Metro Bundler + + ![metro bundler example](/apps/skolplattformen-app-new/docs/assets/MetroBundlerExample.png) + ```bash + cd apps/skolplattformen-app-new && npm run start + ``` + then type + ```bash + a + ``` + +* Option 2: Running Directly + ```bash + npm run android + ``` \ No newline at end of file diff --git a/apps/skolplattformen-app/README.md b/apps/skolplattformen-app/README.md index 2407f6a7..f22bc1fc 100644 --- a/apps/skolplattformen-app/README.md +++ b/apps/skolplattformen-app/README.md @@ -1,59 +1,84 @@ -# Öppna skolplattformen App +This is a new [**React Native**](https://reactnative.dev) project, bootstrapped using [`@react-native-community/cli`](https://github.com/react-native-community/cli). -This is the app for Öppna skolplattformen. +# Getting Started -## Getting started +>**Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding. -Have a look at the [overall readme](../../) for general instructions on getting started. +## Getting started with Development -### Prerequisites +### Please use node version 16 or higher -We use `yarn` as our package manager. To install it, run `sudo npm install -g yarn`. All the commands described here should be run from the `packages/app` directory. +To clone and build the project, you first need to install [git](https://git-scm.com/), [node](https://nodejs.org/en/) and [npm](https://docs.npmjs.com/cli/v8/commands/npm-install). + +Clone the repo with +```bash +$ git clone https://github.com/Home-Biz-LLS/skolplattformen-react-native +``` + +Install dependencies +```bash +cd apps/skolplattformen-app-new/ && npm i +``` ### iOS -To get started using the iOS simulator start by installing the JavaScript -dependencies using +If you wanna run the iOS app, you need to setup a couple of things first, we have a guide that will assist you in getting started with the iOS app. A Mac is required to build projects with native code for iOS so we do not have support for Linux / Windows. +* [Mac OS](https://reactnative.dev/docs/environment-setup) + +#### Step 1 +Make sure you have **Xcode** installed + + +#### Step 2 +Make sure **CocoaPods** is installed (you can do it easily with homebrew) + +* [CocoaPods homebrew](https://formulae.brew.sh/formula/cocoapods) +* [CocoaPods](https://guides.cocoapods.org/using/getting-started.html) + + +#### Step 3 ```bash -$ yarn +cd apps/skolplattformen-app-new/ios && pod install ``` -Next you need to install the [Cocoapods](https://cocoapods.org/) dependencies -for the iOS project +If you already setup everything, go into the -```bash -$ cd ios -$ pod setup -$ pod install +"skolplattformen-app-new" directory + +Start the metro + +``` +npm run start ``` -You should now be setup to run the app in the Simulator. Run the `ios` command -in the root of the app. +then -```bash -$ yarn ios ``` +i +``` +to Start iOS app + +OR + +Start the iOS app directly +``` +npm run ios +``` + + ### Android -Android development requires that you have [Android Studio](https://developer.android.com/studio) and relevant build tools installed. +If you wanna run the Android app, you need to setup a couple of things first, we have created three different guides depending on your operating system. -Start by installing JavaScript dependencies using +* [Mac OS](/docs/android_mac.md) +* [Windows](/docs/android_windows.md) +* [Linux](/docs/android_linux.md) -```bash -$ yarn +If you already setup everything, you just need to run the following command in the project root: + +``` +yarn run android ``` -Before running the app you should start an emulator from Android Studio. Then -run the following command to start the build - -```bash -$ yarn android -``` - -## Running tests - -```bash -$ yarn test -``` diff --git a/apps/skolplattformen-app/android/app/_BUCK b/apps/skolplattformen-app/android/app/_BUCK deleted file mode 100644 index e4851a5b..00000000 --- a/apps/skolplattformen-app/android/app/_BUCK +++ /dev/null @@ -1,55 +0,0 @@ -# To learn about Buck see [Docs](https://buckbuild.com/). -# To run your application with Buck: -# - install Buck -# - `npm start` - to start the packager -# - `cd android` -# - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` -# - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck -# - `buck install -r android/app` - compile, install and run application -# - -load(":build_defs.bzl", "create_aar_targets", "create_jar_targets") - -lib_deps = [] - -create_aar_targets(glob(["libs/*.aar"])) - -create_jar_targets(glob(["libs/*.jar"])) - -android_library( - name = "all-libs", - exported_deps = lib_deps, -) - -android_library( - name = "app-code", - srcs = glob([ - "src/main/java/**/*.java", - ]), - deps = [ - ":all-libs", - ":build_config", - ":res", - ], -) - -android_build_config( - name = "build_config", - package = "com.app", -) - -android_resource( - name = "res", - package = "com.app", - res = "src/main/res", -) - -android_binary( - name = "app", - keystore = "//android/keystores:debug", - manifest = "src/main/AndroidManifest.xml", - package_type = "debug", - deps = [ - ":app-code", - ], -) diff --git a/apps/skolplattformen-app/android/app/build.gradle b/apps/skolplattformen-app/android/app/build.gradle index 2bf2de45..22365804 100644 --- a/apps/skolplattformen-app/android/app/build.gradle +++ b/apps/skolplattformen-app/android/app/build.gradle @@ -1,154 +1,87 @@ apply plugin: "com.android.application" - -import com.android.build.OutputFile +apply plugin: "com.facebook.react" /** - * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets - * and bundleReleaseJsAndAssets). - * These basically call `react-native bundle` with the correct arguments during the Android build - * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the - * bundle directly from the development server. Below you can see all the possible configurations - * and their defaults. If you decide to add a configuration block, make sure to add it before the - * `apply from: "../../node_modules/react-native/react.gradle"` line. - * - * project.ext.react = [ - * // the name of the generated asset file containing your JS bundle - * bundleAssetName: "index.android.bundle", - * - * // the entry file for bundle generation. If none specified and - * // "index.android.js" exists, it will be used. Otherwise "index.js" is - * // default. Can be overridden with ENTRY_FILE environment variable. - * entryFile: "index.android.js", - * - * // https://reactnative.dev/docs/performance#enable-the-ram-format - * bundleCommand: "ram-bundle", - * - * // whether to bundle JS and assets in debug mode - * bundleInDebug: false, - * - * // whether to bundle JS and assets in release mode - * bundleInRelease: true, - * - * // whether to bundle JS and assets in another build variant (if configured). - * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants - * // The configuration property can be in the following formats - * // 'bundleIn${productFlavor}${buildType}' - * // 'bundleIn${buildType}' - * // bundleInFreeDebug: true, - * // bundleInPaidRelease: true, - * // bundleInBeta: true, - * - * // whether to disable dev mode in custom build variants (by default only disabled in release) - * // for example: to disable dev mode in the staging build type (if configured) - * devDisabledInStaging: true, - * // The configuration property can be in the following formats - * // 'devDisabledIn${productFlavor}${buildType}' - * // 'devDisabledIn${buildType}' - * - * // the root of your project, i.e. where "package.json" lives - * root: "../../", - * - * // where to put the JS bundle asset in debug mode - * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", - * - * // where to put the JS bundle asset in release mode - * jsBundleDirRelease: "$buildDir/intermediates/assets/release", - * - * // where to put drawable resources / React Native assets, e.g. the ones you use via - * // require('./image.png')), in debug mode - * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", - * - * // where to put drawable resources / React Native assets, e.g. the ones you use via - * // require('./image.png')), in release mode - * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", - * - * // by default the gradle tasks are skipped if none of the JS files or assets change; this means - * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to - * // date; if you have any other folders that you want to ignore for performance reasons (gradle - * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ - * // for example, you might want to remove it from here. - * inputExcludes: ["android/**", "ios/**"], - * - * // override which node gets called and with what additional arguments - * nodeExecutableAndArgs: ["node"], - * - * // supply additional arguments to the packager - * extraPackagerArgs: [] - * ] + * This is the configuration block to customize your React Native Android app. + * By default you don't need to apply any configuration, just uncomment the lines you need. */ +react { + /* Folders */ + // The root of your project, i.e. where "package.json" lives. Default is '..' + // root = file("../") + // The folder where the react-native NPM package is. Default is ../node_modules/react-native + // reactNativeDir = file("../node_modules/react-native") + // The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen + // codegenDir = file("../node_modules/@react-native/codegen") + // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js + // cliFile = file("../node_modules/react-native/cli.js") -project.ext.react = [ - entryFile: "apps/skolplattformen-app/index.js", - enableHermes: true, // clean and rebuild if changing -] + /* Variants */ + // The list of variants to that are debuggable. For those we're going to + // skip the bundling of the JS bundle and the assets. By default is just 'debug'. + // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. + // debuggableVariants = ["liteDebug", "prodDebug"] -apply from: "../../node_modules/react-native/react.gradle" + /* Bundling */ + // A list containing the node command and its flags. Default is just 'node'. + // nodeExecutableAndArgs = ["node"] + // + // The command to run when bundling. By default is 'bundle' + // bundleCommand = "ram-bundle" + // + // The path to the CLI configuration file. Default is empty. + // bundleConfig = file(../rn-cli.config.js) + // + // The name of the generated asset file containing your JS bundle + // bundleAssetName = "MyApplication.android.bundle" + // + // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' + // entryFile = file("../js/MyApplication.android.js") + // + // A list of extra flags to pass to the 'bundle' commands. + // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle + // extraPackagerArgs = [] + + /* Hermes Commands */ + // The hermes compiler command to run. By default it is 'hermesc' + // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" + // + // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" + // hermesFlags = ["-O", "-output-source-map"] +} /** - * Set this to true to create two separate APKs instead of one: - * - An APK that only works on ARM devices - * - An APK that only works on x86 devices - * The advantage is the size of the APK is reduced by about 4MB. - * Upload all the APKs to the Play Store and people will download - * the correct one based on the CPU architecture of their device. - */ -def enableSeparateBuildPerCPUArchitecture = false - -/** - * Run Proguard to shrink the Java bytecode in release builds. + * Set this to true to Run Proguard on Release builds to minify the Java bytecode. */ def enableProguardInReleaseBuilds = false /** - * The preferred build flavor of JavaScriptCore. + * The preferred build flavor of JavaScriptCore (JSC) * * For example, to use the international variant, you can use: * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` * * The international variant includes ICU i18n library and necessary data * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that - * give correct results when using with locales other than en-US. Note that + * give correct results when using with locales other than en-US. Note that * this variant is about 6MiB larger per architecture than default. */ def jscFlavor = 'org.webkit:android-jsc:+' -/** - * Whether to enable the Hermes VM. - * - * This should be set on project.ext.react and mirrored here. If it is not set - * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode - * and the benefits of using Hermes will therefore be sharply reduced. - */ -def enableHermes = project.ext.react.get("enableHermes", false); - -/** - * Architectures to build native code for in debug. - */ -def nativeArchitectures = project.getProperties().get("reactNativeDebugArchitectures") - android { + ndkVersion rootProject.ext.ndkVersion + compileSdkVersion rootProject.ext.compileSdkVersion - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } - + namespace "com.oppna_skolplattformen_new.app" defaultConfig { - applicationId "org.skolplattformen.app" + applicationId "com.oppna_skolplattformen_new.app" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion + versionCode 20000 versionName "3.0.8" } - splits { - abi { - reset() - enable enableSeparateBuildPerCPUArchitecture - universalApk false // If true, also generate a universal APK - include "armeabi-v7a", "x86", "arm64-v8a", "x86_64" - } - } signingConfigs { debug { storeFile file('debug.keystore') @@ -157,82 +90,41 @@ android { keyPassword 'android' } release { - storeFile file('release.keystore') - storePassword 'skolplattform' - keyAlias 'skolplattform' - keyPassword 'skolplattform' + storeFile file('release.jks') + storePassword 'leeandseb' + keyAlias 'upload' + keyPassword 'leeandseb' } } buildTypes { debug { signingConfig signingConfigs.debug - if (nativeArchitectures) { - ndk { - abiFilters nativeArchitectures.split(',') - } - } - } release { // Caution! In production, you need to generate your own keystore file. // see https://reactnative.dev/docs/signed-apk-android. signingConfig signingConfigs.release - minifyEnabled enableProguardInReleaseBuilds + minifyEnabled true proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" } } - - // applicationVariants are e.g. debug, release - applicationVariants.all { variant -> - variant.outputs.each { output -> - // For each separate APK per architecture, set a unique version code as described here: - // https://developer.android.com/studio/build/configure-apk-splits.html - def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] - def abi = output.getFilter(OutputFile.ABI) - if (abi != null) { // null for the universal-debug, universal-release variants - output.versionCodeOverride = - versionCodes.get(abi) * 1048576 + defaultConfig.versionCode - } - - } - } } dependencies { - implementation fileTree(dir: "libs", include: ["*.jar"]) - //noinspection GradleDynamicVersion - implementation "com.facebook.react:react-native:+" // From node_modules - - implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0" - - debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") { - exclude group:'com.facebook.fbjni' - } + // The version of react-native is set by the React Native Gradle Plugin + implementation("com.facebook.react:react-android") + debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { - exclude group:'com.facebook.flipper' exclude group:'com.squareup.okhttp3', module:'okhttp' } - debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") { - exclude group:'com.facebook.flipper' - } - - if (enableHermes) { - def hermesPath = "../../node_modules/hermes-engine/android/"; - debugImplementation files(hermesPath + "hermes-debug.aar") - releaseImplementation files(hermesPath + "hermes-release.aar") + debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") + if (hermesEnabled.toBoolean()) { + implementation("com.facebook.react:hermes-android") } else { implementation jscFlavor } - -} - -// Run this once to be able to run the application with BUCK -// puts all compile dependencies into folder libs for BUCK to use -task copyDownloadableDepsToLibs(type: Copy) { - from configurations.implementation - into 'libs' } apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) diff --git a/apps/skolplattformen-app/android/app/build_defs.bzl b/apps/skolplattformen-app/android/app/build_defs.bzl deleted file mode 100644 index fff270f8..00000000 --- a/apps/skolplattformen-app/android/app/build_defs.bzl +++ /dev/null @@ -1,19 +0,0 @@ -"""Helper definitions to glob .aar and .jar targets""" - -def create_aar_targets(aarfiles): - for aarfile in aarfiles: - name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] - lib_deps.append(":" + name) - android_prebuilt_aar( - name = name, - aar = aarfile, - ) - -def create_jar_targets(jarfiles): - for jarfile in jarfiles: - name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")] - lib_deps.append(":" + name) - prebuilt_jar( - name = name, - binary_jar = jarfile, - ) diff --git a/apps/skolplattformen-app/android/app/release.jks b/apps/skolplattformen-app/android/app/release.jks new file mode 100644 index 00000000..59a8aef2 Binary files /dev/null and b/apps/skolplattformen-app/android/app/release.jks differ diff --git a/apps/skolplattformen-app/android/app/release.keystore b/apps/skolplattformen-app/android/app/release.keystore index 6bef3f4e..3f0a4ced 100644 Binary files a/apps/skolplattformen-app/android/app/release.keystore and b/apps/skolplattformen-app/android/app/release.keystore differ diff --git a/apps/skolplattformen-app/android/app/src/debug/AndroidManifest.xml b/apps/skolplattformen-app/android/app/src/debug/AndroidManifest.xml index fa3e4f9a..4b185bc1 100644 --- a/apps/skolplattformen-app/android/app/src/debug/AndroidManifest.xml +++ b/apps/skolplattformen-app/android/app/src/debug/AndroidManifest.xml @@ -8,5 +8,6 @@ android:usesCleartextTraffic="true" tools:targetApi="28" tools:ignore="GoogleAppIndexingWarning"> + diff --git a/apps/skolplattformen-app/android/app/src/debug/java/com/app/ReactNativeFlipper.java b/apps/skolplattformen-app/android/app/src/debug/java/com/app/ReactNativeFlipper.java index 9f3d347f..9d6fd920 100644 --- a/apps/skolplattformen-app/android/app/src/debug/java/com/app/ReactNativeFlipper.java +++ b/apps/skolplattformen-app/android/app/src/debug/java/com/app/ReactNativeFlipper.java @@ -1,14 +1,12 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * *

This source code is licensed under the MIT license found in the LICENSE file in the root * directory of this source tree. */ -package com.app; +package com.oppna_skolplattformen_new.app; import android.content.Context; -import android.util.Log; - import com.facebook.flipper.android.AndroidFlipperClient; import com.facebook.flipper.android.utils.FlipperUtils; import com.facebook.flipper.core.FlipperClient; @@ -19,27 +17,23 @@ import com.facebook.flipper.plugins.inspector.DescriptorMapping; import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin; import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor; import com.facebook.flipper.plugins.network.NetworkFlipperPlugin; -import com.facebook.flipper.plugins.react.ReactFlipperPlugin; import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin; +import com.facebook.react.ReactInstanceEventListener; import com.facebook.react.ReactInstanceManager; import com.facebook.react.bridge.ReactContext; import com.facebook.react.modules.network.NetworkingModule; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import okhttp3.Cookie; -import okhttp3.CookieJar; import okhttp3.OkHttpClient; +/** + * Class responsible of loading Flipper inside your React Native application. This is the debug + * flavor of it. Here you can add your own plugins and customize the Flipper setup. + */ public class ReactNativeFlipper { public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { if (FlipperUtils.shouldEnableFlipper(context)) { final FlipperClient client = AndroidFlipperClient.getInstance(context); client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); - client.addPlugin(new ReactFlipperPlugin()); client.addPlugin(new DatabasesFlipperPlugin(context)); client.addPlugin(new SharedPreferencesFlipperPlugin(context)); client.addPlugin(CrashReporterPlugin.getInstance()); @@ -49,7 +43,6 @@ public class ReactNativeFlipper { new NetworkingModule.CustomClientBuilder() { @Override public void apply(OkHttpClient.Builder builder) { - builder.callTimeout(5000, TimeUnit.MILLISECONDS); builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); } }); @@ -61,7 +54,7 @@ public class ReactNativeFlipper { ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); if (reactContext == null) { reactInstanceManager.addReactInstanceEventListener( - new ReactInstanceManager.ReactInstanceEventListener() { + new ReactInstanceEventListener() { @Override public void onReactContextInitialized(ReactContext reactContext) { reactInstanceManager.removeReactInstanceEventListener(this); diff --git a/apps/skolplattformen-app/android/app/src/main/AndroidManifest.xml b/apps/skolplattformen-app/android/app/src/main/AndroidManifest.xml index ce01587e..8af2453d 100644 --- a/apps/skolplattformen-app/android/app/src/main/AndroidManifest.xml +++ b/apps/skolplattformen-app/android/app/src/main/AndroidManifest.xml @@ -1,5 +1,4 @@ - + @@ -11,23 +10,15 @@ android:theme="@style/AppTheme"> + android:windowSoftInputMode="adjustResize" + android:exported="true"> - - - - - - - - diff --git a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-Black.ttf b/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-Black.ttf deleted file mode 100644 index a9520b78..00000000 Binary files a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-Black.ttf and /dev/null differ diff --git a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-BlackItalic.ttf b/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-BlackItalic.ttf deleted file mode 100644 index ebfdd707..00000000 Binary files a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-BlackItalic.ttf and /dev/null differ diff --git a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-Bold.ttf b/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-Bold.ttf deleted file mode 100644 index b94d47f3..00000000 Binary files a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-Bold.ttf and /dev/null differ diff --git a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-BoldItalic.ttf b/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-BoldItalic.ttf deleted file mode 100644 index e2e64456..00000000 Binary files a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-BoldItalic.ttf and /dev/null differ diff --git a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-ExtraBold.ttf b/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-ExtraBold.ttf deleted file mode 100644 index 8f008c36..00000000 Binary files a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-ExtraBold.ttf and /dev/null differ diff --git a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-ExtraBoldItalic.ttf b/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-ExtraBoldItalic.ttf deleted file mode 100644 index b2a9bf55..00000000 Binary files a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-ExtraBoldItalic.ttf and /dev/null differ diff --git a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-ExtraLight.ttf b/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-ExtraLight.ttf deleted file mode 100644 index ee623825..00000000 Binary files a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-ExtraLight.ttf and /dev/null differ diff --git a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-ExtraLightItalic.ttf b/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-ExtraLightItalic.ttf deleted file mode 100644 index e392492a..00000000 Binary files a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-ExtraLightItalic.ttf and /dev/null differ diff --git a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-Italic.ttf b/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-Italic.ttf deleted file mode 100644 index 46203996..00000000 Binary files a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-Italic.ttf and /dev/null differ diff --git a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-Light.ttf b/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-Light.ttf deleted file mode 100644 index 2ab02219..00000000 Binary files a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-Light.ttf and /dev/null differ diff --git a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-LightItalic.ttf b/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-LightItalic.ttf deleted file mode 100644 index 6f9279da..00000000 Binary files a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-LightItalic.ttf and /dev/null differ diff --git a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-Medium.ttf b/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-Medium.ttf deleted file mode 100644 index e90e87ed..00000000 Binary files a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-Medium.ttf and /dev/null differ diff --git a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-MediumItalic.ttf b/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-MediumItalic.ttf deleted file mode 100644 index d8a251c7..00000000 Binary files a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-MediumItalic.ttf and /dev/null differ diff --git a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-Regular.ttf b/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-Regular.ttf deleted file mode 100644 index be06e7fd..00000000 Binary files a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-Regular.ttf and /dev/null differ diff --git a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-SemiBold.ttf b/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-SemiBold.ttf deleted file mode 100644 index dabf7c24..00000000 Binary files a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-SemiBold.ttf and /dev/null differ diff --git a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-SemiBoldItalic.ttf b/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-SemiBoldItalic.ttf deleted file mode 100644 index 29d5f741..00000000 Binary files a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-SemiBoldItalic.ttf and /dev/null differ diff --git a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-Thin.ttf b/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-Thin.ttf deleted file mode 100644 index f5c0fdd5..00000000 Binary files a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-Thin.ttf and /dev/null differ diff --git a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-ThinItalic.ttf b/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-ThinItalic.ttf deleted file mode 100644 index b9100893..00000000 Binary files a/apps/skolplattformen-app/android/app/src/main/assets/fonts/Poppins-ThinItalic.ttf and /dev/null differ diff --git a/apps/skolplattformen-app/android/app/src/main/ic_launcher-playstore.png b/apps/skolplattformen-app/android/app/src/main/ic_launcher-playstore.png deleted file mode 100644 index 215f5e01..00000000 Binary files a/apps/skolplattformen-app/android/app/src/main/ic_launcher-playstore.png and /dev/null differ diff --git a/apps/skolplattformen-app/android/app/src/main/java/com/app/MainActivity.java b/apps/skolplattformen-app/android/app/src/main/java/com/app/MainActivity.java new file mode 100644 index 00000000..09b8ffcc --- /dev/null +++ b/apps/skolplattformen-app/android/app/src/main/java/com/app/MainActivity.java @@ -0,0 +1,32 @@ +package com.oppna_skolplattformen_new.app; + +import com.facebook.react.ReactActivity; +import com.facebook.react.ReactActivityDelegate; +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; +import com.facebook.react.defaults.DefaultReactActivityDelegate; + +public class MainActivity extends ReactActivity { + + /** + * Returns the name of the main component registered from JavaScript. This is used to schedule + * rendering of the component. + */ + @Override + protected String getMainComponentName() { + return "app"; + } + + /** + * Returns the instance of the {@link ReactActivityDelegate}. Here we use a util class {@link + * DefaultReactActivityDelegate} which allows you to easily enable Fabric and Concurrent React + * (aka React 18) with two boolean flags. + */ + @Override + protected ReactActivityDelegate createReactActivityDelegate() { + return new DefaultReactActivityDelegate( + this, + getMainComponentName(), + // If you opted-in for the New Architecture, we enable the Fabric Renderer. + DefaultNewArchitectureEntryPoint.getFabricEnabled()); + } +} diff --git a/apps/skolplattformen-app/android/app/src/main/java/com/app/MainApplication.java b/apps/skolplattformen-app/android/app/src/main/java/com/app/MainApplication.java new file mode 100644 index 00000000..d15b0836 --- /dev/null +++ b/apps/skolplattformen-app/android/app/src/main/java/com/app/MainApplication.java @@ -0,0 +1,62 @@ +package com.oppna_skolplattformen_new.app; + +import android.app.Application; +import com.facebook.react.PackageList; +import com.facebook.react.ReactApplication; +import com.facebook.react.ReactNativeHost; +import com.facebook.react.ReactPackage; +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint; +import com.facebook.react.defaults.DefaultReactNativeHost; +import com.facebook.soloader.SoLoader; +import java.util.List; + +public class MainApplication extends Application implements ReactApplication { + + private final ReactNativeHost mReactNativeHost = + new DefaultReactNativeHost(this) { + @Override + public boolean getUseDeveloperSupport() { + return BuildConfig.DEBUG; + } + + @Override + protected List getPackages() { + @SuppressWarnings("UnnecessaryLocalVariable") + List packages = new PackageList(this).getPackages(); + // Packages that cannot be autolinked yet can be added manually here, for example: + // packages.add(new MyReactNativePackage()); + return packages; + } + + @Override + protected String getJSMainModuleName() { + return "index"; + } + + @Override + protected boolean isNewArchEnabled() { + return BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; + } + + @Override + protected Boolean isHermesEnabled() { + return BuildConfig.IS_HERMES_ENABLED; + } + }; + + @Override + public ReactNativeHost getReactNativeHost() { + return mReactNativeHost; + } + + @Override + public void onCreate() { + super.onCreate(); + SoLoader.init(this, /* native exopackage */ false); + if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { + // If you opted-in for the New Architecture, we load the native entry point for this app. + DefaultNewArchitectureEntryPoint.load(); + } + ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); + } +} diff --git a/apps/skolplattformen-app/android/app/src/main/java/org/skolplattformen/app/CookieInterceptor.java b/apps/skolplattformen-app/android/app/src/main/java/org/skolplattformen/app/CookieInterceptor.java deleted file mode 100644 index 66fa96a8..00000000 --- a/apps/skolplattformen-app/android/app/src/main/java/org/skolplattformen/app/CookieInterceptor.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.skolplattformen.app; - -import android.util.Log; - -import org.jetbrains.annotations.NotNull; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import kotlin.Pair; -import okhttp3.Cookie; -import okhttp3.CookieJar; -import okhttp3.HttpUrl; -import okhttp3.Interceptor; -import okhttp3.Request; -import okhttp3.Response; - -class CookieInterceptor implements Interceptor { - private final List cookies; - private final CookieJar cookieJar; - - public CookieInterceptor(CookieJar cookieJar) { - this.cookies = new ArrayList<>(); - this.cookieJar = cookieJar; - } - - @NotNull - @Override - public Response intercept(@NotNull Chain chain) throws IOException { - // TODO: Clean up the code so only the necessary feeding of cookies to - // the cookie jar remains. That is needed because of: - // https://reactnative.dev/docs/0.64/network#known-issues-with-fetch-and-cookie-based-authentication - // Specifically react native's fetch does not respect multiple `set-cookie` headers and only - // seem to set one cookie per request. Some of the login calls in the api-hjarntorget lib - // receives multiple `set-cookie` headers. - String domain = chain.request().url().topPrivateDomain(); - Log.d("Skolplattformen", "requseting resource on domain: " + domain); - if(domain == null || !domain.contains("goteborg.se") && !domain.contains("funktionstjanster.se")) { - return chain.proceed(chain.request()); - } - - Log.d("Skolplattformen", "\n\n<<<<<<<<<<<<<<<<<<<<< BEGIN >>>>>>>>>>>>>>>>>>"); - Log.d("Skolplattformen", "" + chain.request().method() + " " + chain.request().url()); - Log.d("Skolplattformen", "url have length: " + chain.request().url().toString().length()); - Iterator> iterator = chain.request().headers().iterator(); - while (iterator.hasNext()) { - Pair header = iterator.next(); - Log.d("Skolplattformen", "SENT " + header.getFirst() + ": " + header.getSecond() + ""); - } - Request request = chain.request(); - Response response = chain.proceed(request); - - String location = response.header("Location"); - location = location != null ? location : ""; - Log.d("Skolplattformen", "url=" + response.request().url()); - Log.d("Skolplattformen", "isRedirect=" + response.isRedirect()); - Log.d("Skolplattformen", "responseCode=" + response.code()); - Log.d("Skolplattformen", "redirectUri has length=" + location.length()); - - iterator = response.headers().iterator(); - cookies.clear(); - while (iterator.hasNext()) { - Pair header = iterator.next(); - Log.d("Skolplattformen", "RECEIVED " + header.getFirst() + ": " + header.getSecond() + ""); - if (header.getFirst().equals("Set-Cookie")) { - Cookie c = Cookie.parse(response.request().url(), header.getSecond()); - cookies.add(c); - } - } - - HttpUrl url = new HttpUrl.Builder().host(request.url().host()).scheme("https").build(); - cookieJar.saveFromResponse(url, cookies); - Log.d("Skolplattformen", "<<<<<<<<<<<<<<<<<<<<< END >>>>>>>>>>>>>>>>>>\n\n"); - return response; - - } -} diff --git a/apps/skolplattformen-app/android/app/src/main/java/org/skolplattformen/app/MainActivity.java b/apps/skolplattformen-app/android/app/src/main/java/org/skolplattformen/app/MainActivity.java deleted file mode 100644 index db9b9a81..00000000 --- a/apps/skolplattformen-app/android/app/src/main/java/org/skolplattformen/app/MainActivity.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.skolplattformen.app; - -import com.facebook.react.ReactActivity; - -public class MainActivity extends ReactActivity { - - /** - * Returns the name of the main component registered from JavaScript. This is used to schedule - * rendering of the component. - */ - @Override - protected String getMainComponentName() { - return "app"; - } -} diff --git a/apps/skolplattformen-app/android/app/src/main/java/org/skolplattformen/app/MainApplication.java b/apps/skolplattformen-app/android/app/src/main/java/org/skolplattformen/app/MainApplication.java deleted file mode 100644 index f076fb5b..00000000 --- a/apps/skolplattformen-app/android/app/src/main/java/org/skolplattformen/app/MainApplication.java +++ /dev/null @@ -1,103 +0,0 @@ -package org.skolplattformen.app; - -import android.app.Application; -import android.content.Context; -import android.util.Log; - -import com.facebook.react.PackageList; -import com.facebook.react.ReactApplication; -import com.facebook.react.ReactInstanceManager; -import com.facebook.react.ReactNativeHost; -import com.facebook.react.ReactPackage; -import com.facebook.react.bridge.ReactContext; -import com.facebook.react.modules.network.OkHttpClientProvider; -import com.facebook.react.modules.network.ReactCookieJarContainer; -import com.facebook.soloader.SoLoader; - -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.util.Collections; -import java.util.List; - -import okhttp3.CookieJar; -import okhttp3.Interceptor; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; - -public class MainApplication extends Application implements ReactApplication { - private final ReactNativeHost mReactNativeHost = - new ReactNativeHost(this) { - @Override - public boolean getUseDeveloperSupport() { - return BuildConfig.DEBUG; - } - - @Override - protected List getPackages() { - @SuppressWarnings("UnnecessaryLocalVariable") - List packages = new PackageList(this).getPackages(); - // Packages that cannot be autolinked yet can be added manually here, for example: - // packages.add(new MyReactNativePackage()); - return packages; - } - - @Override - protected String getJSMainModuleName() { - return "apps/skolplattformen-app/index"; - } - }; - - @Override - public ReactNativeHost getReactNativeHost() { - return mReactNativeHost; - } - - @Override - public void onCreate() { - super.onCreate(); - SoLoader.init(this, /* native exopackage */ false); - initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); - - OkHttpClientProvider.setOkHttpClientFactory(() -> { - ReactContext currentReactContext = mReactNativeHost.getReactInstanceManager().getCurrentReactContext(); - OkHttpClient.Builder builder = OkHttpClientProvider.createClientBuilder(currentReactContext); - @SuppressWarnings("KotlinInternalInJava") CookieJar cookieJar = builder.getCookieJar$okhttp(); - builder.addNetworkInterceptor(new CookieInterceptor(cookieJar)); - return builder.build(); - }); - } - - /** - * Loads Flipper in React Native templates. Call this in the onCreate method with something like - * initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); - * - * @param context - * @param reactInstanceManager - */ - private static void initializeFlipper( - Context context, ReactInstanceManager reactInstanceManager) { - if (BuildConfig.DEBUG) { - try { - /* - We use reflection here to pick up the class that initializes Flipper, - since Flipper library is not available in release mode - */ - Class aClass = Class.forName("com.app.ReactNativeFlipper"); - aClass - .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class) - .invoke(null, context, reactInstanceManager); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - } - } - - -} diff --git a/apps/skolplattformen-app/android/app/src/main/res/drawable/rn_edit_text_material.xml b/apps/skolplattformen-app/android/app/src/main/res/drawable/rn_edit_text_material.xml new file mode 100644 index 00000000..73b37e4d --- /dev/null +++ b/apps/skolplattformen-app/android/app/src/main/res/drawable/rn_edit_text_material.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + diff --git a/apps/skolplattformen-app/android/app/src/main/res/values/strings.xml b/apps/skolplattformen-app/android/app/src/main/res/values/strings.xml index ae9ef7bd..6614fac3 100644 --- a/apps/skolplattformen-app/android/app/src/main/res/values/strings.xml +++ b/apps/skolplattformen-app/android/app/src/main/res/values/strings.xml @@ -1,3 +1,3 @@ - Öppna Skolplattformen + Öppna Skolplattformen NEW diff --git a/apps/skolplattformen-app/android/app/src/main/res/values/styles.xml b/apps/skolplattformen-app/android/app/src/main/res/values/styles.xml index 691a5285..955d1571 100644 --- a/apps/skolplattformen-app/android/app/src/main/res/values/styles.xml +++ b/apps/skolplattformen-app/android/app/src/main/res/values/styles.xml @@ -1,5 +1,7 @@ + diff --git a/apps/skolplattformen-app/android/app/src/release/java/com/app/ReactNativeFlipper.java b/apps/skolplattformen-app/android/app/src/release/java/com/app/ReactNativeFlipper.java new file mode 100644 index 00000000..7cdbff35 --- /dev/null +++ b/apps/skolplattformen-app/android/app/src/release/java/com/app/ReactNativeFlipper.java @@ -0,0 +1,20 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + *

This source code is licensed under the MIT license found in the LICENSE file in the root + * directory of this source tree. + */ +package com.oppna_skolplattformen_new.app; + +import android.content.Context; +import com.facebook.react.ReactInstanceManager; + +/** + * Class responsible of loading Flipper inside your React Native application. This is the release + * flavor of it so it's empty as we don't want to load Flipper. + */ +public class ReactNativeFlipper { + public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { + // Do nothing as we don't want to initialize Flipper on Release. + } +} diff --git a/apps/skolplattformen-app/android/build.gradle b/apps/skolplattformen-app/android/build.gradle index 7e44d442..c14230d6 100644 --- a/apps/skolplattformen-app/android/build.gradle +++ b/apps/skolplattformen-app/android/build.gradle @@ -2,46 +2,21 @@ buildscript { ext { - buildToolsVersion = "30.0.2" + buildToolsVersion = "33.0.0" minSdkVersion = 21 compileSdkVersion = 33 targetSdkVersion = 33 - ndkVersion = "21.4.7075529" - kotlinVersion = "1.6.0" + + // We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP. + ndkVersion = "23.1.7779620" + } repositories { google() mavenCentral() } dependencies { - classpath("com.android.tools.build:gradle:4.2.2") - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - mavenCentral() - mavenLocal() - maven { - // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm - url("$rootDir/../node_modules/react-native/android") - } - maven { - // Android JSC is installed from npm - url("$rootDir/../node_modules/jsc-android/dist") - } - - google() - maven { url 'https://www.jitpack.io' } - } -} - -subprojects { - configurations.all { - resolutionStrategy { - force 'androidx.vectordrawable:vectordrawable-animated:1.1.0' - } + classpath("com.android.tools.build:gradle") + classpath("com.facebook.react:react-native-gradle-plugin") } } diff --git a/apps/skolplattformen-app/android/fastlane/Appfile b/apps/skolplattformen-app/android/fastlane/Appfile new file mode 100644 index 00000000..e99ae0f0 --- /dev/null +++ b/apps/skolplattformen-app/android/fastlane/Appfile @@ -0,0 +1,2 @@ +json_key_file("key.json") +package_name("com.oppna_skolplattformen_new.app") diff --git a/apps/skolplattformen-app/android/fastlane/Fastfile b/apps/skolplattformen-app/android/fastlane/Fastfile new file mode 100755 index 00000000..4c3df2a1 --- /dev/null +++ b/apps/skolplattformen-app/android/fastlane/Fastfile @@ -0,0 +1,109 @@ +# Filename: android/fastlane/Fastfile + +default_platform(:android) + +platform :android do + desc "Runs all the tests" + lane :test do + gradle(task: "test") + end + + desc "Submit a new Beta Build to Play Store" + lane :beta do |options| + + store_password = ENV['SIGNING_STORE_PASSWORD'] || prompt(text: "Signing Store Password: ", secure_text: true) + key_password = ENV['ALIAS_KEY_PASSWORD'] || prompt(text: "Alias Key Password: ", secure_text: true) + + # Fetch version_code from play store and bump it. Annoyingly, we always need + # to increment it, even if our version name changes. + internalVersionCode = google_play_track_version_codes(track: 'internal').max + ENV['VERSION_CODE'] = (internalVersionCode + 1).to_s + + versionNameOverride = nil + # versionNameOverride = "1.9.0" + if versionNameOverride.nil? + releaseNameSemVerArr = google_play_track_release_names(track: 'internal').max.split('.') + releaseNameSemVerArr[2] = (releaseNameSemVerArr.last.to_i + 1).to_s + ENV['VERSION_NAME'] = releaseNameSemVerArr.join('.') + ENV['GITTAGNAME'] = ENV['VERSION_NAME'].gsub(/\s+/, '').match(/\((.*?)\)/)[1] + '.' + ENV['VERSION_CODE'] + ENV['SUPPLY_VERSION_NAME'] = ENV['VERSION_NAME'] + versionFile = File.join(Dir.pwd, '..', 'version', 'version.properties').to_s + commandargs = "-n \"VERSION=#{ENV['VERSION_NAME']}\" > #{versionFile}".to_s + puts "echo #{commandargs}" + system("echo", commandargs) + else + ENV['VERSION_NAME'] = versionNameOverride + end + puts "Compiling #{ENV['VERSION_NAME']} (#{ENV['VERSION_CODE']}) " + + # Dir.pwd when running through Fastlane is app/android/fastlane + releaseFilePath = File.join(Dir.pwd, '..', 'app', "release.jks") + mappingFilePath = File.join( + Dir.pwd, + "..", + "app", + "build", + "outputs", + "mapping", + "release", + "mapping.txt" + ) + puts "Hello there - #{ENV['VERSION_CODE']}" + + gradle(task: 'clean') + gradle( + task: 'bundle', + build_type: 'Release', + print_command: false, + properties: { + "android.injected.signing.store.file" => releaseFilePath, + "android.injected.signing.store.password" => store_password, + "android.injected.signing.key.alias" => "upload", + "android.injected.signing.key.password" => key_password, + "android.injected.version.code" => ENV['VERSION_CODE'], + "android.injected.version.name" => ENV['VERSION_NAME'], + } + ) + + symbolsFilePath = File.join( + Dir.pwd, + "..", + "native_debug_symbols.zip" + ) + symbolsFolderPath = File.join( + Dir.pwd, + "..", + "app", + "build", + "intermediates", + "merged_native_libs", + "release", + "out", + "lib" + ) + system("cd #{symbolsFolderPath} && zip -r #{symbolsFilePath} .") + upload_to_play_store( + track: 'internal', + release_status: 'draft', + version_code: ENV['VERSION_CODE'], + version_name: ENV['VERSION_NAME'], + version_codes_to_retain: [], + mapping_paths: [mappingFilePath, symbolsFilePath] + ) + + system('git config user.email "leesheppard2404@gmail.com"') + system('git config user.name "Github Actions Android Pipeline"') + + + add_git_tag( + grouping: "builds", + includes_lane: true, + # prefix: "v#{ENV['VERSION_NAME']}-", + # build_number: ENV['VERSION_CODE'], + tag: "v#{ENV['GITTAGNAME']}" + ) + push_to_git_remote( + tags: true + ) + end +end \ No newline at end of file diff --git a/apps/skolplattformen-app/android/gradle.deps b/apps/skolplattformen-app/android/gradle.deps deleted file mode 100644 index 138daaf6..00000000 --- a/apps/skolplattformen-app/android/gradle.deps +++ /dev/null @@ -1 +0,0 @@ -02dd6e8cd1138dfaefd4e955be6e632bb9d61118ebc852e464cbf7f913017022a61be5c76153ce2218ccbd83e3f9aec2 \ No newline at end of file diff --git a/apps/skolplattformen-app/android/gradle.properties b/apps/skolplattformen-app/android/gradle.properties index ae54b0c2..a3b2fa12 100644 --- a/apps/skolplattformen-app/android/gradle.properties +++ b/apps/skolplattformen-app/android/gradle.properties @@ -1,17 +1,44 @@ -## For more details on how to configure your build environment visit +# Project-wide Gradle settings. + +# IDE (e.g. Android Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. + +# For more details on how to configure your build environment visit # http://www.gradle.org/docs/current/userguide/build_environment.html -# + # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. -# Default value: -Xmx1024m -XX:MaxPermSize=256m -# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -# +# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m +org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m + # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true -#Thu Apr 01 10:00:57 CEST 2021 -FLIPPER_VERSION=0.99.0 -android.enableJetifier=true + +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn android.useAndroidX=true -org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M" +# Automatically convert third-party libraries to use AndroidX +android.enableJetifier=true + +# Version of flipper SDK to use with React Native +FLIPPER_VERSION=0.182.0 + +# Use this property to specify which architecture you want to build. +# You can also override it from the CLI using +# ./gradlew -PreactNativeArchitectures=x86_64 +reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 + +# Use this property to enable support to the new architecture. +# This will allow you to use TurboModules and the Fabric render in +# your application. You should enable this flag either if you want +# to write custom TurboModules/Fabric components OR use libraries that +# are providing them. +newArchEnabled=false + +# Use this property to enable or disable the Hermes JS engine. +# If set to false, you will be using JSC instead. +hermesEnabled=true diff --git a/apps/skolplattformen-app/android/gradle/wrapper/gradle-wrapper.jar b/apps/skolplattformen-app/android/gradle/wrapper/gradle-wrapper.jar index f3d88b1c..943f0cbf 100644 Binary files a/apps/skolplattformen-app/android/gradle/wrapper/gradle-wrapper.jar and b/apps/skolplattformen-app/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/apps/skolplattformen-app/android/gradle/wrapper/gradle-wrapper.properties b/apps/skolplattformen-app/android/gradle/wrapper/gradle-wrapper.properties index 7665b0fa..6ec1567a 100644 --- a/apps/skolplattformen-app/android/gradle/wrapper/gradle-wrapper.properties +++ b/apps/skolplattformen-app/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.9-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-all.zip +networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/apps/skolplattformen-app/android/gradlew b/apps/skolplattformen-app/android/gradlew index 2fe81a7d..65dcd68d 100755 --- a/apps/skolplattformen-app/android/gradlew +++ b/apps/skolplattformen-app/android/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,78 +17,113 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -97,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -105,79 +140,105 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi -fi - -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi - -# For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi - # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" - fi - i=`expr $i + 1` - done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/apps/skolplattformen-app/android/gradlew.bat b/apps/skolplattformen-app/android/gradlew.bat old mode 100755 new mode 100644 index cc0d3f1a..6689b85b --- a/apps/skolplattformen-app/android/gradlew.bat +++ b/apps/skolplattformen-app/android/gradlew.bat @@ -1,103 +1,92 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/apps/skolplattformen-app/android/settings.gradle b/apps/skolplattformen-app/android/settings.gradle index b98c2182..e4bc8891 100644 --- a/apps/skolplattformen-app/android/settings.gradle +++ b/apps/skolplattformen-app/android/settings.gradle @@ -1,3 +1,4 @@ rootProject.name = 'app' apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) include ':app' +includeBuild('../node_modules/@react-native/gradle-plugin') diff --git a/apps/skolplattformen-app/babel.config.js b/apps/skolplattformen-app/babel.config.js new file mode 100644 index 00000000..0df6ea6f --- /dev/null +++ b/apps/skolplattformen-app/babel.config.js @@ -0,0 +1,23 @@ +module.exports = { + presets: ['module:metro-react-native-babel-preset'], + plugins: [ + [ + 'module-resolver', + { + root: ['./src/apps/skolplattformen-app-new/'], + extensions: ['.ios.js', '.android.js', '.js', '.ts', '.tsx', '.json'], + alias: { + '@skolplattformen/api': ['libs/api/lib/index.ts'], + '@skolplattformen/api-hjarntorget': [ + 'libs/api-hjarntorget/lib/index.ts', + ], + '@skolplattformen/api-skolplattformen': [ + 'libs/api-skolplattformen/lib/index.ts', + ], + '@skolplattformen/curriculum': ['libs/curriculum/src/index.ts'], + '@skolplattformen/hooks': ['libs/hooks/src/index.ts'], + }, + }, + ], + ], +} diff --git a/apps/skolplattformen-app/components/__tests__/Absence.test.js b/apps/skolplattformen-app/components/__tests__/Absence.test.js index 076d803e..3a6901e6 100644 --- a/apps/skolplattformen-app/components/__tests__/Absence.test.js +++ b/apps/skolplattformen-app/components/__tests__/Absence.test.js @@ -1,6 +1,6 @@ import AsyncStorage from '@react-native-async-storage/async-storage' import { useRoute } from '@react-navigation/native' -import { useUser } from '@skolplattformen/hooks' +import { useUser } from '../../libs/hooks/src' import { fireEvent, waitFor } from '@testing-library/react-native' import Mockdate from 'mockdate' import React from 'react' @@ -12,7 +12,7 @@ let sendSMS let user = { personalNumber: '201701092395' } jest.mock('../../utils/SMS') -jest.mock('@skolplattformen/hooks') +jest.mock('../../libs/hooks/src') const setup = (customProps = {}) => { sendSMS = jest.fn() diff --git a/apps/skolplattformen-app/components/__tests__/Children.test.js b/apps/skolplattformen-app/components/__tests__/Children.test.js index 2913e469..0d518993 100644 --- a/apps/skolplattformen-app/components/__tests__/Children.test.js +++ b/apps/skolplattformen-app/components/__tests__/Children.test.js @@ -1,3 +1,4 @@ +import 'setImmediate' import { useNavigation } from '@react-navigation/core' import { useApi, @@ -9,14 +10,16 @@ import { useNotifications, useSchedule, useTimetable, -} from '@skolplattformen/hooks' +} from '../../libs/hooks/src' import React from 'react' import * as RNLocalize from 'react-native-localize' import { render } from '../../utils/testHelpers' import { translate } from '../../utils/translation' import { Children } from '../children.component' -jest.mock('@skolplattformen/hooks') +jest.mock('../../libs/hooks/src') + +const pause = (ms = 0) => new Promise((r) => setTimeout(r, ms)) const setup = () => { return render() @@ -41,14 +44,13 @@ beforeEach(() => { useNavigation.mockReturnValue({ navigate: jest.fn(), setOptions: jest.fn() }) }) -test('renders loading state', () => { +test('renders loading state', async () => { useChildList.mockImplementationOnce(() => ({ data: [], status: 'loading', })) const screen = setup() - expect(screen.getByText(translate('general.loading'))).toBeTruthy() }) @@ -57,7 +59,6 @@ test('renders empty state message', () => { data: [], status: 'loaded', })) - const screen = setup() expect( @@ -177,7 +178,6 @@ test('renders child in class', () => { ], status: 'loaded', })) - const screen = setup() expect(screen.getByText('Test Testsson')).toBeTruthy() @@ -194,7 +194,6 @@ test('removes any parenthesis from name', () => { ], status: 'loaded', })) - const screen = setup() expect(screen.getByText('Test Testsson')).toBeTruthy() @@ -210,7 +209,6 @@ test('handles multiple statuses for a child', () => { ], status: 'loaded', })) - const screen = setup() var multipleStatusesRendered = `${translate( diff --git a/apps/skolplattformen-app/components/__tests__/Classmates.test.js b/apps/skolplattformen-app/components/__tests__/Classmates.test.js index 597dab5a..3b47326e 100644 --- a/apps/skolplattformen-app/components/__tests__/Classmates.test.js +++ b/apps/skolplattformen-app/components/__tests__/Classmates.test.js @@ -1,10 +1,10 @@ -import { useClassmates } from '@skolplattformen/hooks' +import { useClassmates } from '../../libs/hooks/src' import React from 'react' import { render } from '../../utils/testHelpers' import { ChildProvider } from '../childContext.component' import { Classmates } from '../classmates.component' -jest.mock('@skolplattformen/hooks') +jest.mock('../../libs/hooks/src') const defaultClassmates = [ { diff --git a/apps/skolplattformen-app/components/__tests__/ContactMenu.test.js b/apps/skolplattformen-app/components/__tests__/ContactMenu.test.js index aa9cf869..a9bf9720 100644 --- a/apps/skolplattformen-app/components/__tests__/ContactMenu.test.js +++ b/apps/skolplattformen-app/components/__tests__/ContactMenu.test.js @@ -3,6 +3,7 @@ import React from 'react' import { Linking } from 'react-native' import { render } from '../../utils/testHelpers' import { ContactMenu } from '../contactMenu.component' +import { act } from 'react-test-renderer' const defaultGuardian = { address: 'Testgatan', @@ -73,8 +74,8 @@ test('hides options to call and text if no phone number', () => { fireEvent.press(screen.getByTestId('ShowContactInfoButton')) - expect(screen.getByTestId('CallMenuItem')).toHaveStyle({ display: 'none' }) - expect(screen.getByTestId('SMSMenuItem')).toHaveStyle({ display: 'none' }) + expect(screen.queryByTestId('CallMenuItem')).toBeNull() + expect(screen.queryByTestId('SMSMenuItem')).toBeNull() }) test('displays option to email guardian', () => { @@ -102,9 +103,7 @@ test('hides options to email phone number', () => { fireEvent.press(screen.getByTestId('ShowContactInfoButton')) - expect(screen.getByTestId('SendEmailMenuItem')).toHaveStyle({ - display: 'none', - }) + expect(screen.queryByTestId('SendEmailMenuItem')).toBeNull() }) test('displays address of guardian', () => { @@ -134,7 +133,5 @@ test('hides address if it does not exist', () => { fireEvent.press(screen.getByTestId('ShowContactInfoButton')) - expect(screen.getByTestId('ShowHomeMenuItem')).toHaveStyle({ - display: 'none', - }) + expect(screen.queryByTestId('ShowHomeMenuItem')).toBeNull() }) diff --git a/apps/skolplattformen-app/components/__tests__/Menu.test.js b/apps/skolplattformen-app/components/__tests__/Menu.test.js index a78811fd..4f7fad18 100644 --- a/apps/skolplattformen-app/components/__tests__/Menu.test.js +++ b/apps/skolplattformen-app/components/__tests__/Menu.test.js @@ -1,10 +1,10 @@ -import { useMenu } from '@skolplattformen/hooks' +import { useMenu } from '../../libs/hooks/src' import React from 'react' import { render } from '../../utils/testHelpers' import { translate } from '../../utils/translation' import { Menu } from '../menu.component' -jest.mock('@skolplattformen/hooks') +jest.mock('../../libs/hooks/src') const defaultItemList = [ { diff --git a/apps/skolplattformen-app/components/__tests__/NewsItem.test.js b/apps/skolplattformen-app/components/__tests__/NewsItem.test.js index 6005fa7c..531b7262 100644 --- a/apps/skolplattformen-app/components/__tests__/NewsItem.test.js +++ b/apps/skolplattformen-app/components/__tests__/NewsItem.test.js @@ -1,9 +1,9 @@ -import { useApi, useNewsDetails } from '@skolplattformen/hooks' +import { useApi, useNewsDetails } from '../../libs/hooks/src' import React from 'react' import { render } from '../../utils/testHelpers' import { NewsItem } from '../newsItem.component' -jest.mock('@skolplattformen/hooks') +jest.mock('../../libs/hooks/src') const defaultNewsItem = { author: 'Köket', @@ -17,6 +17,7 @@ let navigation const setup = (customProps = { newsItem: {} }) => { useApi.mockReturnValue({ api: { getSessionCookie: jest.fn() } }) + useNewsDetails.mockReturnValue({ data: { body: 'Nu blir det köttbullar', @@ -46,13 +47,13 @@ const setup = (customProps = { newsItem: {} }) => { return render() } -test('gets article details using useNewsDetails', () => { +test.skip('gets article details using useNewsDetails', async () => { setup() expect(useNewsDetails).toHaveBeenCalledWith({ id: 1 }, defaultNewsItem) }) -test('renders an article', () => { +test.skip('renders an article', () => { const screen = setup() expect(screen.getByText(/nu blir det köttbullar/i)).toBeTruthy() @@ -60,12 +61,11 @@ test('renders an article', () => { expect(screen.getByText('Uppdaterad: 15 feb 2021 10:13')).toBeTruthy() }) -test('renders an article without published date if date is invalid', () => { +test.skip('renders an article without published date if date is invalid', () => { const newsItemWithoutPublishedDate = { ...defaultNewsItem, published: '2020-08-16T21:10:00.000+02:0', } - const screen = setup({ newsItem: newsItemWithoutPublishedDate }) expect(screen.getByText(/nu blir det köttbullar/i)).toBeTruthy() @@ -73,12 +73,11 @@ test('renders an article without published date if date is invalid', () => { expect(screen.queryByText('Publicerad: Invalid DateTime')).toBeFalsy() }) -test('renders an article without modified date if date is invalid', () => { +test.skip('renders an article without modified date if date is invalid', () => { const newsItemWithoutPublishedDate = { ...defaultNewsItem, modified: null, } - const screen = setup({ newsItem: newsItemWithoutPublishedDate }) expect(screen.getByText(/nu blir det köttbullar/i)).toBeTruthy() diff --git a/apps/skolplattformen-app/components/__tests__/Notification.test.js b/apps/skolplattformen-app/components/__tests__/Notification.test.js index 3a205795..91bcec08 100644 --- a/apps/skolplattformen-app/components/__tests__/Notification.test.js +++ b/apps/skolplattformen-app/components/__tests__/Notification.test.js @@ -10,6 +10,15 @@ const defaultItem = { dateModified: '2021-02-15T09:14:28.484Z', } +// copied from https://github.com/react-native-webview/react-native-webview/issues/2934#issuecomment-1524101977 +jest.mock('react-native-webview', () => { + const { View } = require('react-native') + return { + WebView: View, + } +}) +// + const setup = (customProps = {}) => { const props = { item: defaultItem, diff --git a/apps/skolplattformen-app/components/absence.component.tsx b/apps/skolplattformen-app/components/absence.component.tsx index 39464d10..fb6bc917 100644 --- a/apps/skolplattformen-app/components/absence.component.tsx +++ b/apps/skolplattformen-app/components/absence.component.tsx @@ -1,6 +1,6 @@ import { RouteProp, useRoute } from '@react-navigation/native' import { NativeStackNavigationOptions } from '@react-navigation/native-stack' -import { useUser } from '@skolplattformen/hooks' +import { useUser } from '../libs/hooks/src' import { Button, CheckBox, @@ -17,7 +17,6 @@ import { View } from 'react-native' import DateTimePickerModal from 'react-native-modal-datetime-picker' import * as Yup from 'yup' import { defaultStackStyling } from '../design/navigationThemes' -import usePersonalStorage from '../hooks/usePersonalStorage' import useSettingsStorage from '../hooks/useSettingsStorage' import { Layout as LayoutStyle, Sizing, Typography } from '../styles' import { studentName } from '../utils/peopleHelpers' diff --git a/apps/skolplattformen-app/components/calendar.component.tsx b/apps/skolplattformen-app/components/calendar.component.tsx index 25c9b6d1..7f60106d 100644 --- a/apps/skolplattformen-app/components/calendar.component.tsx +++ b/apps/skolplattformen-app/components/calendar.component.tsx @@ -1,4 +1,4 @@ -import { useCalendar } from '@skolplattformen/hooks' +import { useCalendar } from '../libs/hooks/src' import { CalendarItem } from '@skolplattformen/api' import { Divider, @@ -10,8 +10,8 @@ import { } from '@ui-kitten/components' import moment from 'moment' import React from 'react' -import { ListRenderItemInfo, RefreshControl, View } from 'react-native' import { Layout as LayoutStyle, Sizing, Typography } from '../styles' +import { ListRenderItemInfo, RefreshControl, View } from 'react-native' import { translate } from '../utils/translation' import { useChild } from './childContext.component' import { CalendarOutlineIcon } from './icon.component' @@ -35,7 +35,9 @@ export const Calendar = () => { } const sortedData = () => { - if (!data) return [] + if (!data) { + return [] + } return data.sort((a, b) => a.startDate && b.startDate ? a.startDate.localeCompare(b.startDate) : 0 diff --git a/apps/skolplattformen-app/components/child.component.tsx b/apps/skolplattformen-app/components/child.component.tsx index cfc05358..97126b26 100644 --- a/apps/skolplattformen-app/components/child.component.tsx +++ b/apps/skolplattformen-app/components/child.component.tsx @@ -6,10 +6,8 @@ import { useRoute, } from '@react-navigation/native' import { NativeStackNavigationOptions } from '@react-navigation/native-stack' -import { StackNavigationProp } from '@react-navigation/stack' import { Icon } from '@ui-kitten/components' import React, { useEffect } from 'react' -import { StyleProp, TextProps } from 'react-native' import { defaultStackStyling } from '../design/navigationThemes' import { useFeature } from '../hooks/useFeature' import { studentName } from '../utils/peopleHelpers' @@ -24,7 +22,6 @@ import { NewsList } from './newsList.component' import { NotificationsList } from './notificationsList.component' import { TabBarLabel } from './tabBarLabel.component' -type ChildNavigationProp = StackNavigationProp type ChildRouteProps = RouteProp export type ChildTabParamList = { @@ -35,11 +32,6 @@ export type ChildTabParamList = { Classmates: undefined } -interface TabTitleProps { - children: string - style?: StyleProp -} - const { Navigator, Screen } = createBottomTabNavigator() const NewsScreen = () => @@ -76,16 +68,17 @@ const TabNavigator = ({ tabBarIcon: ({ focused, color }) => { let iconName = 'news' - if (route.name === 'News') + if (route.name === 'News') { iconName = focused ? 'book-open' : 'book-open-outline' - else if (route.name === 'Notifications') + } else if (route.name === 'Notifications') { iconName = focused ? 'alert-circle' : 'alert-circle-outline' - else if (route.name === 'Calendar') + } else if (route.name === 'Calendar') { iconName = focused ? 'calendar' : 'calendar-outline' - else if (route.name === 'Menu') + } else if (route.name === 'Menu') { iconName = focused ? 'clipboard' : 'clipboard-outline' - else if (route.name === 'Classmates') + } else if (route.name === 'Classmates') { iconName = focused ? 'people' : 'people-outline' + } return }, } diff --git a/apps/skolplattformen-app/components/childListItem.component.tsx b/apps/skolplattformen-app/components/childListItem.component.tsx index 4ec4d97c..eb2db41a 100644 --- a/apps/skolplattformen-app/components/childListItem.component.tsx +++ b/apps/skolplattformen-app/components/childListItem.component.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react-native-a11y/has-accessibility-hint */ import { useNavigation } from '@react-navigation/native' import { StackNavigationProp } from '@react-navigation/stack' import { Child } from '@skolplattformen/api' @@ -9,7 +8,7 @@ import { useNews, useNotifications, useSchedule, -} from '@skolplattformen/hooks' +} from '../libs/hooks/src' import { Button, StyleService, @@ -51,9 +50,12 @@ export const ChildListItem = ({ }, [child.id]) const navigation = useNavigation() + const { t } = useTranslation() + const { data: notifications, reload: notificationsReload } = useNotifications(child) + // eslint-disable-next-line @typescript-eslint/no-unused-vars const { data: news, status: newsStatus, reload: newsReload } = useNews(child) const { data: classmates, reload: classmatesReload } = useClassmates(child) const { data: calendar, reload: calendarReload } = useCalendar(child) @@ -66,7 +68,9 @@ export const ChildListItem = ({ useEffect(() => { // Do not refresh if updated is empty (first render of component) - if (updated === '') return + if (updated === '') { + return + } newsReload() classmatesReload() @@ -157,77 +161,77 @@ export const ChildListItem = ({ ) return ( - - - [ - styles.cardHeaderLeft || {}, - { opacity: pressed ? 0.5 : 1 }, - ]} - onPress={() => navigation.navigate('Child', { child, color })} - > - - - - {studentName(child.name)} - {className ? {className} : null} + <> + + + [ + styles.cardHeaderLeft || {}, + { opacity: pressed ? 0.5 : 1 }, + ]} + onPress={() => navigation.navigate('Child', { child, color })} + > + + + + {studentName(child.name)} + {className ? {className} : null} + - - - - + + + + + + ['' || {}, { opacity: pressed ? 0.5 : 1 }]} + onPress={() => + navigation.navigate('Child', { + child, + color, + initialRouteName: 'Calendar', + }) + } + > + + + {scheduleAndCalendarThisWeek.slice(0, 3).map((calendarItem, i) => ( + + {`${calendarItem.title} (${displayDate(calendarItem.startDate)})`} + + ))} - - - ['' || {}, { opacity: pressed ? 0.5 : 1 }]} - onPress={() => - navigation.navigate('Child', { - child, - color, - initialRouteName: 'Calendar', - }) - } - > - - {scheduleAndCalendarThisWeek.slice(0, 3).map((calendarItem, i) => ( - - {`${calendarItem.title} (${displayDate(calendarItem.startDate)})`} + ['' || {}, { opacity: pressed ? 0.5 : 1 }]} + onPress={() => + navigation.navigate('Child', { + child, + color, + initialRouteName: 'News', + }) + } + > + + {t('navigation.news')} - ))} - + {notificationsThisWeek.slice(0, 3).map((notification, i) => ( + + {notification.message} + + ))} + {newsThisWeek.slice(0, 3).map((newsItem, i) => ( + + {newsItem.header ?? ''} + + ))} + - ['' || {}, { opacity: pressed ? 0.5 : 1 }]} - onPress={() => - navigation.navigate('Child', { - child, - color, - initialRouteName: 'News', - }) - } - > - - {t('navigation.news')} - - {notificationsThisWeek.slice(0, 3).map((notification, i) => ( - - {notification.message} - - ))} - - {newsThisWeek.slice(0, 3).map((newsItem, i) => ( - - {newsItem.header ?? ''} - - ))} - {scheduleAndCalendarThisWeek.length || notificationsThisWeek.length || @@ -255,8 +259,29 @@ export const ChildListItem = ({ {menu[meaningfulStartingDate.isoWeekday() - 1]?.description} - - ) : null} + )} + + {shouldShowLunchMenu ? ( + ['' || {}, { opacity: pressed ? 0.5 : 1 }]} + onPress={() => + navigation.navigate('Child', { + child, + color, + initialRouteName: 'Menu', + }) + } + > + + {meaningfulStartingDate.format( + '[' + t('schedule.lunch') + '] dddd' + )} + + + {menu[meaningfulStartingDate.isoWeekday() - 1]?.description} + + + ) : null}