Skip to content

Commit

Permalink
refactor: Moved components and utils to AppToolkit library
Browse files Browse the repository at this point in the history
- Moved various UI components (dialogs, preferences, spacers) and utility classes (ClipboardHelper, IntentsHelper, PermissionsHelper) to the AppToolkit library.
- Updated usages of these components and utils in the app to use the versions from AppToolkit.
- Updated dependencies and imports to reflect the move.
- Removed the now unused classes and resources from the app.
  • Loading branch information
Mihai-Cristian Condrea committed Feb 13, 2025
1 parent 5f650f9 commit 2ccf959
Show file tree
Hide file tree
Showing 40 changed files with 810 additions and 1,051 deletions.
95 changes: 81 additions & 14 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,33 +1,100 @@
# Gradle files
###############################################################################
# BUILD OUTPUTS
###############################################################################
# Gradle build cache and output
.gradle/
build/
generated/

# Local configuration file (sdk path, etc)
# Ignore generated binaries and other typical build artifacts
bin/
gen/
out/

# Android packaged/bundled application files
*.apk
*.aab

# Dalvik/ART VM bytecode
*.dex

# Java/Kotlin class files
*.class

# Release artifacts (uncomment or adjust as needed)
app/release/*
release/

###############################################################################
# LOCAL CONFIG / ENV FILES
###############################################################################
# SDK path and other local configurations
local.properties

# Log/OS Files
# Proguard folder generated by Eclipse
proguard/

###############################################################################
# LOG / OS FILES
###############################################################################
# Log files
*.log

# Android Studio generated files and folders
# macOS Finder metadata
.DS_Store

# Windows thumbnail cache files (if needed)
Thumbs.db

###############################################################################
# ANDROID STUDIO / INTELLIJ
###############################################################################
# Android Studio captures folder
captures/

# Android Studio generated external native build folders
.externalNativeBuild/
.cxx/
*.apk
output.json

# IntelliJ
# Gradle user-specific settings in IntelliJ/Android Studio
*.iml
.idea/
# If you'd like to keep your code style settings in VCS, leave the negated lines
.idea/*
!.idea/codeStyles
/.idea/codeStyles/*
!/.idea/codeStyles/Project.xml
!/.idea/codeStyles/codeStyleConfig.xml

# Other IntelliJ/AS config files
misc.xml
deploymentTargetDropDown.xml
render.experimental.xml
.navigation/
.idea/libraries
.idea/caches
.idea/modules.xml
.idea/navEditor.xml

###############################################################################
# ANDROID PROFILING
###############################################################################
*.hprof

# Keystore files
*.jks
*.keystore
###############################################################################
# VERSION CONTROL SYSTEM
###############################################################################
vcs.xml

# Google Services (e.g. APIs or Firebase)
google-services.json
###############################################################################
# LINT
###############################################################################
lint/intermediates/
lint/generated/
lint/outputs/
lint/tmp/

# Android Profiling
*.hprof
###############################################################################
# KOTLIN
###############################################################################
.kotlin
5 changes: 0 additions & 5 deletions .idea/appInsightsSettings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 5 additions & 16 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ android {
applicationId = "com.d4rk.cartcalculator"
minSdk = 23
targetSdk = 35
versionCode = 79
versionCode = 80
versionName = "1.2.1"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
resourceConfigurations += listOf(
@Suppress("UnstableApiUsage")
androidResources.localeFilters += listOf(
"en" ,
"bg-rBG" ,
"de-rDE" ,
Expand Down Expand Up @@ -94,24 +95,12 @@ android {
}

dependencies {

// App Core
implementation(dependencyNotation = "com.github.D4rK7355608:AppToolkit:0.0.15") {
implementation(dependencyNotation = "com.github.D4rK7355608:AppToolkit:0.0.54") {
isTransitive = true
}

// Firebase
implementation(dependencyNotation = platform(libs.firebase.bom))
implementation(dependencyNotation = libs.firebase.crashlytics.ktx)
implementation(dependencyNotation = libs.firebase.analytics.ktx)
implementation(dependencyNotation = libs.firebase.perf)

// Google
implementation(dependencyNotation = libs.play.services.ads)
implementation(dependencyNotation = libs.billing)
implementation(dependencyNotation = libs.review.ktx)
implementation(dependencyNotation = libs.app.update.ktx)
implementation(dependencyNotation = libs.volley)

// KSP
ksp(dependencyNotation = libs.androidx.room.compiler)
implementation(dependencyNotation = libs.androidx.room.ktx)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,124 +4,92 @@ package com.d4rk.cartcalculator.data.core

import android.annotation.SuppressLint
import android.app.Activity
import android.app.Application
import android.database.sqlite.SQLiteException
import android.os.Bundle
import android.util.Log
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.OnLifecycleEvent
import androidx.lifecycle.ProcessLifecycleOwner
import androidx.multidex.MultiDexApplication
import androidx.room.Room
import androidx.room.migration.Migration
import com.d4rk.cartcalculator.data.core.ads.AdsCoreManager
import com.d4rk.cartcalculator.data.core.datastore.DataStoreCoreManager
import com.d4rk.android.libs.apptoolkit.data.core.BaseCoreManager
import com.d4rk.android.libs.apptoolkit.data.core.ads.AdsCoreManager
import com.d4rk.android.libs.apptoolkit.utils.error.ErrorHandler
import com.d4rk.android.libs.apptoolkit.utils.error.ErrorHandler.handleInitializationFailure
import com.d4rk.cartcalculator.data.database.AppDatabase
import com.d4rk.cartcalculator.data.database.migrations.MIGRATION_2_3
import com.d4rk.cartcalculator.data.datastore.DataStore
import com.d4rk.cartcalculator.utils.error.ErrorHandler.handleInitializationFailure
import kotlinx.coroutines.CoroutineScope
import com.d4rk.cartcalculator.utils.constants.ads.AdsConstants
import com.d4rk.cartcalculator.utils.error.CrashlyticsErrorReporter
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.supervisorScope

class AppCoreManager : MultiDexApplication() , Application.ActivityLifecycleCallbacks ,
LifecycleObserver {
class AppCoreManager : BaseCoreManager() {

private val dataStoreCoreManager : DataStoreCoreManager by lazy {
DataStoreCoreManager(context = this)
}
private var currentActivity : Activity? = null

private val adsCoreManager : AdsCoreManager by lazy {
AdsCoreManager(context = this)
}
companion object {
@SuppressLint("StaticFieldLeak")
lateinit var instance : AppCoreManager
private set

private var currentActivity : Activity? = null
lateinit var dataStore : DataStore
private set

override fun onCreate() {
super.onCreate()
instance = this
registerActivityLifecycleCallbacks(this)
ProcessLifecycleOwner.get().lifecycle.addObserver(observer = this)
CoroutineScope(context = Dispatchers.IO).launch {
initializeApp()
lateinit var database : AppDatabase
private set

val adsCoreManager : AdsCoreManager by lazy {
AdsCoreManager(context = instance)
}
val isAppLoaded : Boolean
get() = BaseCoreManager.isAppLoaded
}

private suspend fun initializeApp() = supervisorScope {
val dataBase : Deferred<Unit> = async { initializeDatabase() }
val dataStore : Deferred<Unit> = async { initializeDataStore() }

dataBase.await()
dataStore.await()
override fun onCreate() {
super.onCreate()
instance = this

adsCoreManager.initializeAds()
val crashlyticsReporter = CrashlyticsErrorReporter()
ErrorHandler.init(reporter = crashlyticsReporter)

initializeAds()
finalizeInitialization()
registerActivityLifecycleCallbacks(this)
ProcessLifecycleOwner.get().lifecycle.addObserver(observer = this)
}

private suspend fun initializeDatabase() {
runCatching {
database = Room.databaseBuilder(
context = this@AppCoreManager,
klass = AppDatabase::class.java,
name = "Android Studio Tutorials"
)
.addMigrations(migrations = getMigrations())
.fallbackToDestructiveMigration()
.fallbackToDestructiveMigrationOnDowngrade()
.build()
override suspend fun onInitializeApp() = supervisorScope {
val dataStoreInitialization : Deferred<Unit> = async { initializeDataStore() }
val databaseInitialization : Deferred<Unit> = async { initializeDatabase() }
val adsInitialization : Deferred<Unit> = async { initializeAds() }

database.openHelper.writableDatabase
}.onFailure {
handleDatabaseError(exception = it as Exception)
}
dataStoreInitialization.await()
databaseInitialization.await()
adsInitialization.await()
}

private fun getMigrations() : Array<Migration> {
return arrayOf(
MIGRATION_2_3 ,
)
}

private suspend fun initializeDataStore() {
private fun initializeDataStore() {
runCatching {
dataStore = DataStore.getInstance(context = this@AppCoreManager)
dataStoreCoreManager.initializeDataStore()
}.onFailure {
handleInitializationFailure(
message = "DataStore initialization failed" ,
exception = it as Exception ,
applicationContext = applicationContext
message = "DataStore initialization failed" , exception = it as Exception , applicationContext = applicationContext
)
}
}

private fun initializeAds() {
private suspend fun initializeDatabase() {
runCatching {
adsCoreManager.initializeAds()
database = Room.databaseBuilder(
context = this@AppCoreManager , klass = AppDatabase::class.java , name = "Android Studio Tutorials"
).addMigrations(migrations = getMigrations()).fallbackToDestructiveMigration().fallbackToDestructiveMigrationOnDowngrade().build()

database.openHelper.writableDatabase
}.onFailure {
handleInitializationFailure(
message = "Ads initialization failed" ,
exception = it as Exception ,
applicationContext = applicationContext
)
handleDatabaseError(exception = it as Exception)
}
}

private fun finalizeInitialization() {
markAppAsLoaded()
}

@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onMoveToForeground() {
currentActivity?.let { adsCoreManager.showAdIfAvailable(activity = it) }
}

private suspend fun handleDatabaseError(exception : Exception) {
if (exception is SQLiteException || (exception is IllegalStateException && exception.message?.contains(other = "Migration failed") == true)) {
eraseDatabase()
Expand All @@ -142,41 +110,34 @@ class AppCoreManager : MultiDexApplication() , Application.ActivityLifecycleCall
Log.e("AppCoreManager" , "Database error: ${exception.message}" , exception)
}

private fun markAppAsLoaded() {
isAppLoaded = true
private fun initializeAds() {
adsCoreManager.initializeAds(AdsConstants.APP_OPEN_UNIT_ID)
}

private fun getMigrations() : Array<Migration> {
return arrayOf(
MIGRATION_2_3
)
}

fun isAppLoaded() : Boolean {
return isAppLoaded
}

@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onMoveToForeground() {
currentActivity?.let { adsCoreManager.showAdIfAvailable(it) }
}

override fun onActivityCreated(activity : Activity , savedInstanceState : Bundle?) {}

override fun onActivityStarted(activity : Activity) {
if (! adsCoreManager.isShowingAd) {
currentActivity = activity
}
currentActivity = activity
}

override fun onActivityResumed(activity : Activity) {}
override fun onActivityPaused(activity : Activity) {}
override fun onActivityStopped(activity : Activity) {}
override fun onActivitySaveInstanceState(activity : Activity , outState : Bundle) {}
override fun onActivityDestroyed(activity : Activity) {}

companion object {

lateinit var dataStore : DataStore
private set

lateinit var database : AppDatabase
private set

@SuppressLint("StaticFieldLeak")
lateinit var instance : AppCoreManager
private set

var isAppLoaded : Boolean = false
private set
}
}
Loading

0 comments on commit 2ccf959

Please sign in to comment.