Merge branch 'feature/frontend/deploy-to-stores'
Some checks failed
/ push-to-remote (push) Failing after 3s
39
frontend/.github/workflows/build_app_android.yaml
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: macos-lastest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Set up ruby env
|
||||
uses: ruby/setup-ruby@v1.138.0
|
||||
with:
|
||||
ruby-version: 3.2.1
|
||||
bundler-cache: true
|
||||
|
||||
- name: Setup java for android build
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'zulu'
|
||||
|
||||
- name: Setup android SDK
|
||||
uses: https://github.com/android-actions/setup-android@v3
|
||||
|
||||
- name: Infer version number from git tag
|
||||
id: version
|
||||
env:
|
||||
REF_NAME: ${{ github.ref_name }}
|
||||
run:
|
||||
# remove the 'v' prefix from the tag name
|
||||
echo "VERSION=${REF_NAME//v}" >> $GITHUB_ENV
|
||||
|
||||
- name: Run fastlane lane
|
||||
run: bundle exec fastlane deploy
|
||||
working-directory: android
|
||||
env:
|
||||
VERSION_NAME: ${{outputs.version.VERSION}}
|
@@ -1,6 +1,6 @@
|
||||
# Frontend
|
||||
|
||||
This is the frontend of the project. It is a Flutter application that is designed to run on both Android and iOS devices. The frontend is responsible for displaying the user interface and handling user input. It communicates with the backend to retrieve and send data.
|
||||
The frontend of this project is a Flutter application designed to run on both Android and iOS devices (and possibly as a PWA). The frontend is responsible for displaying the user interface and handling user input. It communicates with the backend via a REST-api to retrieve and send data.
|
||||
|
||||
|
||||
## Getting Started
|
||||
@@ -15,3 +15,43 @@ Once you have the Flutter SDK installed, you can locally install the dependencie
|
||||
```bash
|
||||
flutter pub get
|
||||
```
|
||||
|
||||
## Development
|
||||
### ...
|
||||
### Icons and logos
|
||||
The application uses a custom launcher icon and splash screen. These are managed platform-independently using the `flutter_launcher_icons` package.
|
||||
|
||||
To update the icons, change the `flutter_launcher_icons.yaml` configuration file. Especially the `image_path` is relevant. Then run
|
||||
```bash
|
||||
dart run flutter_launcher_icons
|
||||
```
|
||||
|
||||
### Deploying a new version
|
||||
To truly deploy a new version of the application, i.e. to the official app stores, a special CI step is required. This listens for new tags. To create a new tag position yourself on the main branch and run
|
||||
```bash
|
||||
git tag -a v<name> -m "Release <name>"
|
||||
git push origin v<name>
|
||||
```
|
||||
We adhere to the [Semantic Versioning](https://semver.org/) standard, so the tag should be of the form `v0.1.8` for example.
|
||||
|
||||
|
||||
## Fastlane - in depth
|
||||
The application is deployed to the Google Play Store and the Apple App Store using fastlane: [https://docs.fastlane.tools/](https://docs.fastlane.tools/)
|
||||
|
||||
Fastlane is installed as a Ruby gem. Since the bundler-gemfile is scoped to a single directory, a `Gemfile` is included in both the `android` and `ios` directories. Once installed, the usage is
|
||||
```bash
|
||||
cd frontend/android # or ios
|
||||
bundle install
|
||||
bundle exec fastlane <lane>
|
||||
```
|
||||
This is reused in the CI/CD pipeline to automate the deployment process.
|
||||
|
||||
Fastlane assumes mutliple secrets to be present as files in the platform directories. These are:
|
||||
- for android:
|
||||
- `secrets.properties` used by gradle to load secrets needed at execution time
|
||||
- `release.keystore` used by gradle to sign the apk
|
||||
- `google-key.json` used by fastlane to authenticate with the Google Play Store
|
||||
- for ios:
|
||||
- TODO
|
||||
|
||||
These files are stored as secrets in the GitHub repository so that the CI pipeline can access them.
|
3
frontend/android/.gitignore
vendored
@@ -12,3 +12,6 @@ GeneratedPluginRegistrant.java
|
||||
key.properties
|
||||
**/*.keystore
|
||||
**/*.jks
|
||||
|
||||
# Fastlane google cloud access
|
||||
google-key.json
|
||||
|
3
frontend/android/Gemfile
Normal file
@@ -0,0 +1,3 @@
|
||||
source "https://rubygems.org"
|
||||
|
||||
gem "fastlane"
|
220
frontend/android/Gemfile.lock
Normal file
@@ -0,0 +1,220 @@
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
CFPropertyList (3.0.7)
|
||||
base64
|
||||
nkf
|
||||
rexml
|
||||
addressable (2.8.7)
|
||||
public_suffix (>= 2.0.2, < 7.0)
|
||||
artifactory (3.0.17)
|
||||
atomos (0.1.3)
|
||||
aws-eventstream (1.3.0)
|
||||
aws-partitions (1.970.0)
|
||||
aws-sdk-core (3.202.2)
|
||||
aws-eventstream (~> 1, >= 1.3.0)
|
||||
aws-partitions (~> 1, >= 1.651.0)
|
||||
aws-sigv4 (~> 1.9)
|
||||
jmespath (~> 1, >= 1.6.1)
|
||||
aws-sdk-kms (1.88.0)
|
||||
aws-sdk-core (~> 3, >= 3.201.0)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sdk-s3 (1.159.0)
|
||||
aws-sdk-core (~> 3, >= 3.201.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sigv4 (1.9.1)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
babosa (1.0.4)
|
||||
base64 (0.2.0)
|
||||
claide (1.1.0)
|
||||
colored (1.2)
|
||||
colored2 (3.1.2)
|
||||
commander (4.6.0)
|
||||
highline (~> 2.0.0)
|
||||
declarative (0.0.20)
|
||||
digest-crc (0.6.5)
|
||||
rake (>= 12.0.0, < 14.0.0)
|
||||
domain_name (0.6.20240107)
|
||||
dotenv (2.8.1)
|
||||
emoji_regex (3.2.3)
|
||||
excon (0.111.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.2)
|
||||
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.3.1)
|
||||
fastlane (2.222.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 (~> 1.2)
|
||||
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-env (>= 1.6.0, < 2.0.0)
|
||||
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, < 1.0.0)
|
||||
plist (>= 3.1.0, < 4.0.0)
|
||||
rubyzip (>= 2.0.0, < 3.0.0)
|
||||
security (= 0.1.5)
|
||||
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, < 2.0.0)
|
||||
gh_inspector (1.1.3)
|
||||
google-apis-androidpublisher_v3 (0.54.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-apis-core (0.11.3)
|
||||
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
|
||||
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.31.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-cloud-core (1.7.1)
|
||||
google-cloud-env (>= 1.0, < 3.a)
|
||||
google-cloud-errors (~> 1.0)
|
||||
google-cloud-env (1.6.0)
|
||||
faraday (>= 0.17.3, < 3.0)
|
||||
google-cloud-errors (1.4.0)
|
||||
google-cloud-storage (1.47.0)
|
||||
addressable (~> 2.8)
|
||||
digest-crc (~> 0.4)
|
||||
google-apis-iamcredentials_v1 (~> 0.1)
|
||||
google-apis-storage_v1 (~> 0.31.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.7)
|
||||
domain_name (~> 0.5)
|
||||
httpclient (2.8.3)
|
||||
jmespath (1.6.2)
|
||||
json (2.7.2)
|
||||
jwt (2.8.2)
|
||||
base64
|
||||
mini_magick (4.13.2)
|
||||
mini_mime (1.1.5)
|
||||
multi_json (1.15.0)
|
||||
multipart-post (2.4.1)
|
||||
nanaimo (0.3.0)
|
||||
naturally (2.2.1)
|
||||
nkf (0.2.0)
|
||||
optparse (0.5.0)
|
||||
os (1.1.4)
|
||||
plist (3.7.1)
|
||||
public_suffix (6.0.1)
|
||||
rake (13.2.1)
|
||||
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.3.6)
|
||||
strscan
|
||||
rouge (2.0.7)
|
||||
ruby2_keywords (0.0.5)
|
||||
rubyzip (2.3.2)
|
||||
security (0.1.5)
|
||||
signet (0.19.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
|
||||
strscan (3.1.0)
|
||||
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.2)
|
||||
tty-spinner (0.9.3)
|
||||
tty-cursor (~> 0.7)
|
||||
uber (0.1.0)
|
||||
unicode-display_width (2.5.0)
|
||||
word_wrap (1.0.0)
|
||||
xcodeproj (1.25.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.3.2, < 4.0)
|
||||
xcpretty (0.3.0)
|
||||
rouge (~> 2.0.7)
|
||||
xcpretty-travis-formatter (1.0.1)
|
||||
xcpretty (~> 0.2, >= 0.0.7)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
x86_64-linux
|
||||
|
||||
DEPENDENCIES
|
||||
fastlane
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.18
|
@@ -2,13 +2,12 @@
|
||||
|
||||
### Keystore setup
|
||||
```bash
|
||||
keytool -genkey -v -keystore release.keystore -keyalg RSA -keysize 2048 -validity 10000 -alias release
|
||||
keytool -genkey -v -keystore release.keystore -keyalg RSA -keysize 2048 -validity 10000 -alias upload
|
||||
```
|
||||
- This is required to store local credentials securely (not used for now).
|
||||
- But necesseary in order to restrict the particular api key to a particular app (through the sha1 of the associated keystore).
|
||||
- This is required to store local credentials securely and more importantly to sign the app for google play store distribution.
|
||||
|
||||
|
||||
### Building and secret credentials
|
||||
### Using secret credentials during build
|
||||
Following the guide under [https://developers.google.com/maps/flutter-package/config#android_1](https://developers.google.com/maps/flutter-package/config#android_1).
|
||||
- Add the following to `android/build.gradle`:
|
||||
```gradle
|
||||
@@ -36,13 +35,39 @@ Following the guide under [https://developers.google.com/maps/flutter-package/co
|
||||
android:value="${MAPS_API_KEY}" />
|
||||
```
|
||||
|
||||
### Signing the app
|
||||
Compared to the flutter template application, a few changes have to be made:
|
||||
- Added to `android/app/build.gradle`:
|
||||
```gradle
|
||||
signingConfigs {
|
||||
release {
|
||||
keyAlias = secretProperties['keyAlias']
|
||||
keyPassword = secretProperties['keyPassword']
|
||||
storeFile = secretProperties['storeFile'] ? file(secretProperties['storeFile']) : null
|
||||
storePassword = secretProperties['storePassword']
|
||||
}
|
||||
}
|
||||
```
|
||||
- Changed the `buildTypes` to use the `release` signing config:
|
||||
```gradle
|
||||
buildTypes {
|
||||
release {
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
}
|
||||
```
|
||||
This makes use of the `secretProperties` defined previously:
|
||||
```gradle
|
||||
secretPropertiesFile.withReader('UTF-8') { reader ->
|
||||
secretProperties.load(reader)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Using the credentials in CI
|
||||
- Add the base64 encoded credentials to the repository secrets (e.g. `ANDROID_SECRETS`).
|
||||
- Add the secret files to the repository secrets (e.g. `ANDROID_SECRETS_PROPERTIES`).
|
||||
|
||||
- temporarily write them back to files during the CI execution:
|
||||
```bash
|
||||
base64 -i android/secrets.properties
|
||||
echo {{ secrets.ANDROID_SECRETS }} >> android/secrets.properties
|
||||
```
|
||||
- Use the following in the CI script:
|
||||
```bash
|
||||
echo {{ secrets.ANDROID_SECRETS }} | base64 -d > android/secrets.properties
|
||||
```
|
@@ -76,11 +76,18 @@ android {
|
||||
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
release {
|
||||
keyAlias = secretProperties['keyAlias']
|
||||
keyPassword = secretProperties['keyPassword']
|
||||
storeFile = secretProperties['storeFile'] ? file(secretProperties['storeFile']) : null
|
||||
storePassword = secretProperties['storePassword']
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
// TODO: Add your own signing config for the release build.
|
||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||
signingConfig signingConfigs.debug
|
||||
signingConfig = signingConfigs.release
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 544 B After Width: | Height: | Size: 3.6 KiB |
Before Width: | Height: | Size: 442 B After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 721 B After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 9.4 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 13 KiB |
2
frontend/android/fastlane/Appfile
Normal file
@@ -0,0 +1,2 @@
|
||||
json_key_file("google-key.json") # Path to the json secret file - Follow https://docs.fastlane.tools/actions/supply/#setup to get one
|
||||
package_name("com.anydev.anyway") # e.g. com.krausefx.app
|
53
frontend/android/fastlane/Fastfile
Normal file
@@ -0,0 +1,53 @@
|
||||
# This file contains the fastlane.tools configuration
|
||||
# You can find the documentation at https://docs.fastlane.tools
|
||||
#
|
||||
# For a list of all available actions, check out
|
||||
#
|
||||
# https://docs.fastlane.tools/actions
|
||||
#
|
||||
# For a list of all available plugins, check out
|
||||
#
|
||||
# https://docs.fastlane.tools/plugins/available-plugins
|
||||
#
|
||||
|
||||
# Uncomment the line if you want fastlane to automatically update itself
|
||||
# update_fastlane
|
||||
|
||||
default_platform(:android)
|
||||
|
||||
platform :android do
|
||||
desc "Runs all the tests"
|
||||
lane :test do
|
||||
gradle(task: "test")
|
||||
end
|
||||
|
||||
desc "Submit a new build to the closed testing lane"
|
||||
lane :closed_testing do
|
||||
gradle(
|
||||
task: "bundle",
|
||||
# flavor: "staging",
|
||||
)
|
||||
|
||||
upload_to_play_store(
|
||||
track: 'alpha',
|
||||
skip_upload_apk: true,
|
||||
skip_upload_changelogs: true,
|
||||
)
|
||||
end
|
||||
|
||||
desc "Deploy a new release to the Google Play"
|
||||
lane :deploy do
|
||||
gradle(
|
||||
task: "clean assembleRelease",
|
||||
properties: {
|
||||
# loaded from environment
|
||||
android.injected.version.name: ENV["VERSION_NAME"],
|
||||
}
|
||||
)
|
||||
upload_to_play_store(
|
||||
track: "production",
|
||||
skip_upload_apk: true,
|
||||
skip_upload_changelogs: true,
|
||||
)
|
||||
end
|
||||
end
|
48
frontend/android/fastlane/README.md
Normal file
@@ -0,0 +1,48 @@
|
||||
fastlane documentation
|
||||
----
|
||||
|
||||
# Installation
|
||||
|
||||
Make sure you have the latest version of the Xcode command line tools installed:
|
||||
|
||||
```sh
|
||||
xcode-select --install
|
||||
```
|
||||
|
||||
For _fastlane_ installation instructions, see [Installing _fastlane_](https://docs.fastlane.tools/#installing-fastlane)
|
||||
|
||||
# Available Actions
|
||||
|
||||
## Android
|
||||
|
||||
### android test
|
||||
|
||||
```sh
|
||||
[bundle exec] fastlane android test
|
||||
```
|
||||
|
||||
Runs all the tests
|
||||
|
||||
### android closed_testing
|
||||
|
||||
```sh
|
||||
[bundle exec] fastlane android closed_testing
|
||||
```
|
||||
|
||||
Submit a new build to the closed testing lane
|
||||
|
||||
### android deploy
|
||||
|
||||
```sh
|
||||
[bundle exec] fastlane android deploy
|
||||
```
|
||||
|
||||
Deploy a new version to the Google Play
|
||||
|
||||
----
|
||||
|
||||
This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run.
|
||||
|
||||
More information about _fastlane_ can be found on [fastlane.tools](https://fastlane.tools).
|
||||
|
||||
The documentation of _fastlane_ can be found on [docs.fastlane.tools](https://docs.fastlane.tools).
|
@@ -0,0 +1,7 @@
|
||||
AnyWay - plan city trips your way
|
||||
|
||||
AnyWay is a mobile application that helps users plan city trips. The app allows users to specify their preferences and constraints, and then generates a personalized itinerary for them. The planning follows some guiding principles:
|
||||
- **Personalization**:The user's preferences should be reflected in the choice of destinations.
|
||||
- **Efficiency**:The itinerary should be optimized for the user's constraints.
|
||||
- **Flexibility**: We aknowledge that tourism is a dynamic activity, and that users may want to change their plans on the go.
|
||||
- **Discoverability**: Tourism is an inherently exploratory activity. Once a rough itinerary is generated, detours and spontaneous decisions should be encouraged.
|
After Width: | Height: | Size: 638 KiB |
After Width: | Height: | Size: 893 KiB |
After Width: | Height: | Size: 876 KiB |
After Width: | Height: | Size: 123 KiB |
After Width: | Height: | Size: 96 KiB |
After Width: | Height: | Size: 209 KiB |
After Width: | Height: | Size: 638 KiB |
After Width: | Height: | Size: 893 KiB |
After Width: | Height: | Size: 876 KiB |
After Width: | Height: | Size: 123 KiB |
After Width: | Height: | Size: 96 KiB |
After Width: | Height: | Size: 209 KiB |
After Width: | Height: | Size: 638 KiB |
After Width: | Height: | Size: 893 KiB |
After Width: | Height: | Size: 876 KiB |
After Width: | Height: | Size: 123 KiB |
After Width: | Height: | Size: 96 KiB |
After Width: | Height: | Size: 209 KiB |
@@ -0,0 +1 @@
|
||||
AnyWay - plan city trips your way!
|
@@ -0,0 +1 @@
|
||||
AnyWay
|
23
frontend/android/fastlane/report.xml
Normal file
@@ -0,0 +1,23 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<testsuites>
|
||||
<testsuite name="fastlane.lanes">
|
||||
|
||||
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000594355">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="1: bundle" time="11.355126485">
|
||||
|
||||
</testcase>
|
||||
|
||||
|
||||
<testcase classname="fastlane.lanes" name="2: upload_to_play_store" time="63.414149183">
|
||||
|
||||
</testcase>
|
||||
|
||||
</testsuite>
|
||||
</testsuites>
|
BIN
frontend/assets/launcher/icon.png
Normal file
After Width: | Height: | Size: 24 KiB |
17
frontend/flutter_launcher_icons.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
flutter_launcher_icons:
|
||||
image_path: "assets/launcher/icon.png"
|
||||
|
||||
# Android section
|
||||
android: true
|
||||
min_sdk_android: 21 # android min sdk min:16, default 21
|
||||
|
||||
# iOS section
|
||||
ios: true
|
||||
remove_alpha_ios: true # app store rejecs icons with alpha
|
||||
|
||||
# Web section
|
||||
web:
|
||||
generate: true
|
||||
image_path: "assets/launcher/icon.png"
|
||||
# background_color: "#hexcode"
|
||||
# theme_color: "#hexcode"
|
@@ -427,7 +427,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
@@ -484,7 +484,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 97 KiB |
Before Width: | Height: | Size: 295 B After Width: | Height: | Size: 738 B |
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 450 B After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 282 B After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 462 B After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 704 B After Width: | Height: | Size: 3.8 KiB |
Before Width: | Height: | Size: 406 B After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 586 B After Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 5.8 KiB |
After Width: | Height: | Size: 1.9 KiB |
After Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 2.5 KiB |
After Width: | Height: | Size: 5.6 KiB |
Before Width: | Height: | Size: 862 B After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 10 KiB |
After Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 8.1 KiB |
Before Width: | Height: | Size: 762 B After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 8.9 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 7.4 KiB |
@@ -1,5 +1,6 @@
|
||||
const String APP_NAME = 'AnyWay';
|
||||
|
||||
String API_URL_BASE = 'https://anyway.kluster.moll.re';
|
||||
String API_URL_BASE = 'https://anyway.anydev.info';
|
||||
String PRIVACY_URL = 'https://anydev.info/privacy';
|
||||
|
||||
const String MAP_ID = '41c21ac9b81dbfd8';
|
||||
|
@@ -1,6 +1,3 @@
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:anyway/structs/landmark.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:anyway/constants.dart';
|
||||
@@ -53,7 +50,21 @@ class _BasePageState extends State<BasePage> {
|
||||
if (availableTrips.isNotEmpty) {
|
||||
return TripPage(trip: availableTrips[0]);
|
||||
} else {
|
||||
return Text("Wow, so empty!");
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Text("Wow, so empty!"),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton.extended(
|
||||
onPressed: () {
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const NewTripPage()
|
||||
)
|
||||
);
|
||||
},
|
||||
label: Text("Plan a trip now"),
|
||||
),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
return const Text("loading...");
|
||||
|
@@ -13,6 +13,40 @@ class ProfilePage extends StatefulWidget {
|
||||
class _ProfilePageState extends State<ProfilePage> {
|
||||
Future<UserPreferences> _prefs = loadUserPreferences();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListView(
|
||||
children: [
|
||||
// First a round, centered image
|
||||
Center(
|
||||
child: CircleAvatar(
|
||||
radius: 100,
|
||||
child: Icon(Icons.person, size: 100),
|
||||
)
|
||||
),
|
||||
Center(
|
||||
child: Text('Curious traveler', style: TextStyle(fontSize: 24))
|
||||
),
|
||||
|
||||
Divider(indent: 25, endIndent: 25, height: 50),
|
||||
|
||||
Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: 10, right: 10, top: 0, bottom: 10),
|
||||
child: Text('For a tailored experience, please rate your discovery preferences.', style: TextStyle(fontSize: 18))
|
||||
),
|
||||
),
|
||||
|
||||
FutureBuilder(future: _prefs, builder: futureSliders),
|
||||
|
||||
Divider(indent: 25, endIndent: 25, height: 50),
|
||||
|
||||
privacyInfo(),
|
||||
|
||||
debugButton(),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
Widget debugButton() {
|
||||
return Padding(
|
||||
@@ -60,37 +94,6 @@ class _ProfilePageState extends State<ProfilePage> {
|
||||
}
|
||||
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListView(
|
||||
children: [
|
||||
// First a round, centered image
|
||||
Center(
|
||||
child: CircleAvatar(
|
||||
radius: 100,
|
||||
child: Icon(Icons.person, size: 100),
|
||||
)
|
||||
),
|
||||
Center(
|
||||
child: Text('Curious traveler', style: TextStyle(fontSize: 24))
|
||||
),
|
||||
|
||||
Divider(indent: 25, endIndent: 25, height: 50),
|
||||
|
||||
Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: 10, right: 10, top: 0, bottom: 10),
|
||||
child: Text('For a tailored experience, please rate your discovery preferences.', style: TextStyle(fontSize: 18))
|
||||
),
|
||||
),
|
||||
|
||||
FutureBuilder(future: _prefs, builder: futureSliders),
|
||||
debugButton()
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
Widget futureSliders(BuildContext context, AsyncSnapshot<UserPreferences> snapshot) {
|
||||
if (snapshot.connectionState == ConnectionState.done) {
|
||||
UserPreferences prefs = snapshot.data!;
|
||||
@@ -106,6 +109,23 @@ class _ProfilePageState extends State<ProfilePage> {
|
||||
return CircularProgressIndicator();
|
||||
}
|
||||
}
|
||||
|
||||
Widget privacyInfo() {
|
||||
return Padding(
|
||||
padding: EdgeInsets.only(top: 20),
|
||||
child: Row(
|
||||
children: [
|
||||
Text('Privacy policy is available at '),
|
||||
TextButton.icon(
|
||||
icon: Icon(Icons.info),
|
||||
label: Text(PRIVACY_URL),
|
||||
onPressed: () {
|
||||
}
|
||||
)
|
||||
],
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,6 +1,14 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: archive
|
||||
sha256: cb6a278ef2dbb298455e1a713bda08524a175630ec643a242c399c932a0a1f7d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.6.1"
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -65,6 +73,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.3.0"
|
||||
checked_yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: checked_yaml
|
||||
sha256: feb6bed21949061731a7a75fc5d2aa727cf160b91af9a3e464c5e3a32e28b5ff
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.3"
|
||||
cli_util:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cli_util
|
||||
sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.4.1"
|
||||
clock:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -166,6 +190,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.4.0"
|
||||
flutter_launcher_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_launcher_icons
|
||||
sha256: "526faf84284b86a4cb36d20a5e45147747b7563d921373d4ee0559c54fcdbcea"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.13.1"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
@@ -304,6 +336,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.2"
|
||||
image:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: image
|
||||
sha256: "2237616a36c0d69aef7549ab439b833fb7f9fb9fc861af2cc9ac3eedddd69ca8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.2.0"
|
||||
json_annotation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: json_annotation
|
||||
sha256: "1ce844379ca14835a50d2f019a3099f419082cfdd231cd86a142af94dd5c6bb1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.9.0"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -805,6 +853,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.5.0"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: yaml
|
||||
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
sdks:
|
||||
dart: ">=3.5.0 <4.0.0"
|
||||
flutter: ">=3.24.0"
|
||||
|
@@ -48,6 +48,7 @@ dependencies:
|
||||
map_launcher: ^3.3.1
|
||||
flutter_svg: ^2.0.10+1
|
||||
url_launcher: ^6.3.0
|
||||
flutter_launcher_icons: ^0.13.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
Before Width: | Height: | Size: 917 B After Width: | Height: | Size: 633 B |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 45 KiB |
@@ -32,4 +32,4 @@
|
||||
"purpose": "maskable"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|