|
1 | | -# on_time_front |
| 1 | +# OnTime Front |
2 | 2 |
|
3 | | -# widgetbook |
| 3 | +OnTime is a Flutter app for schedule preparation, alarms, and arrival-time planning. The app is organized with clean architecture: presentation widgets and BLoCs depend on domain use cases, while data sources, Drift DAOs, and repository implementations live behind domain contracts. |
| 4 | + |
| 5 | +Primary supported targets are web, Android, and iOS. Desktop platform folders are present in the Flutter project, but Firebase options are currently configured only for web, Android, and iOS. |
| 6 | + |
| 7 | +## Contents |
| 8 | + |
| 9 | +- [Requirements](#requirements) |
| 10 | +- [Project Structure](#project-structure) |
| 11 | +- [First-Time Setup](#first-time-setup) |
| 12 | +- [Runtime Configuration](#runtime-configuration) |
| 13 | +- [Firebase Configuration](#firebase-configuration) |
| 14 | +- [Development Commands](#development-commands) |
| 15 | +- [Build and Release](#build-and-release) |
| 16 | +- [Widgetbook](#widgetbook) |
| 17 | +- [Troubleshooting](#troubleshooting) |
| 18 | +- [Further Reading](#further-reading) |
| 19 | + |
| 20 | +## Requirements |
| 21 | + |
| 22 | +- Flutter stable. CI uses Flutter `3.32.6`; use that version for release parity when possible. |
| 23 | +- Dart SDK compatible with `pubspec.yaml` (`^3.5.4`). |
| 24 | +- Java and Android SDK for Android builds. |
| 25 | +- Xcode and CocoaPods for iOS builds. |
| 26 | +- Firebase CLI and FlutterFire CLI when regenerating Firebase config. |
| 27 | +- Access to the project secrets/configuration values listed below. |
| 28 | + |
| 29 | +Check your local toolchain with: |
| 30 | + |
| 31 | +```sh |
| 32 | +flutter doctor |
| 33 | +flutter --version |
| 34 | +dart --version |
| 35 | +``` |
| 36 | + |
| 37 | +## Project Structure |
| 38 | + |
| 39 | +```text |
| 40 | +lib/ |
| 41 | + core/ platform services, database, dependency injection, Dio, utilities |
| 42 | + data/ data sources, DAOs, models, tables, repository implementations |
| 43 | + domain/ entities, repository contracts, use cases |
| 44 | + l10n/ localization files |
| 45 | + presentation/ screens, blocs, cubits, shared widgets, routing, theme |
| 46 | +test/ tests mirroring app paths |
| 47 | +docs/ architecture and feature documentation |
| 48 | +assets/ shared assets and fonts |
| 49 | +widgetbook/ component catalog app |
| 50 | +``` |
| 51 | + |
| 52 | +Generated Dart files such as `*.g.dart`, `*.freezed.dart`, `*.config.dart`, and `*.mocks.dart` are not committed. Regenerate them locally after dependency changes or code-generator changes. |
| 53 | + |
| 54 | +## First-Time Setup |
| 55 | + |
| 56 | +1. Install dependencies: |
| 57 | + |
| 58 | + ```sh |
| 59 | + flutter pub get |
| 60 | + ``` |
| 61 | + |
| 62 | +2. Generate code: |
| 63 | + |
| 64 | + ```sh |
| 65 | + dart run build_runner build --delete-conflicting-outputs |
| 66 | + ``` |
| 67 | + |
| 68 | +3. Provide environment values and platform config. At minimum, local app runs need `REST_API_URL`; some flows may also require Firebase and native sign-in config. See [Runtime Configuration](#runtime-configuration) and [Firebase Configuration](#firebase-configuration). |
| 69 | + |
| 70 | +4. Run the app: |
| 71 | + |
| 72 | + ```sh |
| 73 | + flutter run -d chrome --dart-define=REST_API_URL=<api-base-url> |
| 74 | + ``` |
| 75 | + |
| 76 | +For Android or iOS, replace `chrome` with the device id from `flutter devices`. |
| 77 | + |
| 78 | +## Runtime Configuration |
| 79 | + |
| 80 | +The app reads compile-time values from Dart defines in `lib/core/constants/environment_variable.dart`. |
| 81 | + |
| 82 | +| Define | Required | Used for | |
| 83 | +| --- | --- | --- | |
| 84 | +| `REST_API_URL` | Yes | Base URL for Dio API calls. | |
| 85 | +| `REST_AUTH_TOKEN` | Optional | Static auth token override for development/test scenarios. | |
| 86 | +| `GOOGLE_RESERVED_CLIENT_ID_IOS` | iOS release/archive only | Reversed iOS Google client ID used as the iOS URL scheme for Google Sign-In. | |
| 87 | + |
| 88 | +Pass defines directly on Flutter commands: |
| 89 | + |
| 90 | +```sh |
| 91 | +flutter run -d chrome \ |
| 92 | + --dart-define=REST_API_URL=<api-base-url> |
| 93 | + |
| 94 | +flutter build web --release \ |
| 95 | + --dart-define=REST_API_URL=<api-base-url> |
| 96 | +``` |
| 97 | + |
| 98 | +For iOS release and archive builds, include the Google URL scheme define: |
| 99 | + |
| 100 | +```sh |
| 101 | +flutter build ios --release \ |
| 102 | + --dart-define=REST_API_URL=<api-base-url> \ |
| 103 | + --dart-define=GOOGLE_RESERVED_CLIENT_ID_IOS=<reversed-ios-client-id> |
| 104 | +``` |
| 105 | + |
| 106 | +The iOS Xcode scheme decodes `DART_DEFINES` into `ios/Flutter/Dart-Defines.xcconfig`. Release builds fail if `GOOGLE_RESERVED_CLIENT_ID_IOS` is missing or if the built `Info.plist` does not contain the Google Sign-In URL scheme. |
| 107 | + |
| 108 | +## Firebase Configuration |
| 109 | + |
| 110 | +`lib/firebase_options.dart` is generated by FlutterFire and currently supports web, Android, and iOS. macOS, Windows, and Linux throw `UnsupportedError` unless Firebase is reconfigured for those targets. |
| 111 | + |
| 112 | +Tracked Firebase-related files: |
| 113 | + |
| 114 | +- `lib/firebase_options.dart` |
| 115 | +- `firebase.json` |
| 116 | +- `web/firebase-messaging-sw.js` |
| 117 | + |
| 118 | +Native Firebase files are intentionally not committed and must come from project secret/config access: |
| 119 | + |
| 120 | +- Android: `android/app/google-services.json`, or a variant-specific file under `android/app/src/debug/` or `android/app/src/release/`. |
| 121 | +- iOS: `ios/Runner/GoogleService-Info.plist`. |
| 122 | + |
| 123 | +Android local builds skip the Google Services Gradle plugin when no `google-services.json` file is present, which is useful for non-Firebase development. Firebase-dependent features and production builds should use the correct native config files. |
| 124 | + |
| 125 | +To regenerate Firebase configuration, use the FlutterFire CLI with the `ontime-c63f1` Firebase project and keep the outputs aligned with `firebase.json`. |
| 126 | + |
| 127 | +## Development Commands |
| 128 | + |
| 129 | +Install dependencies: |
| 130 | + |
| 131 | +```sh |
| 132 | +flutter pub get |
| 133 | +``` |
| 134 | + |
| 135 | +Regenerate Drift, JSON, Injectable, Freezed, Mockito, and Widgetbook code: |
| 136 | + |
| 137 | +```sh |
| 138 | +dart run build_runner build --delete-conflicting-outputs |
| 139 | +``` |
| 140 | + |
| 141 | +Format Dart code: |
| 142 | + |
| 143 | +```sh |
| 144 | +dart format lib test |
| 145 | +``` |
| 146 | + |
| 147 | +Run analyzer: |
| 148 | + |
| 149 | +```sh |
| 150 | +flutter analyze |
| 151 | +``` |
| 152 | + |
| 153 | +Run tests: |
| 154 | + |
| 155 | +```sh |
| 156 | +flutter test |
| 157 | +``` |
| 158 | + |
| 159 | +Run tests with coverage: |
| 160 | + |
| 161 | +```sh |
| 162 | +flutter test --coverage |
| 163 | +``` |
| 164 | + |
| 165 | +Run the web app locally: |
| 166 | + |
| 167 | +```sh |
| 168 | +flutter run -d chrome --dart-define=REST_API_URL=<api-base-url> |
| 169 | +``` |
| 170 | + |
| 171 | +Do not use `npm test`; the root `package.json` script is a placeholder that intentionally fails. |
| 172 | + |
| 173 | +## Build and Release |
| 174 | + |
| 175 | +### Web |
| 176 | + |
| 177 | +Preview and production web deployments are handled by GitHub Actions and Firebase Hosting. CI uses the `REST_API_URL` GitHub environment variable and builds with: |
| 178 | + |
| 179 | +```sh |
| 180 | +flutter build web --release --dart-define=REST_API_URL=<api-base-url> |
| 181 | +``` |
| 182 | + |
| 183 | +Firebase Hosting deploys `build/web` to project `ontime-c63f1`. |
| 184 | + |
| 185 | +### Android |
| 186 | + |
| 187 | +Build a release APK: |
| 188 | + |
| 189 | +```sh |
| 190 | +flutter build apk --release \ |
| 191 | + --dart-define=REST_API_URL=<api-base-url> |
| 192 | +``` |
| 193 | + |
| 194 | +Build an app bundle for Play Console upload: |
| 195 | + |
| 196 | +```sh |
| 197 | +flutter build appbundle --release \ |
| 198 | + --dart-define=REST_API_URL=<api-base-url> |
| 199 | +``` |
| 200 | + |
| 201 | +Before production upload, confirm the release `google-services.json`, signing configuration, version name, and version code. The current Gradle release block uses the debug signing config as a local-build fallback, so production signing must be configured before store release. |
| 202 | + |
| 203 | +### iOS |
| 204 | + |
| 205 | +Build locally: |
| 206 | + |
| 207 | +```sh |
| 208 | +flutter build ios --release \ |
| 209 | + --dart-define=REST_API_URL=<api-base-url> \ |
| 210 | + --dart-define=GOOGLE_RESERVED_CLIENT_ID_IOS=<reversed-ios-client-id> |
| 211 | +``` |
| 212 | + |
| 213 | +Create an App Store archive from Xcode or CI with the same Dart defines. See [docs/iOS-Release-Configuration.md](docs/iOS-Release-Configuration.md) for the release-only validation flow. |
| 214 | + |
| 215 | +Before production upload, confirm `ios/Runner/GoogleService-Info.plist`, Apple signing, bundle id, app capabilities, push notification entitlement, build number, and App Store Connect metadata. |
| 216 | + |
| 217 | +## Widgetbook |
| 218 | + |
| 219 | +Widgetbook is a separate Flutter project under `widgetbook/`. |
| 220 | + |
| 221 | +Run locally: |
| 222 | + |
| 223 | +```sh |
| 224 | +cd widgetbook |
| 225 | +flutter pub get |
| 226 | +dart run build_runner build --delete-conflicting-outputs |
| 227 | +flutter run -d chrome |
| 228 | +``` |
| 229 | + |
| 230 | +Build for Firebase Hosting: |
| 231 | + |
| 232 | +```sh |
| 233 | +cd widgetbook |
| 234 | +flutter build web --release |
| 235 | +``` |
| 236 | + |
| 237 | +Published Widgetbook: |
4 | 238 |
|
5 | 239 | https://on-time-front-widgetbook.web.app/ |
| 240 | + |
| 241 | +## Troubleshooting |
| 242 | + |
| 243 | +### Generated files are missing or stale |
| 244 | + |
| 245 | +Run: |
| 246 | + |
| 247 | +```sh |
| 248 | +dart run build_runner build --delete-conflicting-outputs |
| 249 | +``` |
| 250 | + |
| 251 | +If generation still fails, clean generated state and fetch dependencies again: |
| 252 | + |
| 253 | +```sh |
| 254 | +flutter clean |
| 255 | +flutter pub get |
| 256 | +dart run build_runner build --delete-conflicting-outputs |
| 257 | +``` |
| 258 | + |
| 259 | +### API calls fail immediately |
| 260 | + |
| 261 | +Confirm `REST_API_URL` was passed to the `flutter run` or `flutter build` command. `String.fromEnvironment` values are compile-time constants, so changing a shell variable after launch does not update the app. |
| 262 | + |
| 263 | +### Firebase initialization fails on desktop |
| 264 | + |
| 265 | +Firebase options are not configured for macOS, Windows, or Linux. Use web, Android, or iOS, or regenerate Firebase options for desktop platforms before enabling those targets. |
| 266 | + |
| 267 | +### Android Firebase features do not work locally |
| 268 | + |
| 269 | +Add the appropriate `google-services.json` file under `android/app/` or a variant directory. Without that file, the Gradle build intentionally skips the Google Services plugin. |
| 270 | + |
| 271 | +### iOS release fails with `GOOGLE_RESERVED_CLIENT_ID_IOS` |
| 272 | + |
| 273 | +Pass the reversed iOS Google client ID with `--dart-define=GOOGLE_RESERVED_CLIENT_ID_IOS=<value>`. The release build validates both the Dart define extraction and the final `Info.plist` URL scheme. |
| 274 | + |
| 275 | +### Web push notifications do not arrive |
| 276 | + |
| 277 | +Confirm the browser has notification permission, the Firebase web config in `web/firebase-messaging-sw.js` matches the active Firebase project, and the app is served over HTTPS or localhost. |
| 278 | + |
| 279 | +### SQLite or Drift tests fail in CI-like environments |
| 280 | + |
| 281 | +Install SQLite system libraries before running tests. The GitHub Actions workflow installs `sqlite3` and `libsqlite3-dev` before `flutter test`. |
| 282 | + |
| 283 | +## Further Reading |
| 284 | + |
| 285 | +- [Architecture](docs/Architecture.md) |
| 286 | +- [Error handling and Result system](docs/Error-Handling-Result-System.md) |
| 287 | +- [Logging policy](docs/Logging-Policy.md) |
| 288 | +- [iOS release configuration](docs/iOS-Release-Configuration.md) |
| 289 | +- [Schedule timer system](docs/Schedule-Timer-System.md) |
| 290 | +- [Git workflow](docs/Git.md) |
0 commit comments