Skip to content
Open
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
109 changes: 109 additions & 0 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
name: Flutter CI

on:
push:
branches: [ "dev" , "main" ]
pull_request:
branches: [ "dev" , "main" ]
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 45

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
cache: true

- name: Cache Gradle packages
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-

- name: Cache pub dependencies
uses: actions/cache@v3
with:
path: |
${{ env.PUB_CACHE }}
~/.pub-cache
key: ${{ runner.os }}-pub-${{ hashFiles('**/pubspec.lock') }}
restore-keys: |
${{ runner.os }}-pub-

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '18'

- name: Install Firebase CLI
run: npm install -g firebase-tools

- name: Install FlutterFire CLI
run: dart pub global activate flutterfire_cli
- name: Install dependencies
run: flutter pub get

- name: Generate local code
run: flutter pub run build_runner build --delete-conflicting-outputs

- name: Generate Firebase Options
env:
FIREBASE_PROJECT_ID: ${{ secrets.FIREBASE_PROJECT_ID }}
FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
run: flutterfire configure --project=$FIREBASE_PROJECT_ID -y --platforms=android --out=lib/firebase_options.dart --token=$FIREBASE_TOKEN --android-package-name=com.pennypilot.moneyplus

- name: Configure Gradle memory
run: |
mkdir -p ~/.gradle
cat > ~/.gradle/gradle.properties << EOF
org.gradle.jvmargs=-Xmx4096m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError
org.gradle.daemon=false
org.gradle.parallel=true
org.gradle.caching=true
android.useAndroidX=true
android.enableJetifier=true
EOF

- name: Decode keystore
env:
ANDROID_KEYSTORE_BASE64: ${{ secrets.SIGNING_KEY_BASE64 }}
run: echo "$ANDROID_KEYSTORE_BASE64" | base64 --decode > android/app/upload-keystore.jks

- name: Create key.properties
env:
ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
ANDROID_KEY_ALIAS_PASSWORD: ${{ secrets.ANDROID_KEY_ALIAS_PASSWORD }}
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
run: |
cat <<EOF > android/key.properties
storePassword=$ANDROID_KEYSTORE_PASSWORD
keyPassword=$ANDROID_KEY_ALIAS_PASSWORD
keyAlias=$ANDROID_KEY_ALIAS
storeFile=upload-keystore.jks
EOF

- name: Build release APK
timeout-minutes: 30
run: flutter build apk --release --obfuscate --split-debug-info=build/app/outputs/symbols

- name: Distribute to Firebase
env:
FIREBASE_APP_ID: ${{ secrets.FIREBASE_APP_ID }}
FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
run: |
firebase appdistribution:distribute build/app/outputs/flutter-apk/app-release.apk \
--app "$FIREBASE_APP_ID" \
--groups "closed-beta-testers" \
--release-notes "Build from ${{ github.ref_name }} - Commit: ${{ github.sha }}"
59 changes: 0 additions & 59 deletions .github/workflows/flutter_build.yml

This file was deleted.

32 changes: 32 additions & 0 deletions .github/workflows/ios.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Flutter CI iOS

on:
push:
branches: [ "dev", "main" ]
pull_request:
branches: [ "dev", "main" ]
workflow_dispatch:

jobs:
build-ios:
runs-on: macos-latest
timeout-minutes: 60

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
cache: true

- name: Install dependencies
run: flutter pub get

- name: Generate local code
run: flutter pub run build_runner build --delete-conflicting-outputs

- name: Build iOS (simulator)
run: flutter build ios --simulator
54 changes: 40 additions & 14 deletions android/app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,15 +1,34 @@
import java.util.Properties
import java.io.FileInputStream
plugins {
id("com.android.application")
// START: FlutterFire Configuration
id("com.google.gms.google-services")
id("com.google.firebase.crashlytics")
// END: FlutterFire Configuration
id("kotlin-android")
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
id("dev.flutter.flutter-gradle-plugin")
}

val keystoreProperties = Properties()
val keystorePropertiesFile = rootProject.file("key.properties")
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(FileInputStream(keystorePropertiesFile))
}

android {
namespace = "com.pennypilot.moneyplus"
compileSdk = flutter.compileSdkVersion
ndkVersion = flutter.ndkVersion

defaultConfig {
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
}

compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
Expand All @@ -19,26 +38,33 @@ android {
jvmTarget = JavaVersion.VERSION_17.toString()
}

defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId = "com.pennypilot.moneyplus"
// You can update the following values to match your application needs.
// For more information, see: https://flutter.dev/to/review-gradle-config.
minSdk = flutter.minSdkVersion
targetSdk = flutter.targetSdkVersion
versionCode = flutter.versionCode
versionName = flutter.versionName
signingConfigs {
create("release") {
keyAlias = keystoreProperties.getProperty("keyAlias")
keyPassword = keystoreProperties.getProperty("keyPassword")
storeFile = file(keystoreProperties.getProperty("storeFile"))
storePassword = keystoreProperties.getProperty("storePassword")
}
}

buildTypes {
release {
// TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.getByName("debug")

getByName("release") {
signingConfig = signingConfigs.getByName("release")
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
ndk {
abiFilters.clear()
abiFilters.addAll(listOf("armeabi-v7a", "arm64-v8a"))
}

}
}
}

flutter {
source = "../.."
}
4 changes: 4 additions & 0 deletions android/settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ pluginManagement {
plugins {
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
id("com.android.application") version "8.11.1" apply false
// START: FlutterFire Configuration
id("com.google.gms.google-services") version("4.3.15") apply false
id("com.google.firebase.crashlytics") version("2.8.1") apply false
// END: FlutterFire Configuration
id("org.jetbrains.kotlin.android") version "2.2.20" apply false
}

Expand Down
5 changes: 5 additions & 0 deletions lib/core/constants/app_constants.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,9 @@ class AppConstants {

// Deep link paths
static const String resetPasswordRedirect = "com.pennypilot.moneyplus://reset-password";

static const String googleWebClientId = "GOOGLE_WEB_CLIENT_ID";
static const String googleIosClientId = "GOOGLE_IOS_CLIENT_ID";
static const String hashedSignature = "TALSEC_SIGNING_CERT_HASH";
static const String watcherMail = "TALSEC_WATCHER_MAIL";
}
65 changes: 65 additions & 0 deletions lib/core/di/cubit_di.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import 'package:moneyplus/domain/repository/account_repository.dart';
import 'package:moneyplus/domain/repository/authentication_repository.dart';
import 'package:moneyplus/domain/repository/statistics_repository.dart';
import 'package:moneyplus/domain/repository/transaction_repository.dart';
import 'package:moneyplus/domain/repository/user_money_repository.dart';
import 'package:moneyplus/domain/validator/authentication_validator.dart';
import 'package:moneyplus/presentation/account_setup/cubit/account_setup_cubit.dart';
import 'package:moneyplus/presentation/home/cubit/home_cubit.dart';
import 'package:moneyplus/presentation/income/cubit/add_income_cubit.dart';
import 'package:moneyplus/presentation/login/cubit/login_cubit.dart';
import 'package:moneyplus/presentation/statistics/cubit/statistics_cubit.dart';
import 'package:moneyplus/presentation/transactions/cubit/transaction_cubit.dart';
import 'package:moneyplus/presentation/trasnaction_details/trasnaction_details_cubit.dart';

import '../../presentation/expense/cubit/add_expense_cubit.dart';
import 'injection.dart';

void initCubitDI() {
getIt.registerLazySingleton<AuthenticationValidator>(
() => AuthenticationValidator(),
);

getIt.registerFactory<HomeCubit>(
() => HomeCubit(userMoneyRepository: getIt<UserMoneyRepository>()),
);

getIt.registerFactory<LoginCubit>(
() => LoginCubit(
authRepository: getIt<AuthenticationRepository>(),
validator: getIt<AuthenticationValidator>(),
),
);

getIt.registerLazySingleton<AccountSetupCubit>(
() => AccountSetupCubit(getIt<AccountRepository>()),
);

getIt.registerFactory<AddExpenseCubit>(
() => AddExpenseCubit(
transactionRepository: getIt<TransactionRepository>(),
userMoneyRepository: getIt<UserMoneyRepository>(),
),
);
getIt.registerFactory<AddIncomeCubit>(
() => AddIncomeCubit(
transactionRepository: getIt<TransactionRepository>(),
userMoneyRepository: getIt<UserMoneyRepository>(),
),
);

getIt.registerFactory<TransactionCubit>(
() =>
TransactionCubit(transactionRepository: getIt<TransactionRepository>()),
);

getIt.registerFactory<StatisticsCubit>(
() => StatisticsCubit(repository: getIt<StatisticsRepository>()),
);

getIt.registerFactory<TransactionDetailsCubit>(
() => TransactionDetailsCubit(
transactionRepository: getIt<TransactionRepository>(),
),
);
}
Loading
Loading