diff --git a/.env/flutter_defines.example.json b/.env/flutter_defines.example.json new file mode 100644 index 0000000..4250c9f --- /dev/null +++ b/.env/flutter_defines.example.json @@ -0,0 +1,5 @@ +{ + "SUPABASE_URL": "https://your-project.supabase.co", + "SUPABASE_ANON_KEY": "your_anon_key", + "SUPABASE_USE_PKCE": "true" +} diff --git a/.gitignore b/.gitignore index d39914f..1779abf 100644 --- a/.gitignore +++ b/.gitignore @@ -44,5 +44,16 @@ app.*.map.json /android/app/profile /android/app/release -TPB.md -supabase_migration.sql +/TPB.md +/supabase_migration.sql +/TPB_APP_CHECKLIST.md + +# Local run configuration with secrets +/.vscode/launch.json +/.env/flutter_defines.json + +# Local testing artifacts +/flutter_*.png +/devtools_options.yaml + +FINDINGS.md \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..11930d0 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,44 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Flutter Build APK (Release)", + "type": "shell", + "command": "flutter", + "args": [ + "build", + "apk", + "--release", + "--dart-define-from-file=.env/flutter_defines.json" + ], + "group": "build", + "problemMatcher": [] + }, + { + "label": "Flutter Build App Bundle (Release)", + "type": "shell", + "command": "flutter", + "args": [ + "build", + "appbundle", + "--release", + "--dart-define-from-file=.env/flutter_defines.json" + ], + "group": "build", + "problemMatcher": [] + }, + { + "label": "Flutter Build iOS IPA (Release)", + "type": "shell", + "command": "flutter", + "args": [ + "build", + "ipa", + "--release", + "--dart-define-from-file=.env/flutter_defines.json" + ], + "group": "build", + "problemMatcher": [] + } + ] +} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..0ab4c4e --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,74 @@ +# Contributing Guide + +Thanks for contributing to car64. + +## Workflow + +- Create a branch from `main`: + - `feature/` for features + - `fix/` for bug fixes + - `docs/` for documentation updates +- Keep pull requests focused and small when possible. +- Write clear commit messages (Conventional Commit style is preferred). + +## Development Setup + +1. Install Flutter stable and run `flutter doctor`. +2. Copy `.env/flutter_defines.example.json` to `.env/flutter_defines.json`. +3. Fill in your own Supabase config values. +4. Run: + +```bash +flutter pub get +flutter analyze +``` + +## Code Style + +- Follow existing project style and naming patterns. +- Prefer small, explicit methods over deeply nested logic. +- Preserve backend contract names (`hotwheels`, RPC names, etc.) unless migration is intentional. + +## Testing & Validation + +Before opening a PR: + +- Run `flutter analyze` +- Run available tests +- Manually test affected flows (scanner, collections, auth, storage upload) + +## Pull Request Checklist + +- [ ] Scope is clear and focused +- [ ] Analyzer passes +- [ ] User-facing strings are intentional and reviewed +- [ ] No secrets/config values were committed +- [ ] README/docs updated if behavior changed + +## Commit Message Examples + +Preferred format: + +```text +type(scope): short summary +``` + +Common types used in this repository: + +- `feat`: new feature +- `fix`: bug fix +- `perf`: performance improvement +- `docs`: documentation-only change +- `refactor`: code cleanup without behavior change +- `test`: tests added/updated +- `chore`: maintenance/tooling/config updates + +Examples: + +- `feat(scanner): add adaptive cooldown for repeated OCR misses` +- `fix(garage): prevent duplicate copy into target collection` +- `perf(collections): coalesce overlapping refresh requests` +- `docs(readme): add VS Code release build task usage` +- `refactor(auth): simplify session guard flow in AuthGate` +- `test(utils): cover scanner id extraction edge cases` +- `chore(vscode): add release build tasks for apk and appbundle` diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0c104d9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Lukas Müllner @derkauzigekoala + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index c024eb0..1db737a 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,198 @@ -# hwhub +

+ car64 logo +

-A new Flutter project. +

car64

+ +

+ A modern Flutter + Supabase app for tracking and managing die-cast car collections. +

+ +--- + +## Table of Contents + +- [Overview](#overview) +- [Features](#features) +- [Tech Stack](#tech-stack) +- [Prerequisites](#prerequisites) +- [Configuration](#configuration) +- [Getting Started](#getting-started) +- [VS Code Workflows](#vs-code-workflows) +- [Project Structure (high level)](#project-structure-high-level) +- [Troubleshooting](#troubleshooting) +- [Release Checklist](#release-checklist) +- [Roadmap](#roadmap) +- [Contributing](#contributing) +- [Security Notes](#security-notes) +- [License](#license) +- [Reference](#reference) + +## Overview + +car64 helps collectors scan model IDs, organize personal and shared collections, and keep a clean catalog with community validation/reporting flows. + +## Features + +- Fast scan workflow (camera OCR + manual entry fallback) +- Multi-collection support with member roles (owner/member/viewer) +- Private image storage with signed URL access +- Collection collaboration and member management +- Community validation and issue reporting for catalog entries +- Profile/settings flows including password updates and report tracking + +## Tech Stack + +- Flutter (Material 3) +- Supabase (Auth, PostgREST, Storage, RPC) +- Shared Preferences (local settings) +- Google ML Kit Text Recognition (scanner) + +## Prerequisites + +- Flutter SDK (stable) +- A Supabase project +- For iOS builds: macOS + Xcode + +## Configuration + +Supabase config is required at runtime/build time (no embedded fallback values). + +### Option A: local defines file (recommended) + +Use: + +- `.env/flutter_defines.json` (local, ignored by git) +- [.env/flutter_defines.example.json](.env/flutter_defines.example.json) (tracked template) + +Expected shape: + +```json +{ + "SUPABASE_URL": "https://your-project.supabase.co", + "SUPABASE_ANON_KEY": "your_anon_key", + "SUPABASE_USE_PKCE": "true" +} +``` + +### Option B: direct dart-define flags + +```bash +flutter run \ + --dart-define=SUPABASE_URL=https://your-project.supabase.co \ + --dart-define=SUPABASE_ANON_KEY=your_anon_key \ + --dart-define=SUPABASE_USE_PKCE=true +``` ## Getting Started -This project is a starting point for a Flutter application. +1. Install dependencies -A few resources to get you started if this is your first Flutter project: +```bash +flutter pub get +``` -- [Learn Flutter](https://docs.flutter.dev/get-started/learn-flutter) -- [Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) -- [Flutter learning resources](https://docs.flutter.dev/reference/learning-resources) +2. Run analyze + +```bash +flutter analyze +``` + +3. Launch app + +```bash +flutter run +``` + +## VS Code Workflows + +### Run / Debug (`launch.json`) + +Use **Run and Debug** with your local launch config. + +- `Flutter (Supabase Local - Debug)` +- `Flutter (Supabase Local - Profile)` +- `Flutter (Supabase Local - Release)` + +These configurations read: + +`--dart-define-from-file=.env/flutter_defines.json` + +### Build Tasks (`tasks.json`) + +Use **Terminal → Run Task**: + +- `Flutter Build APK (Release)` +- `Flutter Build App Bundle (Release)` +- `Flutter Build iOS IPA (Release)` + +Task definition file: [.vscode/tasks.json](.vscode/tasks.json) + +## Project Structure (high level) + +- `lib/screens/` UI screens and flows +- `lib/services/` Supabase integration/services +- `lib/widgets/` reusable UI components +- `lib/utils/` helpers and formatting utilities +- `lib/theme/` app theme and colors + +## Troubleshooting + +### App fails at startup with Supabase config error + +- Ensure `.env/flutter_defines.json` exists locally. +- Confirm all required keys are present: + - `SUPABASE_URL` + - `SUPABASE_ANON_KEY` + - `SUPABASE_USE_PKCE` + +### Build task works but app cannot connect to backend + +- Verify the Supabase URL/key pair belong to the same project. +- Check Supabase RLS policies and RPC permissions. + +### iOS IPA task fails on Windows + +- `flutter build ipa` requires macOS + Xcode. + +## Release Checklist + +- [ ] `flutter pub get` +- [ ] `flutter analyze` +- [ ] Manual smoke test on Android +- [ ] Manual smoke test on iOS +- [ ] Confirm `.env/flutter_defines.json` points to production Supabase +- [ ] Build Android `appbundle` +- [ ] Build iOS `ipa` +- [ ] Verify auth, scan flow, collections, and upload flows + +## Roadmap + +- [ ] Optional dark/light theme toggle in settings +- [ ] Extended scanner confidence hints and retry UX +- [ ] Bulk actions and better collection analytics +- [ ] Improved offline behavior for low-connectivity sessions + +## Contributing + +See [CONTRIBUTING.md](CONTRIBUTING.md) for branching strategy, commit message rules, and PR guidelines. + +## Security Notes + +- Supabase anon keys are intentionally client-side, but RLS and RPC permissions must be strict. +- Sensitive local config files are git-ignored. +- User-facing errors are sanitized and shown via global overlays. + +For reporting vulnerabilities, see [SECURITY.md](SECURITY.md). + +## License + +This project is licensed under the MIT License. +See [LICENSE](LICENSE) for details. + +## Reference + +- Contributor guidelines: [CONTRIBUTING.md](CONTRIBUTING.md) +- Security policy: [SECURITY.md](SECURITY.md) +- DB schema export query pack: [db/export_schema.sql](db/export_schema.sql) -For help getting started with Flutter development, view the -[online documentation](https://docs.flutter.dev/), which offers tutorials, -samples, guidance on mobile development, and a full API reference. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..983e897 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,31 @@ +# Security Policy + +## Supported Versions + +This project currently supports the latest active branch in this repository. + +## Reporting a Vulnerability + +If you discover a security issue, please do not open a public issue with exploit details. + +Preferred process: + +1. Share a private report with: + - A clear description of the issue + - Reproduction steps + - Impact assessment + - Suggested fix (if available) +2. Allow time for triage and remediation before public disclosure. + +## Scope Notes + +- Supabase anon keys are client-side by design and are not secret credentials. +- Real protection depends on strict RLS policies, RPC authorization, and server-side validation. +- Local config files with runtime values should stay out of version control. + +## Recommended Hardening + +- Keep Supabase keys in local/CI `dart-define` configuration only. +- Rotate keys when moving between environments or if misuse is suspected. +- Audit RLS policies after every schema/function change. +- Sanitize user-facing error messages (avoid leaking backend internals). diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 138b879..1d00f17 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ + + + diff --git a/android/app/src/main/res/drawable-night-xhdpi/android12splash.png b/android/app/src/main/res/drawable-night-xhdpi/android12splash.png new file mode 100644 index 0000000..87d4a2f Binary files /dev/null and b/android/app/src/main/res/drawable-night-xhdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-night-xhdpi/splash.png b/android/app/src/main/res/drawable-night-xhdpi/splash.png new file mode 100644 index 0000000..87d4a2f Binary files /dev/null and b/android/app/src/main/res/drawable-night-xhdpi/splash.png differ diff --git a/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png b/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png new file mode 100644 index 0000000..ede9677 Binary files /dev/null and b/android/app/src/main/res/drawable-night-xxhdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-night-xxhdpi/splash.png b/android/app/src/main/res/drawable-night-xxhdpi/splash.png new file mode 100644 index 0000000..ede9677 Binary files /dev/null and b/android/app/src/main/res/drawable-night-xxhdpi/splash.png differ diff --git a/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png b/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png new file mode 100644 index 0000000..fd73c39 Binary files /dev/null and b/android/app/src/main/res/drawable-night-xxxhdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-night-xxxhdpi/splash.png b/android/app/src/main/res/drawable-night-xxxhdpi/splash.png new file mode 100644 index 0000000..fd73c39 Binary files /dev/null and b/android/app/src/main/res/drawable-night-xxxhdpi/splash.png differ diff --git a/android/app/src/main/res/drawable-night/launch_background.xml b/android/app/src/main/res/drawable-night/launch_background.xml index f88598c..3cc4948 100644 --- a/android/app/src/main/res/drawable-night/launch_background.xml +++ b/android/app/src/main/res/drawable-night/launch_background.xml @@ -3,4 +3,7 @@ + + + diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml index f88598c..3cc4948 100644 --- a/android/app/src/main/res/drawable-v21/launch_background.xml +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -3,4 +3,7 @@ + + + diff --git a/android/app/src/main/res/drawable-xhdpi/android12splash.png b/android/app/src/main/res/drawable-xhdpi/android12splash.png new file mode 100644 index 0000000..87d4a2f Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png index 8364f1f..19e895f 100644 Binary files a/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png and b/android/app/src/main/res/drawable-xhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/splash.png b/android/app/src/main/res/drawable-xhdpi/splash.png new file mode 100644 index 0000000..87d4a2f Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/splash.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/android12splash.png b/android/app/src/main/res/drawable-xxhdpi/android12splash.png new file mode 100644 index 0000000..ede9677 Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png index 1e675ba..201c7e2 100644 Binary files a/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png and b/android/app/src/main/res/drawable-xxhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/splash.png b/android/app/src/main/res/drawable-xxhdpi/splash.png new file mode 100644 index 0000000..ede9677 Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/splash.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/android12splash.png b/android/app/src/main/res/drawable-xxxhdpi/android12splash.png new file mode 100644 index 0000000..fd73c39 Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/android12splash.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png b/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png index e595bed..468c860 100644 Binary files a/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png and b/android/app/src/main/res/drawable-xxxhdpi/ic_launcher_foreground.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/splash.png b/android/app/src/main/res/drawable-xxxhdpi/splash.png new file mode 100644 index 0000000..fd73c39 Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/splash.png differ diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml index f88598c..3cc4948 100644 --- a/android/app/src/main/res/drawable/launch_background.xml +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -3,4 +3,7 @@ + + + diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml index 5f349f7..c79c58a 100644 --- a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -1,5 +1,9 @@ - + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index 325ce73..85162c9 100644 Binary files a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index 31f8843..1bc9173 100644 Binary files a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index 2ec18b1..2abb97e 100644 Binary files a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index 2037d0b..3618aea 100644 Binary files a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 51305c0..1d72fd2 100644 Binary files a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/values-night-v31/styles.xml b/android/app/src/main/res/values-night-v31/styles.xml index 793e03a..55c68da 100644 --- a/android/app/src/main/res/values-night-v31/styles.xml +++ b/android/app/src/main/res/values-night-v31/styles.xml @@ -7,6 +7,7 @@ false shortEdges #1a1a2e + @drawable/android12splash - + - hwhub + car64 + + +