Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
269be20
fix: adjust padding and input focus handling in various screens
vishaltsolguruz Apr 9, 2026
78b6a5a
test: add unit tests for blocs, use cases, and repositories
vishaltsolguruz Apr 10, 2026
ce16a90
fix: remove redundant isPersonalized field and update date formats in…
vishaltsolguruz Apr 10, 2026
834d378
refactor: refactor test descriptions to follow "should" naming conven…
GaneshSolGuruz Apr 14, 2026
3386d81
feat: add unit tests for theme extension and app version helper
GaneshSolGuruz Apr 14, 2026
49425c3
feat: implement unit tests for validators and file validation results
GaneshSolGuruz Apr 14, 2026
4785f08
Merge pull request #83 from solguruz/fix/content_hidden_behind_bottom…
vishaltsolguruz Apr 14, 2026
8f1483a
Merge remote-tracking branch 'origin/develop' into feat/extension_val…
GaneshSolGuruz Apr 15, 2026
6592a4a
feat: implement an AI ChatBot
vishaltsolguruz Apr 20, 2026
8ee4fcb
feat: enhance AI ChatBot UI with improved styling and layout adjustments
vishaltsolguruz Apr 21, 2026
e6304a5
ref: update golden images
vishaltsolguruz Apr 21, 2026
42cbf14
feat: add a golden test for AI ChatBot
vishaltsolguruz Apr 21, 2026
b27b8ae
Merge pull request #85 from solguruz/feat/ai_chatbot
vishaltsolguruz Apr 24, 2026
2404138
feat: implement in-app review service and integrate into home screen
vishaltsolguruz May 12, 2026
4cfef0e
Merge pull request #86 from solguruz/feat/in_app_feedback_native
vishaltsolguruz May 13, 2026
dc5c1db
fix: correct import path for theme_extension.dart across multiple files
vishaltsolguruz May 13, 2026
6953fcc
feat: implement chat functionality and update its golden test case
vishaltsolguruz May 13, 2026
21ba2ee
Merge remote-tracking branch 'origin/develop' into feat/extension_val…
GaneshSolGuruz May 14, 2026
ed51c29
Merge pull request #87 from solguruz/fix/correct_theme_extension_dire…
vishaltsolguruz May 14, 2026
bb7ba88
feat: integrate liquid glass design into AI chat UI components
vishaltsolguruz May 14, 2026
0611ec8
chore: upgrade Flutter SDK to version 3.41.9 and Dart SDK to version …
vishaltsolguruz May 14, 2026
940fdbb
chore: update dependencies in pubspec.lock for compatibility with Flu…
vishaltsolguruz May 14, 2026
54f4404
Merge pull request #89 from solguruz/chore/upgrade_flutter_sdk_3_41_9
vishaltsolguruz May 14, 2026
6618e7b
Merge remote-tracking branch 'origin/develop' into feat/chat_integration
vishaltsolguruz May 14, 2026
d118b68
chore: resolve merge conflicts
vishaltsolguruz May 14, 2026
337f7f8
Merge pull request #88 from solguruz/feat/chat_integration
vishaltsolguruz May 14, 2026
f19d902
Merge remote-tracking branch 'origin/develop' into feat/home_screen_l…
vishaltsolguruz May 14, 2026
f081ff2
chore: update dependencies in pubspec.lock
vishaltsolguruz May 14, 2026
c12c2a5
ref: update the golden test images for the AI Chatbot
vishaltsolguruz May 14, 2026
b0b3f5c
Merge pull request #90 from solguruz/feat/home_screen_liquid_glass_de…
vishaltsolguruz May 14, 2026
8d19de1
refactor: update navigation and UI components in home screen
vishaltsolguruz May 18, 2026
4a3bd3a
fix: add optional now param to timeAgo() for deterministic testing
GaneshSolGuruz May 18, 2026
17424cd
test: centralise mock localization setup and fix timeAgo test
GaneshSolGuruz May 18, 2026
4d5ea3e
Merge remote-tracking branch 'origin/develop' into feat/extension_val…
GaneshSolGuruz May 18, 2026
e580768
fix: correct spelling of "extension" in theme extension test imports
GaneshSolGuruz May 18, 2026
62d7146
Merge pull request #84 from solguruz/feat/extension_validator_test_case
vishaltsolguruz May 18, 2026
11fdac0
Merge remote-tracking branch 'origin/develop' into fix/search_screen
vishaltsolguruz May 19, 2026
a3ee562
ref: adopt shorthand enum syntax across the app
vishaltsolguruz May 19, 2026
decb6c5
Merge pull request #92 from solguruz/feat/dart_dot_shorthand
vishaltsolguruz May 20, 2026
e57501e
Merge remote-tracking branch 'origin/develop' into fix/search_screen
vishaltsolguruz May 20, 2026
d390d6d
Merge pull request #91 from solguruz/fix/search_screen
vishaltsolguruz May 20, 2026
038c070
chore: bump up version to 1.0.6+6
vishaltsolguruz May 21, 2026
af162bf
Merge pull request #93 from solguruz/chore/bump_version_1_0_6_6
vishaltsolguruz May 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 0 additions & 3 deletions .fvmrc

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ jobs:
- name: 2.1 Set up Flutter SDK
uses: subosito/flutter-action@v2.18.0
with:
flutter-version: '3.35.7'
flutter-version: '3.41.9'

# 2.2 Tool Sanity Check
# Confirm Flutter and Dart are installed properly (fail early)
Expand Down
27 changes: 16 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
![Quality gate](https://sonarqube.solz.me/api/project_badges/quality_gate?project=Skelter-Flutter&token=sqb_85d4c55a7bc25fe595483b116c4cf8f58723cb10)
<br/>

![Flutter](https://img.shields.io/badge/Flutter-v3.35.7-blue?logo=flutter)
![Dart](https://img.shields.io/badge/Dart-3.9.2-blue?logo=dart)
![Flutter](https://img.shields.io/badge/Flutter-v3.41.9-blue?logo=flutter)
![Dart](https://img.shields.io/badge/Dart-3.11.5-blue?logo=dart)
![Version](https://img.shields.io/badge/Version-1.0.4-blue)
![Apache](https://img.shields.io/badge/license-Apache-purple.svg)
<br/>
Expand All @@ -32,8 +32,8 @@ boiler plate code for rapid application development.

## Technology Stack

- **Flutter Version:** ^3.35.7
- **Dart SDK:** ^3.9.2
- **Flutter Version:** ^3.41.9
- **Dart SDK:** ^3.11.5
- **State Management:** BLoC
- **Navigation:** Auto Route
- **Backend Integration:** Firebase (Core, Analytics, Crashlytics, Auth)
Expand Down Expand Up @@ -86,7 +86,7 @@ flutter build ipa --export-method=ad-hoc --flavor prod --dart-define=APP_FLAVOR=
Follow these steps to configure SSL pinning in your Flutter project.

1. **Add Certificate Hash Variables to `.env`**
Add the SHA-256 SSL public key fingerprints for each flavor:
Add the SHA-256 certificate fingerprints (hex, lowercase, no separators) for each flavor:

```
CERT_HASH_DEV="add_your_dev_hash_here"
Expand All @@ -95,14 +95,17 @@ Follow these steps to configure SSL pinning in your Flutter project.
```

2. **Get Your Certificate Hash**
Run the following command (replace `yourdomain.com` with your API domain):
Run the following command (replace `yourdomain.com` with your API domain).
The `http_certificate_pinning` package expects the SHA-256 of the leaf
certificate, encoded as a 64-character lowercase hex string with no
separators:

```bash
openssl s_client -connect yourdomain.com:443 -servername yourdomain.com </dev/null 2>/dev/null \
| openssl x509 -pubkey -noout \
| openssl pkey -pubin -outform DER \
| openssl dgst -sha256 -binary \
| openssl enc -base64
echo | openssl s_client -servername yourdomain.com -connect yourdomain.com:443 2>/dev/null \
| openssl x509 -fingerprint -sha256 -noout \
| cut -d'=' -f2 \
| tr -d ':' \
| tr 'A-Z' 'a-z'
```

**Example output:**
Expand All @@ -111,6 +114,8 @@ Follow these steps to configure SSL pinning in your Flutter project.
```
Copy this value into the matching `CERT_HASH_*` variable in your `.env` file.

> **Note:** This pins the leaf certificate. Public certificates (e.g. Let's Encrypt) rotate every 60–90 days, after which you must regenerate the hash. For longer-lived pinning, consider hashing an intermediate CA certificate instead.

3. **Use the Certificate Hash in Code**
Add a method to fetch the correct hash for the current flavor:

Expand Down
3 changes: 2 additions & 1 deletion android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ plugins {
android {
namespace = "com.solguruz.skelter"
compileSdk = flutter.compileSdkVersion
ndkVersion = "27.0.12077973"
ndkVersion = "28.2.13676358"

compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
Expand Down Expand Up @@ -43,6 +43,7 @@ android {
// 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
proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
}
}

Expand Down
6 changes: 6 additions & 0 deletions android/app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Keep Flutter utility classes accessed reflectively by JNI-based plugins.
# Without these rules R8 strips io.flutter.util.PathUtils in release builds,
# which causes path_provider and similar plugins to throw ClassNotFoundException.
-keep class io.flutter.util.** { *; }
-keep class io.flutter.embedding.** { *; }
-dontwarn io.flutter.embedding.**
58 changes: 29 additions & 29 deletions lib/common/theme/text_style/app_text_styles.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,211 +4,211 @@ import 'package:skelter/gen/fonts.gen.dart';
class AppTextStyles {
static TextStyle h1 = const TextStyle(
fontSize: 29,
fontWeight: FontWeight.w900,
fontWeight: .w900,
fontFamily: FontFamily.inter,
height: 1.5,
letterSpacing: -0.28,
);

static TextStyle h2 = const TextStyle(
fontSize: 24,
fontWeight: FontWeight.w900,
fontWeight: .w900,
fontFamily: FontFamily.inter,
height: 1.5,
letterSpacing: -0.24,
);

static TextStyle h2Bold = const TextStyle(
fontSize: 24,
fontWeight: FontWeight.w700,
fontWeight: .w700,
fontFamily: FontFamily.inter,
height: 1.5,
letterSpacing: -0.24,
);

static TextStyle h3 = const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w900,
fontWeight: .w900,
fontFamily: FontFamily.inter,
height: 1.5,
letterSpacing: -0.24,
);

static TextStyle h3Medium = const TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
fontWeight: .w500,
fontFamily: FontFamily.inter,
height: 1.5,
letterSpacing: -0.24,
);

static TextStyle h5Bold = const TextStyle(
fontSize: 24,
fontWeight: FontWeight.w700,
fontWeight: .w700,
fontFamily: FontFamily.inter,
height: 1.33,
letterSpacing: -0.24,
);

static TextStyle h6Medium = const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500,
fontWeight: .w500,
fontFamily: FontFamily.inter,
height: 1.5,
letterSpacing: -1,
);
static TextStyle h6Bold = const TextStyle(
fontSize: 20,
fontWeight: FontWeight.w700,
fontWeight: .w700,
fontFamily: FontFamily.inter,
height: 1.5,
letterSpacing: -1,
);

static TextStyle h4SemiBold = const TextStyle(
fontSize: 28,
fontWeight: FontWeight.w600,
fontWeight: .w600,
fontFamily: FontFamily.inter,
height: 36 / 28,
letterSpacing: -0.28,
);

static TextStyle h6SemiBold = const TextStyle(
fontSize: 20,
fontWeight: FontWeight.w600,
fontWeight: .w600,
fontFamily: FontFamily.inter,
height: 1.5,
letterSpacing: -1,
);

static TextStyle p3Regular = const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w400,
fontWeight: .w400,
fontFamily: FontFamily.inter,
height: 1.5,
);

static TextStyle p1Medium = const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w500,
fontWeight: .w500,
fontFamily: FontFamily.inter,
height: 1.5,
);

static TextStyle p1SemiBold = const TextStyle(
fontSize: 18,
fontWeight: FontWeight.w600,
fontWeight: .w600,
fontFamily: FontFamily.inter,
height: 1.5,
);

static TextStyle p2Medium = const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
fontWeight: .w500,
fontFamily: FontFamily.inter,
height: 1.5,
);

static TextStyle p2Regular = const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w400,
fontWeight: .w400,
fontFamily: FontFamily.inter,
height: 1.5,
);

static TextStyle p3Medium = const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
fontWeight: .w500,
fontFamily: FontFamily.inter,
height: 1.5,
);

static TextStyle p3SemiBold = const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
fontWeight: .w600,
fontFamily: FontFamily.inter,
height: 1.5,
);

static TextStyle p4Medium = const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w500,
fontWeight: .w500,
fontFamily: FontFamily.inter,
height: 1.5,
);

static TextStyle p4Regular = const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w400,
fontWeight: .w400,
fontFamily: FontFamily.inter,
height: 1.5,
);

static TextStyle p1Bold = const TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
fontWeight: .bold,
fontFamily: FontFamily.inter,
height: 1.5,
);

static TextStyle p2Bold = const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
fontWeight: .bold,
fontFamily: FontFamily.inter,
height: 1.5,
);

static TextStyle p2SemiBold = const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
fontWeight: .w600,
fontFamily: FontFamily.inter,
height: 1.5,
);

static TextStyle p3Bold = const TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
fontWeight: .bold,
fontFamily: FontFamily.inter,
height: 1.5,
);
static TextStyle p4SemiBold = const TextStyle(
fontSize: 12,
fontWeight: FontWeight.w600,
fontWeight: .w600,
fontFamily: FontFamily.inter,
height: 1.5,
);

static TextStyle p4Bold = const TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
fontWeight: .bold,
fontFamily: FontFamily.inter,
height: 1.5,
);

static TextStyle c1SemiBold = const TextStyle(
fontSize: 10,
fontWeight: FontWeight.w600,
fontWeight: .w600,
fontFamily: FontFamily.inter,
height: 1.4,
);

static TextStyle c2Regular = const TextStyle(
fontSize: 10,
fontWeight: FontWeight.w400,
fontWeight: .w400,
fontFamily: FontFamily.inter,
height: 1.5,
);

static TextStyle c2Medium = const TextStyle(
fontSize: 10,
fontWeight: FontWeight.w500,
fontWeight: .w500,
fontFamily: FontFamily.inter,
height: 1.5,
);

static TextStyle c2SemiBold = const TextStyle(
fontSize: 10,
fontWeight: FontWeight.w600,
fontWeight: .w600,
fontFamily: FontFamily.inter,
height: 1.5,
);
Expand Down
9 changes: 9 additions & 0 deletions lib/constants/constants.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
const String kLogFileName = 'app.log';

/// Play Store applicationId of the published Android app.
/// Used by the in-app review flow to deep-link to the store listing.
const String kGooglePlayIdentifier = 'com.solguruz.skelter';

/// Numeric App Store ID from App Store Connect (e.g. `'1234567890'`).
/// Placeholder — replace before iOS release. Not read by the native review
/// dialog (StoreKit uses bundle id); only consumed by `launchStore()`.
const String kAppStoreIdentifier = '0000000000';

const kMimeTypeVideo = 'video/';
const kMimeTypeImage = 'image/';
const kSVGWithDot = '.svg';
Expand Down
12 changes: 6 additions & 6 deletions lib/core/services/app_tour_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ class AppTourService {
return Container(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: .min,
crossAxisAlignment: .start,
children: [
Text(
context.localization.tour_search_title,
Expand All @@ -96,7 +96,7 @@ class AppTourService {
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisAlignment: .end,
children: [
AppButton(
onPressed: () => controller.skip(),
Expand Down Expand Up @@ -132,8 +132,8 @@ class AppTourService {
return Container(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: .min,
crossAxisAlignment: .start,
children: [
Text(
context.localization.tour_nav_title,
Expand All @@ -150,7 +150,7 @@ class AppTourService {
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisAlignment: .end,
children: [
AppButton(
onPressed: () => controller.next(),
Expand Down
Loading
Loading