Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,32 @@
# MaizeBus
<img width="2000" height="546" alt="github_header" src="https://github.com/user-attachments/assets/e13b6768-53cf-4f8b-ab09-de9aa86805fe" />

# Quickstart (Recommended)
## Create an API key for Google Maps
**Keep your API key secret!** Your Google Maps API key is just for your local build of Maizebus (we'll use a different one when publishing to the app store). Our GitHub repository is configured to ignore `android/local.properties` and `ios/Flutter/gmap.xcconfig` so you're safe to commit as usual.

You have two options for getting your API key: either use a Maps Demo Key or get an API key through Google Cloud. The Maps Demo key doesn't require a credit card but is newer and might have stricter usage limits. Google Cloud requires you to have a credit card on file, but our usage stays in the free tier (we're using the "Maps SDK", which has [unlimited free usage](https://developers.google.com/maps/billing-and-pricing/pricing#map-loads-pricing)). I would recommend getting your API key from Google Cloud since it's more stable.

1. Option A: Use a Maps Demo Key (no credit card required)
1. Visit the [Maps Demo Key page](https://mapsplatform.google.com/maps-demo-key/?utm_experiment=13103221)
2. Click "Try for free" and sign in with your Google Account
3. Agree to the terms, and you should see your Maps Demo Key!
2. Option B: Create an API key through Google Cloud
1. Open the [Google Cloud Console](https://console.cloud.google.com/google/maps-apis/overview). Create an account if you don't already have one
2. In the toolbar you should see the Project Picker (right next to "Google Cloud"). Click it and create a new project. Call it whatever you like (such as "Local-Maizebus-Testing")
3. In the sidebar, click "APIs & Services" and enable "Maps SDK for Android" and "Maps SDK for iOS"
4. Now click on "Keys & Credentials" in the sidebar
5. Click on the "Maps Platform API Key" under "API Keys", then click "Show key"

## Run automatic setup
1. Make sure Flutter is installed on your computer (see [this guide](https://docs.flutter.dev/install) for how to do this)
2. Open a terminal (Mac) or WSL terminal (Windows) in the project folder. Run `./setup.sh` to start the setup process
3. Paste your Google Maps API key into the setup script when prompted. The setup script will add your API key to the project
4. Launch an emulator and click the green Run button in VSCode to build and run the project! Alternatively you can run `flutter run` in your terminal

**Note:** `setup.sh` disables Firebase by default and creates dummy configuration files. Most frontend developers probably won't work on the notification system, so we're saving you all the pain of having to get a Firebase API key and configure flutterfire. If you'd like to configure Firebase properly, see the section below.


# Manual Setup

## Google Maps Setup (iOS)

Expand Down
13 changes: 9 additions & 4 deletions lib/services/notification_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';

const useFirebase = bool.fromEnvironment('USE_FIREBASE', defaultValue: kReleaseMode);
class NotificationService {
static final _localNotificationsPlugin = FlutterLocalNotificationsPlugin();
static bool _listeningForFcmUpdates = false;
Expand All @@ -22,10 +23,12 @@ class NotificationService {
/// e.g. call it asap if notifications were previously used, otherwise wait for
/// the user to trigger a feature that requires notifications
static Future<void> initPlugin() async {
await Firebase.initializeApp(
name: "[DEFAULT]",
options: DefaultFirebaseOptions.currentPlatform,
);
if (useFirebase) {
await Firebase.initializeApp(
name: "[DEFAULT]",
options: DefaultFirebaseOptions.currentPlatform,
);
}

// prepare local notifications
const AndroidInitializationSettings androidSettings =
Expand Down Expand Up @@ -69,6 +72,8 @@ class NotificationService {
// Currently this function must be called even if permission is already granted,
// as it sets up some important listeners
static Future<void> requestPermission() async {
if (!useFirebase) return; // If Firebase is disabled for development skip all this

// todo: add back in if needed
final notificationSettings = await FirebaseMessaging.instance
.requestPermission();
Expand Down
118 changes: 118 additions & 0 deletions setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
#!/bin/bash
set -Eeuo pipefail

BLACK="\e[30m";
RED="\033[31m";
GREEN="\033[32m";
YELLOW="\033[33m";
BLUE="\033[34m";
MAGENTA="\033[35m";
CYAN="\033[36m";
WHITE="\033[37m";
RESET="\033[0m";

if flutter --version; then
echo "Found Flutter installation!"
else
echo "Error: Could not find Flutter"
exit 1
fi

flutter doctor

echo "Please paste in your Google Maps API key: "

read gmaps_apikey

touch ios/Flutter/gmap.xcconfig
sed -E 's/^GMapApiKey=([A-Za-z0-9]+)//' ios/Flutter/gmap.xcconfig # Remove all old API keys from gmap.xcconfig
echo "GMapApiKey=$gmaps_apikey" > ios/Flutter/gmap.xcconfig # Add API key to gmap.xcconfig
touch android/local.properties
grep -v '^GOOGLE_MAPS_API_KEY=' android/local.properties > android/local.properties.tmp || true # Remove all old API keys from local.properties
mv android/local.properties.tmp android/local.properties
printf "\nGOOGLE_MAPS_API_KEY=$gmaps_apikey" >> android/local.properties # Add API key to local.properties

flutter pub get

if [ ! -f lib/firebase_options.dart ]; then
touch lib/firebase_options.dart
> lib/firebase_options.dart # Clear the file
cat > lib/firebase_options.dart << 'EOF'
// Dummy Firebase config file. WILL NOT CONNECT TO FIREBASE OR RECEIVE NOTIFICATIONS
// To set the app up to use Firebase notifications, follow this tutorial: https://firebase.google.com/docs/flutter/setup
// ignore_for_file: type=lint
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart'
show defaultTargetPlatform, kIsWeb, TargetPlatform;

// If you're seeing a compile error here, you're making a release build with the
// dummy Firebase config. Set up the real one: https://firebase.google.com/docs/flutter/setup
// ignore: unused_element
const _noReleaseWithDummyFirebase = 1 ~/ (bool.fromEnvironment('dart.vm.product') ? 0 : 1);


/// Default [FirebaseOptions] for use with your Firebase apps.
///
/// Example:
/// ```dart
/// import 'firebase_options.dart';
/// // ...
/// await Firebase.initializeApp(
/// options: DefaultFirebaseOptions.currentPlatform,
/// );
/// ```
class DefaultFirebaseOptions {
static FirebaseOptions get currentPlatform {
throw UnsupportedError("Firebase hasn't been configured for this project! Please delete firebase_options.dart and follow the tutorial at https://firebase.google.com/docs/flutter/setup");
}

static const FirebaseOptions android = FirebaseOptions(
apiKey: 'dummy-api-key',
appId: 'dummy-app-id',
messagingSenderId: 'dummy-sender-id',
projectId: 'dummy-project-id',
storageBucket: 'dummy-project-id.appspot.com',
);
}
EOF
else
printf "${YELLOW}Note: lib/firebase_options.dart already exists and was not overwritten $RESET\n"
printf " If you'd like to replace firebase_options.dart with the dummy version,\n"
printf " remove it and run this script again\n"
fi

if [ ! -f android/app/google-services.json ]; then
cat > android/app/google-services.json << 'EOF'
{
"project_info": {
"project_number": "000000000000",
"project_id": "dummy-project-id",
"storage_bucket": "dummy-project-id.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:000000000000:android:0000000000000000000000",
"android_client_info": {
"package_name": "com.ishankumar.maizebus"
}
},
"oauth_client": [],
"api_key": [{ "current_key": "dummy-api-key" }],
"services": { "appinvite_service": { "other_platform_oauth_client": [] } }
}
],
"configuration_version": "1"
}
EOF
else
printf "${YELLOW}Note: android/app/google-services.json already exists and was not overwritten$RESET\n"
printf " If you'd like to replace google-services.json with the dummy version,\n"
printf " remove it and run this script again\n"
fi

# npm i -g firebase-tools # Install Firebase tools


# dart pub global activate flutterfire_cli

Loading