Skip to content

Commit 2d20fe9

Browse files
authored
Merge pull request #3 from AshvikMishra/dev
feat: complete app integration and final merge to main repo
2 parents d4be529 + 09e89ab commit 2d20fe9

File tree

225 files changed

+13135
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

225 files changed

+13135
-0
lines changed

leaderboard_app/.gitignore

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Miscellaneous
2+
*.class
3+
*.log
4+
*.pyc
5+
*.swp
6+
.DS_Store
7+
.atom/
8+
.build/
9+
.buildlog/
10+
.history
11+
.svn/
12+
.swiftpm/
13+
migrate_working_dir/
14+
15+
# IntelliJ related
16+
*.iml
17+
*.ipr
18+
*.iws
19+
.idea/
20+
21+
# The .vscode folder contains launch configuration and tasks you configure in
22+
# VS Code which you may wish to be included in version control, so this line
23+
# is commented out by default.
24+
#.vscode/
25+
26+
# Flutter/Dart/Pub related
27+
**/doc/api/
28+
**/ios/Flutter/.last_build_id
29+
.dart_tool/
30+
.flutter-plugins-dependencies
31+
.pub-cache/
32+
.pub/
33+
/build/
34+
/coverage/
35+
36+
# Symbolication related
37+
app.*.symbols
38+
39+
# Obfuscation related
40+
app.*.map.json
41+
42+
# Android Studio will place build artifacts here
43+
/android/app/debug
44+
/android/app/profile
45+
/android/app/release

leaderboard_app/.metadata

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# This file tracks properties of this Flutter project.
2+
# Used by Flutter tool to assess capabilities and perform upgrades etc.
3+
#
4+
# This file should be version controlled and should not be manually edited.
5+
6+
version:
7+
revision: "02da4cc00db9eb97fc48e89d319ef48518c2440a"
8+
channel: "master"
9+
10+
project_type: app
11+
12+
# Tracks metadata for the flutter migrate command
13+
migration:
14+
platforms:
15+
- platform: root
16+
create_revision: 02da4cc00db9eb97fc48e89d319ef48518c2440a
17+
base_revision: 02da4cc00db9eb97fc48e89d319ef48518c2440a
18+
- platform: android
19+
create_revision: 02da4cc00db9eb97fc48e89d319ef48518c2440a
20+
base_revision: 02da4cc00db9eb97fc48e89d319ef48518c2440a
21+
- platform: ios
22+
create_revision: 02da4cc00db9eb97fc48e89d319ef48518c2440a
23+
base_revision: 02da4cc00db9eb97fc48e89d319ef48518c2440a
24+
- platform: linux
25+
create_revision: 02da4cc00db9eb97fc48e89d319ef48518c2440a
26+
base_revision: 02da4cc00db9eb97fc48e89d319ef48518c2440a
27+
- platform: macos
28+
create_revision: 02da4cc00db9eb97fc48e89d319ef48518c2440a
29+
base_revision: 02da4cc00db9eb97fc48e89d319ef48518c2440a
30+
- platform: web
31+
create_revision: 02da4cc00db9eb97fc48e89d319ef48518c2440a
32+
base_revision: 02da4cc00db9eb97fc48e89d319ef48518c2440a
33+
- platform: windows
34+
create_revision: 02da4cc00db9eb97fc48e89d319ef48518c2440a
35+
base_revision: 02da4cc00db9eb97fc48e89d319ef48518c2440a
36+
37+
# User provided section
38+
39+
# List of Local paths (relative to this file) that should be
40+
# ignored by the migrate tool.
41+
#
42+
# Files that are not part of the templates will be ignored by default.
43+
unmanaged_files:
44+
- 'lib/main.dart'
45+
- 'ios/Runner.xcodeproj/project.pbxproj'

leaderboard_app/README.md

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
# leaderboard_app
2+
3+
Flutter application with backend integration using `dio` + `retrofit` for typed HTTP APIs.
4+
5+
## Backend Integration
6+
7+
We use:
8+
9+
* `dio` for HTTP transport, interceptors, timeouts.
10+
* `retrofit` for declarative REST interface generation (`lib/services/core/rest_client.dart`).
11+
* `build_runner` + `retrofit_generator` (and `json_serializable` if/when model code generation is added).
12+
13+
### Generating code
14+
15+
Run code generation after updating API interface annotations:
16+
17+
```bash
18+
dart run build_runner build --delete-conflicting-outputs
19+
```
20+
21+
### Using the REST client
22+
23+
```dart
24+
import 'package:leaderboard_app/services/core/dio_provider.dart';
25+
import 'package:leaderboard_app/services/core/rest_client.dart';
26+
27+
final dio = await DioProvider.getInstance();
28+
final api = RestClient(dio);
29+
30+
final start = await api.startVerification({'leetcodeUsername': 'someUser'});
31+
final status = await api.getVerificationStatus('someUser');
32+
```
33+
34+
Auth tokens (JWT) are automatically attached from `SharedPreferences` via an interceptor in `DioProvider`.
35+
36+
### Environment / Base URL
37+
38+
Centralized in `lib/config/api_config.dart`.
39+
40+
Default baked-in base URL (when no override is supplied):
41+
42+
```
43+
http://140.238.213.170:3002/api
44+
```
45+
46+
Override at build/run time:
47+
48+
```bash
49+
flutter run --dart-define=API_BASE_URL=https://your.api.host/api
50+
```
51+
52+
Release / CI example:
53+
54+
```bash
55+
flutter build apk --dart-define=API_BASE_URL=https://prod.api.host/api
56+
```
57+
58+
Trailing slashes are trimmed automatically. Keep `/api` if your backend routes are under that prefix.
59+
60+
### Adding new endpoints
61+
62+
1. Edit `lib/services/core/rest_client.dart` – add a method with appropriate HTTP verb annotation.
63+
2. Run the build command above to regenerate `rest_client.g.dart`.
64+
3. Consume the new method from services or providers.
65+
66+
### Logging & Retry
67+
68+
`DioProvider` adds a lightweight log interceptor and simple retry (only once) for idempotent GET requests on connection errors.
69+
70+
---
71+
72+
Generated code (`rest_client.g.dart`) should not be manually edited.
73+
74+
75+
## Building a Release APK / Sharing the App
76+
77+
1. (Optional) Override the API base URL at build time (recommended for different envs):
78+
79+
```bash
80+
flutter build apk --release --dart-define=API_BASE_URL=https://prod.api.host/api
81+
```
82+
83+
If you omit `--dart-define` the baked-in default from `ApiConfig` is used.
84+
85+
2. The unsigned release APK will be at:
86+
87+
```
88+
build\app\outputs\flutter-apk\app-release.apk
89+
```
90+
91+
3. (Recommended) Create a keystore and configure signing in `android/key.properties` + `build.gradle` to avoid Play Store rejection and to allow in-place upgrades.
92+
93+
### Example keystore creation (run once)
94+
95+
```bash
96+
keytool -genkey -v -keystore my-release-key.keystore -alias upload -keyalg RSA -keysize 2048 -validity 10000
97+
```
98+
99+
Place the keystore under `android/` (never commit to VCS) and add a `key.properties`:
100+
101+
```
102+
storePassword=YOUR_STORE_PASSWORD
103+
keyPassword=YOUR_KEY_PASSWORD
104+
keyAlias=upload
105+
storeFile=../my-release-key.keystore
106+
```
107+
108+
Then update `android/app/build.gradle` signingConfigs + buildTypes (if not already present).
109+
110+
### Distributing for quick tests
111+
112+
You can directly share `app-release.apk` with testers (they must enable install from unknown sources). For Play Store publishing prefer an AAB:
113+
114+
```bash
115+
flutter build appbundle --dart-define=API_BASE_URL=https://prod.api.host/api
116+
```
117+
118+
## Troubleshooting: "Cannot reach server. Check BASE_URL..."
119+
120+
This message originates from `ErrorUtils.fromDio` when the `DioExceptionType.connectionError` occurs. Common causes:
121+
122+
| Cause | Fix |
123+
|-------|-----|
124+
| Device has no internet | Ensure Wi‑Fi/data works (open a website) |
125+
| Backend URL wrong or down | Open the URL in mobile Chrome to verify response |
126+
| Using `localhost` / private IP not reachable externally | Use a public/stable host or expose via tunneling (ngrok, Cloudflare) |
127+
| HTTP blocked (if you switch to HTTPS only) | Ensure correct scheme in `API_BASE_URL` |
128+
| Missing INTERNET permission | Manifest now includes `<uses-permission android:name="android.permission.INTERNET" />` |
129+
130+
To quickly verify the URL the app is using, add a temporary log:
131+
132+
```dart
133+
print('API base URL: ' + ApiConfig.baseUrl);
134+
```
135+
136+
Or run with an override:
137+
138+
```bash
139+
flutter run --release --dart-define=API_BASE_URL=https://your-temp-api/api
140+
```
141+
142+
If the backend uses a self-signed certificate, Android may reject it—use a valid cert (Let's Encrypt) for production.
143+
144+
## Future Enhancements (Optional)
145+
146+
* Add build flavors: dev / staging / prod with per-flavor `--dart-define` presets.
147+
* Add environment banner in-app for non-prod.
148+
* Implement exponential backoff retries for transient network errors.
149+
* Add Sentry or similar for error monitoring.
150+
151+
## Splash Screen & Offline Handling
152+
153+
The app shows a native splash (configured via `flutter_native_splash`) while core services initialize. For returning users (flag stored in `SharedPreferences` as `returningUser`), dashboard data is preloaded (daily question, submissions if verified, leaderboard) before removing the splash to deliver a populated home view quickly.
154+
155+
If there's no network connectivity at launch, a dedicated offline screen (`NoInternetPage`) is displayed. Connectivity is monitored with `connectivity_plus` through `ConnectivityProvider`; once a connection becomes available the app automatically proceeds with initialization and dismisses the splash.
156+
157+
Update splash assets/colors in `pubspec.yaml` under `flutter_native_splash:` then regenerate:
158+
159+
```bash
160+
flutter pub run flutter_native_splash:create
161+
```
162+
163+
Key files:
164+
165+
* `lib/main.dart` – splash preservation & initialization logic (`_AppInitializer`).
166+
* `lib/provider/connectivity_provider.dart` – connectivity listener.
167+
* `lib/pages/no_internet_page.dart` – offline UI.
168+
169+
To disable preloading behavior simply remove the `dashboardProvider.loadAll()` call in `_preload()`.
170+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
include: package:flutter_lints/flutter.yaml

leaderboard_app/android/.gitignore

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
gradle-wrapper.jar
2+
/.gradle
3+
/captures/
4+
/gradlew
5+
/gradlew.bat
6+
/local.properties
7+
GeneratedPluginRegistrant.java
8+
.cxx/
9+
10+
# Remember to never publicly share your keystore.
11+
# See https://flutter.dev/to/reference-keystore
12+
key.properties
13+
**/*.keystore
14+
**/*.jks
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
plugins {
2+
id("com.android.application")
3+
id("kotlin-android")
4+
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
5+
id("dev.flutter.flutter-gradle-plugin")
6+
}
7+
8+
android {
9+
namespace = "com.dscvit.leeterboard"
10+
compileSdk = flutter.compileSdkVersion
11+
ndkVersion = flutter.ndkVersion
12+
13+
compileOptions {
14+
sourceCompatibility = JavaVersion.VERSION_11
15+
targetCompatibility = JavaVersion.VERSION_11
16+
}
17+
18+
kotlinOptions {
19+
jvmTarget = JavaVersion.VERSION_11.toString()
20+
}
21+
22+
defaultConfig {
23+
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
24+
applicationId = "com.dscvit.leeterboard"
25+
// You can update the following values to match your application needs.
26+
// For more information, see: https://flutter.dev/to/review-gradle-config.
27+
minSdk = flutter.minSdkVersion
28+
targetSdk = flutter.targetSdkVersion
29+
versionCode = flutter.versionCode
30+
versionName = flutter.versionName
31+
}
32+
33+
buildTypes {
34+
release {
35+
// TODO: Add your own signing config for the release build.
36+
// Signing with the debug keys for now, so `flutter run --release` works.
37+
signingConfig = signingConfigs.getByName("debug")
38+
}
39+
}
40+
}
41+
42+
flutter {
43+
source = "../.."
44+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
2+
<!-- The INTERNET permission is required for development. Specifically,
3+
the Flutter tool needs it to communicate with the running application
4+
to allow setting breakpoints, to provide hot reload, etc.
5+
-->
6+
<uses-permission android:name="android.permission.INTERNET"/>
7+
</manifest>
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
2+
<!-- Network permissions required for API calls in release builds -->
3+
<uses-permission android:name="android.permission.INTERNET" />
4+
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
5+
<application
6+
android:label="LeeterBoard"
7+
android:name="${applicationName}"
8+
android:icon="@mipmap/ic_launcher"
9+
android:usesCleartextTraffic="true"
10+
android:networkSecurityConfig="@xml/network_security_config">
11+
<activity
12+
android:name=".MainActivity"
13+
android:exported="true"
14+
android:launchMode="singleTop"
15+
android:taskAffinity=""
16+
android:theme="@style/LaunchTheme"
17+
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
18+
android:hardwareAccelerated="true"
19+
android:windowSoftInputMode="adjustResize">
20+
<!-- Specifies an Android theme to apply to this Activity as soon as
21+
the Android process has started. This theme is visible to the user
22+
while the Flutter UI initializes. After that, this theme continues
23+
to determine the Window background behind the Flutter UI. -->
24+
<meta-data
25+
android:name="io.flutter.embedding.android.NormalTheme"
26+
android:resource="@style/NormalTheme"
27+
/>
28+
<intent-filter>
29+
<action android:name="android.intent.action.MAIN"/>
30+
<category android:name="android.intent.category.LAUNCHER"/>
31+
</intent-filter>
32+
</activity>
33+
<!-- Don't delete the meta-data below.
34+
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
35+
<meta-data
36+
android:name="flutterEmbedding"
37+
android:value="2" />
38+
</application>
39+
<!-- Required to query activities that can process text, see:
40+
https://developer.android.com/training/package-visibility and
41+
https://developer.android.com/reference/android/content/Intent#ACTION_PROCESS_TEXT.
42+
43+
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
44+
<queries>
45+
<intent>
46+
<action android:name="android.intent.action.PROCESS_TEXT"/>
47+
<data android:mimeType="text/plain"/>
48+
</intent>
49+
</queries>
50+
</manifest>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.dscvit.leeterboard
2+
3+
import io.flutter.embedding.android.FlutterActivity
4+
5+
class MainActivity : FlutterActivity()
8.57 KB
Loading

0 commit comments

Comments
 (0)