diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 178e52f..701cffb 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -49,6 +49,23 @@ android { ) } } + + productFlavors { + + flavorDimensions.add("nfsmw") + + create("devmenu") { + dimension = "nfsmw" + minSdk = 21 + } + create("no_devmenu") { + dimension = "nfsmw" + minSdk = 21 + } + } + + + compileOptions { sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 @@ -79,7 +96,6 @@ dependencies { implementation(libs.ui.graphics) implementation(libs.ui.tooling.preview) implementation(libs.material3) - implementation(project(":devmenu:data")) testImplementation(libs.junit.v412) //testImplementation(libs.junit) androidTestImplementation(libs.androidx.test.ext.junit) diff --git a/app/src/devmenu/AndroidManifest.xml b/app/src/devmenu/AndroidManifest.xml new file mode 100644 index 0000000..7e0c762 --- /dev/null +++ b/app/src/devmenu/AndroidManifest.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5dbedb2..e3df730 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -34,13 +34,7 @@ - - - - - - + + + + + + + + + + + + \ No newline at end of file diff --git a/devmenu/build.gradle.kts b/devmenu/build.gradle.kts index 6be7607..409620d 100644 --- a/devmenu/build.gradle.kts +++ b/devmenu/build.gradle.kts @@ -1,7 +1,7 @@ -@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed plugins { alias(libs.plugins.androidLibrary) alias(libs.plugins.kotlinAndroid) + alias(libs.plugins.ksp) } android { @@ -59,6 +59,7 @@ dependencies { implementation(libs.ui.graphics) implementation(libs.ui.tooling.preview) implementation(libs.material3) + implementation(project(mapOf("path" to ":devmenu:domain"))) testImplementation(libs.junit) androidTestImplementation(libs.androidx.test.ext.junit) androidTestImplementation(libs.espresso.core) @@ -66,4 +67,9 @@ dependencies { androidTestImplementation(libs.ui.test.junit4) debugImplementation(libs.ui.tooling) debugImplementation(libs.ui.test.manifest) + + implementation(libs.dagger) + ksp(libs.dagger.compiler) + implementation(libs.room) + ksp(libs.room.compiler) } \ No newline at end of file diff --git a/devmenu/data/build.gradle.kts b/devmenu/data/build.gradle.kts index 6ab1e4a..edc6321 100644 --- a/devmenu/data/build.gradle.kts +++ b/devmenu/data/build.gradle.kts @@ -38,6 +38,7 @@ dependencies { implementation(libs.core.ktx) implementation(libs.appcompat) implementation(libs.material) + implementation(project(mapOf("path" to ":devmenu:domain"))) testImplementation(libs.junit) androidTestImplementation(libs.androidx.test.ext.junit) androidTestImplementation(libs.espresso.core) diff --git a/devmenu/data/src/main/java/com/megboyzz/devmenu/data/repositories/MyClass.kt b/devmenu/data/src/main/java/com/megboyzz/devmenu/data/repositories/MyClass.kt deleted file mode 100644 index d48b0d7..0000000 --- a/devmenu/data/src/main/java/com/megboyzz/devmenu/data/repositories/MyClass.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.megboyzz.devmenu.data.repositories - -class MyClass { - - fun main(){ - - val input = readln().split(",").associate { - val s = it.trim().split(" ") - s[0] to s[1].toInt() - } - - var sum = 0 - - readln().split(" ").forEach { - - val s = input[it] ?: 0 - sum += s - - } - - println(sum) - - - } - -} \ No newline at end of file diff --git a/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/entities/FileProps.kt b/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/entities/FileProps.kt index 2141304..1cccd68 100644 --- a/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/entities/FileProps.kt +++ b/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/entities/FileProps.kt @@ -4,6 +4,6 @@ import java.util.Date data class FileProps( val fileName: String, - val size: Int, - val dateOfCreation: Date + val size: Long, + val lastModify: Date ) diff --git a/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/entities/TrackingData.kt b/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/entities/TrackingData.kt new file mode 100644 index 0000000..656c0cb --- /dev/null +++ b/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/entities/TrackingData.kt @@ -0,0 +1,6 @@ +package com.megboyzz.devmenu.domain.entities + +data class TrackingData( + val enabled: Boolean, + val pathToSave: String +) diff --git a/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/repository/SettingsRepository.kt b/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/repository/SettingsRepository.kt index 27d886b..da5e07b 100644 --- a/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/repository/SettingsRepository.kt +++ b/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/repository/SettingsRepository.kt @@ -4,7 +4,6 @@ import com.megboyzz.devmenu.domain.entities.GameLang interface SettingsRepository { - fun setGameLang(lang: GameLang): Boolean - + var gameLang: GameLang } \ No newline at end of file diff --git a/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/repository/TrackingRepository.kt b/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/repository/TrackingRepository.kt index a58c6e1..01f8bb6 100644 --- a/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/repository/TrackingRepository.kt +++ b/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/repository/TrackingRepository.kt @@ -1,7 +1,13 @@ package com.megboyzz.devmenu.domain.repository +import com.megboyzz.devmenu.domain.entities.TrackingData + interface TrackingRepository { - fun setTracking(enabled: Boolean, pathToSave: String): Boolean + var trackingData: TrackingData + + fun startTracking() + + fun stopTracking() } \ No newline at end of file diff --git a/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/IsDevMenuEnabledUseCase.kt b/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/IsDevMenuEnabledUseCase.kt new file mode 100644 index 0000000..3e6a848 --- /dev/null +++ b/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/IsDevMenuEnabledUseCase.kt @@ -0,0 +1,12 @@ +package com.megboyzz.devmenu.domain.usecases + +import com.megboyzz.devmenu.domain.entities.devmenuId +import com.megboyzz.devmenu.domain.repository.FilesRepository +import java.io.File +import javax.inject.Inject + +class IsDevMenuEnabledUseCase @Inject constructor( + private val filesRepository: FilesRepository +) { + operator fun invoke() = File(filesRepository.externalRoot, devmenuId).exists() +} \ No newline at end of file diff --git a/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/StartTrackingUseCase.kt b/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/StartTrackingUseCase.kt new file mode 100644 index 0000000..85a7a7a --- /dev/null +++ b/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/StartTrackingUseCase.kt @@ -0,0 +1,17 @@ +package com.megboyzz.devmenu.domain.usecases + +import com.megboyzz.devmenu.domain.repository.TrackingRepository +import javax.inject.Inject + +class StartTrackingUseCase @Inject constructor( + private val trackingRepository: TrackingRepository +) { + + operator fun invoke(){ + + if(trackingRepository.trackingData.enabled) + trackingRepository.startTracking() + + } + +} \ No newline at end of file diff --git a/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/StopTrackingUseCase.kt b/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/StopTrackingUseCase.kt new file mode 100644 index 0000000..979c5af --- /dev/null +++ b/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/StopTrackingUseCase.kt @@ -0,0 +1,11 @@ +package com.megboyzz.devmenu.domain.usecases + +import com.megboyzz.devmenu.domain.repository.TrackingRepository +import javax.inject.Inject +class StopTrackingUseCase @Inject constructor( + private val trackingRepository: TrackingRepository +) { + + operator fun invoke() = trackingRepository.stopTracking() + +} \ No newline at end of file diff --git a/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/settings/SetGameLangUseCase.kt b/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/settings/SetGameLangUseCase.kt index edb131f..338f964 100644 --- a/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/settings/SetGameLangUseCase.kt +++ b/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/settings/SetGameLangUseCase.kt @@ -8,6 +8,8 @@ class SetGameLangUseCase @Inject constructor( private val settingsRepository: SettingsRepository ) { - operator fun invoke(gameLang: GameLang) = settingsRepository.setGameLang(gameLang) + operator fun invoke(gameLang: GameLang){ + settingsRepository.gameLang = gameLang + } } \ No newline at end of file diff --git a/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/settings/SetTrackingSaveFileUseCase.kt b/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/settings/SetTrackingSaveFileUseCase.kt index afb1eb7..4ce20ae 100644 --- a/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/settings/SetTrackingSaveFileUseCase.kt +++ b/devmenu/domain/src/main/java/com/megboyzz/devmenu/domain/usecases/settings/SetTrackingSaveFileUseCase.kt @@ -1,5 +1,6 @@ package com.megboyzz.devmenu.domain.usecases.settings +import com.megboyzz.devmenu.domain.entities.TrackingData import com.megboyzz.devmenu.domain.repository.TrackingRepository import javax.inject.Inject @@ -7,7 +8,8 @@ class SetTrackingSaveFileUseCase @Inject constructor( private val trackingRepository: TrackingRepository ) { - operator fun invoke(enabled: Boolean, pathToSave: String) = - trackingRepository.setTracking(enabled, pathToSave) + operator fun invoke(enabled: Boolean, pathToSave: String) { + trackingRepository.trackingData = TrackingData(enabled, pathToSave) + } } \ No newline at end of file diff --git a/devmenu/domain/src/test/java/UseCaseTest.kt b/devmenu/domain/src/test/java/UseCaseTest.kt deleted file mode 100644 index 38320bb..0000000 --- a/devmenu/domain/src/test/java/UseCaseTest.kt +++ /dev/null @@ -1,30 +0,0 @@ -import com.megboyzz.devmenu.domain.repository.FilesRepository -import com.megboyzz.devmenu.domain.repository.ReplacementRepository -import com.megboyzz.devmenu.domain.repository.SaveRepository -import com.megboyzz.devmenu.domain.repository.SvmwRepository -import org.mockito.Mockito.mock -import org.mockito.Mockito.`when` -import java.io.File - -class UseCaseTest { - - private val filesRepository = mock(FilesRepository::class.java) - private val replacementRepository = mock(ReplacementRepository::class.java) - private val saveRepository = mock(SaveRepository::class.java) - private val svmwRepository = mock(SvmwRepository::class.java) - - private val externalFile = File("D:\\NFSMW Online\\com.ea.games.nfs13_na") - private val internalFile = File("D:\\NFSMW Online") - - init { - - `when`(filesRepository.externalRoot).thenReturn(externalFile) - `when`(filesRepository.internalRoot).thenReturn(internalFile) - - - //`when`(replacementRepository.getAllReplacements()).thenReturn() - - - } - -} \ No newline at end of file diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/MainActivity.kt b/devmenu/src/main/java/com/megboyzz/devmenu/MainActivity.kt index 15110c8..9b8a398 100644 --- a/devmenu/src/main/java/com/megboyzz/devmenu/MainActivity.kt +++ b/devmenu/src/main/java/com/megboyzz/devmenu/MainActivity.kt @@ -3,10 +3,14 @@ package com.megboyzz.devmenu import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent +import com.megboyzz.devmenu.di.components.AppComponent +import dagger.internal.DaggerGenerated class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + + setContent {} } } diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/db/AppDatabase.kt b/devmenu/src/main/java/com/megboyzz/devmenu/db/AppDatabase.kt new file mode 100644 index 0000000..52c2b6d --- /dev/null +++ b/devmenu/src/main/java/com/megboyzz/devmenu/db/AppDatabase.kt @@ -0,0 +1,11 @@ +package com.megboyzz.devmenu.db + +import androidx.room.Database +import androidx.room.RoomDatabase +import com.megboyzz.devmenu.db.dao.ReplacementDao +import com.megboyzz.devmenu.db.entites.Replacement + +@Database(entities = [Replacement::class], version = 1, exportSchema = false) +abstract class AppDatabase: RoomDatabase() { + abstract val replacementDao: ReplacementDao +} \ No newline at end of file diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/db/dao/ReplacementDao.kt b/devmenu/src/main/java/com/megboyzz/devmenu/db/dao/ReplacementDao.kt new file mode 100644 index 0000000..5cfeaa1 --- /dev/null +++ b/devmenu/src/main/java/com/megboyzz/devmenu/db/dao/ReplacementDao.kt @@ -0,0 +1,24 @@ +package com.megboyzz.devmenu.db.dao + +import androidx.room.Dao +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.Query +import com.megboyzz.devmenu.db.entites.Replacement + +@Dao +interface ReplacementDao { + + @get:Query("SELECT * from replacement") + val all: List + + @Insert + fun addReplacement(replacement: Replacement) + + @Query("SELECT * FROM replacement WHERE original_file_name=:originalFileName") + fun getReplacementByOriginalName(originalFileName: String): Replacement + + @Delete + fun removeReplacement(replacement: Replacement) + +} \ No newline at end of file diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/db/entites/Replacement.kt b/devmenu/src/main/java/com/megboyzz/devmenu/db/entites/Replacement.kt new file mode 100644 index 0000000..fb7431c --- /dev/null +++ b/devmenu/src/main/java/com/megboyzz/devmenu/db/entites/Replacement.kt @@ -0,0 +1,18 @@ +package com.megboyzz.devmenu.db.entites + +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.PrimaryKey + +@Entity +data class Replacement( + + @PrimaryKey(autoGenerate = true) + val id: Int = 0, + + @ColumnInfo(name = "original_file_name") + val originalFileName: String, + + @ColumnInfo(name = "replacement_file_name") + val replacementFileName: String +) diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/di/components/AppComponent.kt b/devmenu/src/main/java/com/megboyzz/devmenu/di/components/AppComponent.kt new file mode 100644 index 0000000..60f50e1 --- /dev/null +++ b/devmenu/src/main/java/com/megboyzz/devmenu/di/components/AppComponent.kt @@ -0,0 +1,50 @@ +package com.megboyzz.devmenu.di.components + +import android.content.Context +import com.megboyzz.devmenu.db.entites.Replacement +import com.megboyzz.devmenu.di.components.subcomponents.FilesUseCaseComponent +import com.megboyzz.devmenu.di.components.subcomponents.HideFilesUseCaseComponent +import com.megboyzz.devmenu.di.components.subcomponents.ReplacementUseCaseComponent +import com.megboyzz.devmenu.di.components.subcomponents.SettingsUseCaseComponent +import com.megboyzz.devmenu.di.components.subcomponents.TrackingHandlerUseCaseComponent +import com.megboyzz.devmenu.di.modules.DatabaseModule +import com.megboyzz.devmenu.di.modules.RepositoryModule +import com.megboyzz.devmenu.di.modules.SubcomponentsModule +import com.megboyzz.devmenu.domain.usecases.files.GetFilePropsUseCase +import dagger.BindsInstance +import dagger.Component +import dagger.Subcomponent +import javax.inject.Singleton + + +@Component( + modules = [ + SubcomponentsModule::class, + DatabaseModule::class, + RepositoryModule::class + ] +) +@Singleton +interface AppComponent { + + val filesUseCaseComponent: FilesUseCaseComponent.Builder + + val hideFilesUseCaseComponent: HideFilesUseCaseComponent.Builder + + val replacementUseCaseComponent: ReplacementUseCaseComponent.Builder + + val settingsUseCaseComponent: SettingsUseCaseComponent.Builder + + val trackingHandlerUseCaseComponent: TrackingHandlerUseCaseComponent.Builder + + @Component.Builder + interface Builder{ + + @BindsInstance + fun context(context: Context): Builder + + fun build(): AppComponent + + } + +} \ No newline at end of file diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/di/components/subcomponents/FilesUseCaseComponent.kt b/devmenu/src/main/java/com/megboyzz/devmenu/di/components/subcomponents/FilesUseCaseComponent.kt new file mode 100644 index 0000000..e9b2435 --- /dev/null +++ b/devmenu/src/main/java/com/megboyzz/devmenu/di/components/subcomponents/FilesUseCaseComponent.kt @@ -0,0 +1,32 @@ +package com.megboyzz.devmenu.di.components.subcomponents + +import android.content.Context +import com.megboyzz.devmenu.di.components.AppComponent +import com.megboyzz.devmenu.domain.usecases.files.GetExternalFilesUseCase +import com.megboyzz.devmenu.domain.usecases.files.GetFilePropsUseCase +import com.megboyzz.devmenu.domain.usecases.files.GetInternalFilesUseCase +import com.megboyzz.devmenu.domain.usecases.files.RemoveFileUseCase +import com.megboyzz.devmenu.domain.usecases.files.RenameFileUseCase +import dagger.BindsInstance +import dagger.Component +import dagger.Subcomponent + +@Subcomponent +interface FilesUseCaseComponent { + + val getExternalFilesUseCase: GetExternalFilesUseCase + + val getInternalFilesUseCase: GetInternalFilesUseCase + + val getFilePropsUseCase: GetFilePropsUseCase + + val removeFileUseCase: RemoveFileUseCase + + val renameFileUseCase: RenameFileUseCase + + @Component.Builder + interface Builder{ + fun build(): AppComponent + } + +} \ No newline at end of file diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/di/components/subcomponents/HideFilesUseCaseComponent.kt b/devmenu/src/main/java/com/megboyzz/devmenu/di/components/subcomponents/HideFilesUseCaseComponent.kt new file mode 100644 index 0000000..e9f8cda --- /dev/null +++ b/devmenu/src/main/java/com/megboyzz/devmenu/di/components/subcomponents/HideFilesUseCaseComponent.kt @@ -0,0 +1,27 @@ +package com.megboyzz.devmenu.di.components.subcomponents + +import com.megboyzz.devmenu.di.components.AppComponent +import com.megboyzz.devmenu.domain.usecases.hidefiles.GetAllHidedFilesUseCase +import com.megboyzz.devmenu.domain.usecases.hidefiles.HideFileUseCase +import com.megboyzz.devmenu.domain.usecases.hidefiles.UnHideAllUseCase +import com.megboyzz.devmenu.domain.usecases.hidefiles.UnHideFileUseCase +import dagger.Component +import dagger.Subcomponent + +@Subcomponent +interface HideFilesUseCaseComponent { + + val getAllHidedFilesUseCase: GetAllHidedFilesUseCase + + val hideFileUseCase: HideFileUseCase + + val unHideFileUseCase: UnHideFileUseCase + + val unHideAllUseCase: UnHideAllUseCase + + @Component.Builder + interface Builder{ + fun build(): AppComponent + } + +} \ No newline at end of file diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/di/components/subcomponents/ReplacementUseCaseComponent.kt b/devmenu/src/main/java/com/megboyzz/devmenu/di/components/subcomponents/ReplacementUseCaseComponent.kt new file mode 100644 index 0000000..48aabff --- /dev/null +++ b/devmenu/src/main/java/com/megboyzz/devmenu/di/components/subcomponents/ReplacementUseCaseComponent.kt @@ -0,0 +1,27 @@ +package com.megboyzz.devmenu.di.components.subcomponents + +import com.megboyzz.devmenu.di.components.AppComponent +import com.megboyzz.devmenu.domain.usecases.replacement.GetAllReplacedFilesUseCase +import com.megboyzz.devmenu.domain.usecases.replacement.RecoverAllReplacementsUseCase +import com.megboyzz.devmenu.domain.usecases.replacement.RecoverReplacementUseCase +import com.megboyzz.devmenu.domain.usecases.replacement.ReplaceFileUseCase +import dagger.Component +import dagger.Subcomponent + +@Subcomponent +interface ReplacementUseCaseComponent { + + val getAllReplacedFilesUseCase: GetAllReplacedFilesUseCase + + val recoverAllReplacedFilesUseCase: RecoverAllReplacementsUseCase + + val recoverReplacementUseCase: RecoverReplacementUseCase + + val replaceFileUseCase: ReplaceFileUseCase + + @Component.Builder + interface Builder{ + fun build(): AppComponent + } + +} \ No newline at end of file diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/di/components/subcomponents/SettingsUseCaseComponent.kt b/devmenu/src/main/java/com/megboyzz/devmenu/di/components/subcomponents/SettingsUseCaseComponent.kt new file mode 100644 index 0000000..42f1094 --- /dev/null +++ b/devmenu/src/main/java/com/megboyzz/devmenu/di/components/subcomponents/SettingsUseCaseComponent.kt @@ -0,0 +1,27 @@ +package com.megboyzz.devmenu.di.components.subcomponents + +import com.megboyzz.devmenu.di.components.AppComponent +import com.megboyzz.devmenu.domain.usecases.settings.RemoveGameDataUseCase +import com.megboyzz.devmenu.domain.usecases.settings.SetGameLangUseCase +import com.megboyzz.devmenu.domain.usecases.settings.SetTrackingSaveFileUseCase +import com.megboyzz.devmenu.domain.usecases.settings.TurnOffDevMenuUseCase +import dagger.Component +import dagger.Subcomponent + +@Subcomponent +interface SettingsUseCaseComponent { + + val removeGameDataUseCase: RemoveGameDataUseCase + + val setGameLangUseCase: SetGameLangUseCase + + val setTrackingSaveFileUseCase: SetTrackingSaveFileUseCase + + val turnOffDevMenuUseCase: TurnOffDevMenuUseCase + + @Component.Builder + interface Builder{ + fun build(): AppComponent + } + +} \ No newline at end of file diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/di/components/subcomponents/TrackingHandlerUseCaseComponent.kt b/devmenu/src/main/java/com/megboyzz/devmenu/di/components/subcomponents/TrackingHandlerUseCaseComponent.kt new file mode 100644 index 0000000..986be68 --- /dev/null +++ b/devmenu/src/main/java/com/megboyzz/devmenu/di/components/subcomponents/TrackingHandlerUseCaseComponent.kt @@ -0,0 +1,24 @@ +package com.megboyzz.devmenu.di.components.subcomponents + +import com.megboyzz.devmenu.di.components.AppComponent +import com.megboyzz.devmenu.domain.usecases.IsDevMenuEnabledUseCase +import com.megboyzz.devmenu.domain.usecases.StartTrackingUseCase +import com.megboyzz.devmenu.domain.usecases.StopTrackingUseCase +import dagger.Component +import dagger.Subcomponent + +@Subcomponent +interface TrackingHandlerUseCaseComponent { + + val isDevMenuEnabledUseCase: IsDevMenuEnabledUseCase + + val startTrackingUseCase: StartTrackingUseCase + + val stopTrackingUseCase: StopTrackingUseCase + + @Component.Builder + interface Builder{ + fun build(): AppComponent + } + +} \ No newline at end of file diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/di/modules/DatabaseModule.kt b/devmenu/src/main/java/com/megboyzz/devmenu/di/modules/DatabaseModule.kt new file mode 100644 index 0000000..ffe966a --- /dev/null +++ b/devmenu/src/main/java/com/megboyzz/devmenu/di/modules/DatabaseModule.kt @@ -0,0 +1,25 @@ +package com.megboyzz.devmenu.di.modules + +import android.content.Context +import androidx.room.Room +import androidx.room.RoomDatabase +import com.megboyzz.devmenu.db.AppDatabase +import dagger.Module +import dagger.Provides + +@Module +class DatabaseModule { + + @Provides + fun providesDataBase(context: Context): AppDatabase = + Room.databaseBuilder( + context, + AppDatabase::class.java, + "replacement-db" + ).build() + + + @Provides + fun providesReplacementDao(appDatabase: AppDatabase) = appDatabase.replacementDao + +} \ No newline at end of file diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/di/modules/RepositoryModule.kt b/devmenu/src/main/java/com/megboyzz/devmenu/di/modules/RepositoryModule.kt new file mode 100644 index 0000000..9ae1dc1 --- /dev/null +++ b/devmenu/src/main/java/com/megboyzz/devmenu/di/modules/RepositoryModule.kt @@ -0,0 +1,51 @@ +package com.megboyzz.devmenu.di.modules + +import android.content.Context +import com.megboyzz.devmenu.db.dao.ReplacementDao +import com.megboyzz.devmenu.domain.repository.FilesRepository +import com.megboyzz.devmenu.domain.repository.ReplacementRepository +import com.megboyzz.devmenu.domain.repository.SaveRepository +import com.megboyzz.devmenu.domain.repository.SettingsRepository +import com.megboyzz.devmenu.domain.repository.TrackingRepository +import com.megboyzz.devmenu.repositories.FilesRepositoryImpl +import com.megboyzz.devmenu.repositories.ReplacementRepositoryImpl +import com.megboyzz.devmenu.repositories.SaveRepositoryImpl +import com.megboyzz.devmenu.repositories.SettingsRepositoryImpl +import com.megboyzz.devmenu.repositories.TrackingRepositoryImpl +import dagger.Module +import dagger.Provides + +@Module +class RepositoryModule { + + @Provides + fun providesFilesRepository(context: Context): FilesRepository = + FilesRepositoryImpl(context) + + @Provides + fun providesReplacementRepository( + replacementDao: ReplacementDao, + filesRepository: FilesRepository + ): ReplacementRepository = + ReplacementRepositoryImpl(replacementDao, filesRepository) + + @Provides + fun providesSaveRepositoryImpl( + filesRepository: FilesRepository + ): SaveRepository = + SaveRepositoryImpl(filesRepository) + + @Provides + fun providesSettingsRepository( + filesRepository: FilesRepository + ): SettingsRepository = + SettingsRepositoryImpl(filesRepository) + + @Provides + fun providesTrackingRepository( + context: Context, + filesRepository: FilesRepository + ): TrackingRepository = + TrackingRepositoryImpl(context, filesRepository) + +} \ No newline at end of file diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/di/modules/SubcomponentsModule.kt b/devmenu/src/main/java/com/megboyzz/devmenu/di/modules/SubcomponentsModule.kt new file mode 100644 index 0000000..15ae17f --- /dev/null +++ b/devmenu/src/main/java/com/megboyzz/devmenu/di/modules/SubcomponentsModule.kt @@ -0,0 +1,19 @@ +package com.megboyzz.devmenu.di.modules + +import com.megboyzz.devmenu.di.components.subcomponents.FilesUseCaseComponent +import com.megboyzz.devmenu.di.components.subcomponents.HideFilesUseCaseComponent +import com.megboyzz.devmenu.di.components.subcomponents.ReplacementUseCaseComponent +import com.megboyzz.devmenu.di.components.subcomponents.SettingsUseCaseComponent +import com.megboyzz.devmenu.di.components.subcomponents.TrackingHandlerUseCaseComponent +import dagger.Module + +@Module( + subcomponents = [ + FilesUseCaseComponent::class, + HideFilesUseCaseComponent::class, + ReplacementUseCaseComponent::class, + SettingsUseCaseComponent::class, + TrackingHandlerUseCaseComponent::class + ] +) +object SubcomponentsModule \ No newline at end of file diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/repositories/FilesRepositoryImpl.kt b/devmenu/src/main/java/com/megboyzz/devmenu/repositories/FilesRepositoryImpl.kt new file mode 100644 index 0000000..e54738b --- /dev/null +++ b/devmenu/src/main/java/com/megboyzz/devmenu/repositories/FilesRepositoryImpl.kt @@ -0,0 +1,32 @@ +package com.megboyzz.devmenu.repositories + +import android.content.Context +import com.megboyzz.devmenu.domain.entities.FileProps +import com.megboyzz.devmenu.domain.repository.FilesRepository +import java.io.File +import java.util.Date + +class FilesRepositoryImpl( + private val context: Context +): FilesRepository { + + override val internalRoot = File(context.applicationInfo.dataDir) + override val externalRoot = context.getExternalFilesDir(null)!! + + override fun getFileProps(file: File) = FileProps( + fileName = file.name, + size = file.length(), + lastModify = Date(file.lastModified()) + ) + + override suspend fun hideFile(file: File): Boolean { + TODO("Not yet implemented") + } + + override suspend fun unHideFile(file: File): Boolean { + TODO("Not yet implemented") + } + + override val allHidedFiles: List + get() = TODO("Not yet implemented") +} \ No newline at end of file diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/repositories/ReplacementRepositoryImpl.kt b/devmenu/src/main/java/com/megboyzz/devmenu/repositories/ReplacementRepositoryImpl.kt new file mode 100644 index 0000000..d47cceb --- /dev/null +++ b/devmenu/src/main/java/com/megboyzz/devmenu/repositories/ReplacementRepositoryImpl.kt @@ -0,0 +1,73 @@ +package com.megboyzz.devmenu.repositories + +import com.megboyzz.devmenu.db.dao.ReplacementDao +import com.megboyzz.devmenu.db.entites.Replacement +import com.megboyzz.devmenu.domain.repository.FilesRepository +import com.megboyzz.devmenu.domain.repository.ReplacementRepository +import java.io.File +import java.lang.Exception +import javax.inject.Inject +import kotlin.random.Random + +class ReplacementRepositoryImpl @Inject constructor( + private val replacementDao: ReplacementDao, + private val filesRepository: FilesRepository +): ReplacementRepository { + + private val folderToSaveReplacements = File("${filesRepository.internalRoot}/replacements") + + private fun generateRandomPostfix(): String { + val length = 10 + return (1..length) + .map { _ -> Random.nextInt(0, 36) } + .joinToString("") { charIndex -> charIndex.toString(radix = 36) } + } + override suspend fun replaceFile(what: File, to: File): Result { + + return kotlin.runCatching { + val replacementFile = + File(folderToSaveReplacements, "replacement-${generateRandomPostfix()}") + replacementFile.createNewFile() + + to.copyTo(replacementFile, overwrite = true) + what.copyTo(to, overwrite = true) + + val replacement = Replacement( + originalFileName = what.absolutePath, + replacementFileName = replacementFile.absolutePath + ) + replacementDao.addReplacement(replacement) + + return Result.success(true) + }.onFailure { + return Result.failure(it) + } + + } + + override suspend fun recoverReplacement(replacement: File): Result { + return kotlin.runCatching { + val rep = replacementDao.getReplacementByOriginalName(replacement.absolutePath) + + val repFile = File(rep.replacementFileName) + + repFile.copyTo(File(rep.originalFileName), overwrite = true) + + repFile.delete() + + replacementDao.removeReplacement(rep) + + return Result.success(true) + }.onFailure { + return Result.failure(it) + } + } + + override suspend fun getAllReplacements(): List { + return replacementDao.all.map { + File(it.originalFileName) + } + } + + +} \ No newline at end of file diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/repositories/SaveRepositoryImpl.kt b/devmenu/src/main/java/com/megboyzz/devmenu/repositories/SaveRepositoryImpl.kt new file mode 100644 index 0000000..2aac431 --- /dev/null +++ b/devmenu/src/main/java/com/megboyzz/devmenu/repositories/SaveRepositoryImpl.kt @@ -0,0 +1,27 @@ +package com.megboyzz.devmenu.repositories + +import com.megboyzz.devmenu.domain.repository.FilesRepository +import com.megboyzz.devmenu.domain.repository.SaveRepository +import java.io.File + +class SaveRepositoryImpl( + private val filesRepository: FilesRepository +): SaveRepository { + + private val saveFile = File(filesRepository.internalRoot, "/files/var/nfstr_save.sb") + + override suspend fun loadSaveFile(file: File): Boolean { + + file.copyTo(saveFile, overwrite = true) + + return true + } + + override suspend fun uploadCurrentSaveFile(fileToUpload: File): Boolean { + + saveFile.copyTo(fileToUpload, overwrite = true) + + return true + } + +} \ No newline at end of file diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/repositories/SettingsRepositoryImpl.kt b/devmenu/src/main/java/com/megboyzz/devmenu/repositories/SettingsRepositoryImpl.kt new file mode 100644 index 0000000..b9ef077 --- /dev/null +++ b/devmenu/src/main/java/com/megboyzz/devmenu/repositories/SettingsRepositoryImpl.kt @@ -0,0 +1,47 @@ +package com.megboyzz.devmenu.repositories + +import android.content.res.Resources +import com.megboyzz.devmenu.domain.entities.GameLang +import com.megboyzz.devmenu.domain.repository.FilesRepository +import com.megboyzz.devmenu.domain.repository.SettingsRepository +import java.io.File +import java.nio.charset.Charset +import javax.inject.Inject + +class SettingsRepositoryImpl @Inject constructor( + private val filesRepository: FilesRepository +): SettingsRepository { + + private val localeFile = File(filesRepository.internalRoot, "files/var/locale") + + private fun getSystemLangAsGameLang(): GameLang { + + val configuration = Resources.getSystem().configuration + return GameLang.values().find { it.name == configuration.locale.language } ?: GameLang.Russian + + } + + + override var gameLang: GameLang + get() { + + val systemLang = getSystemLangAsGameLang() + + if(!localeFile.exists()){ + localeFile.createNewFile() + localeFile.writeBytes(byteArrayOf(0x02, 0x0) + systemLang.name.toByteArray()) + return systemLang + } + + val curLocale = String(localeFile.readBytes().takeLast(2).toByteArray()) + return GameLang.values().find { it.name == curLocale } ?: systemLang + } + set(value) { + + if(!localeFile.exists()) localeFile.createNewFile() + + localeFile.writeBytes(byteArrayOf(0x02, 0x0) + value.name.toByteArray()) + + } + +} \ No newline at end of file diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/repositories/TrackingRepositoryImpl.kt b/devmenu/src/main/java/com/megboyzz/devmenu/repositories/TrackingRepositoryImpl.kt new file mode 100644 index 0000000..7359006 --- /dev/null +++ b/devmenu/src/main/java/com/megboyzz/devmenu/repositories/TrackingRepositoryImpl.kt @@ -0,0 +1,55 @@ +package com.megboyzz.devmenu.repositories + +import android.content.Context +import com.megboyzz.devmenu.domain.entities.TrackingData +import com.megboyzz.devmenu.domain.repository.FilesRepository +import com.megboyzz.devmenu.domain.repository.TrackingRepository +import com.megboyzz.devmenu.util.SaveFileObserver +import javax.inject.Inject + +class TrackingRepositoryImpl @Inject constructor( + private val context: Context, + private val filesRepository: FilesRepository +) : TrackingRepository { + + private val TAG = this::class.simpleName + + private val trackingStateKey = "tracking_enabled" + private val trackingSavePath = "tracking_save_path" + private val defaultPathToSave = "${filesRepository.externalRoot}/files/saveTracking" + + private val saveFile = "${filesRepository.internalRoot}/files/var/nfstr_save.sb" + + private val sharedPreferences = context.getSharedPreferences("tracking", Context.MODE_PRIVATE) + + private val editor = sharedPreferences.edit() + + private lateinit var saveFileObserver: SaveFileObserver + + override var trackingData: TrackingData + get() { + val enabled = sharedPreferences.getBoolean(trackingStateKey, false) + val path = sharedPreferences.getString(trackingStateKey, defaultPathToSave)?: defaultPathToSave + + return TrackingData( + enabled = enabled, + pathToSave = path + ) + } + set(value) { + with(editor) { + putBoolean(trackingStateKey, value.enabled) + putString(trackingSavePath, value.pathToSave) + apply() + } + } + + override fun startTracking() { + saveFileObserver = SaveFileObserver(saveFile, trackingData.pathToSave) + saveFileObserver.startWatching() + } + + override fun stopTracking() { + saveFileObserver.stopWatching() + } +} \ No newline at end of file diff --git a/devmenu/data/src/main/java/com/megboyzz/devmenu/data/util/BaseObserver.kt b/devmenu/src/main/java/com/megboyzz/devmenu/util/BaseObserver.kt similarity index 98% rename from devmenu/data/src/main/java/com/megboyzz/devmenu/data/util/BaseObserver.kt rename to devmenu/src/main/java/com/megboyzz/devmenu/util/BaseObserver.kt index 2f4d5c3..3707ee1 100644 --- a/devmenu/data/src/main/java/com/megboyzz/devmenu/data/util/BaseObserver.kt +++ b/devmenu/src/main/java/com/megboyzz/devmenu/util/BaseObserver.kt @@ -1,4 +1,4 @@ -package com.megboyzz.devmenu.data.util +package com.megboyzz.devmenu.util import android.os.FileObserver import android.util.Log diff --git a/devmenu/data/src/main/java/com/megboyzz/devmenu/data/util/FileEvent.kt b/devmenu/src/main/java/com/megboyzz/devmenu/util/FileEvent.kt similarity index 93% rename from devmenu/data/src/main/java/com/megboyzz/devmenu/data/util/FileEvent.kt rename to devmenu/src/main/java/com/megboyzz/devmenu/util/FileEvent.kt index 2e0ae60..1af0974 100644 --- a/devmenu/data/src/main/java/com/megboyzz/devmenu/data/util/FileEvent.kt +++ b/devmenu/src/main/java/com/megboyzz/devmenu/util/FileEvent.kt @@ -1,4 +1,4 @@ -package com.megboyzz.devmenu.data.util +package com.megboyzz.devmenu.util import android.os.FileObserver diff --git a/devmenu/data/src/main/java/com/megboyzz/devmenu/data/util/SaveFileObserver.kt b/devmenu/src/main/java/com/megboyzz/devmenu/util/SaveFileObserver.kt similarity index 91% rename from devmenu/data/src/main/java/com/megboyzz/devmenu/data/util/SaveFileObserver.kt rename to devmenu/src/main/java/com/megboyzz/devmenu/util/SaveFileObserver.kt index 55b9701..e6b072a 100644 --- a/devmenu/data/src/main/java/com/megboyzz/devmenu/data/util/SaveFileObserver.kt +++ b/devmenu/src/main/java/com/megboyzz/devmenu/util/SaveFileObserver.kt @@ -1,4 +1,4 @@ -package com.megboyzz.devmenu.data.util +package com.megboyzz.devmenu.util import android.util.Log import java.io.File @@ -13,10 +13,10 @@ class SaveFileObserver( private var countSnapshots: Int = 1 private val checkList = listOf( - FileEvent.CLOSE_WRITE, - FileEvent.MODIFY, + //FileEvent.CLOSE_WRITE, + //FileEvent.MODIFY, //FileEvent.DELETE, - FileEvent.CREATE, + //FileEvent.CREATE, //FileEvent.ACCESS, //FileEvent.OPEN, FileEvent.CLOSE_NOWRITE diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8112cc2..1c87d57 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,6 +12,9 @@ compose-bom = "2023.08.00" appcompat = "1.6.1" material = "1.10.0" org-jetbrains-kotlin-jvm = "1.9.0" +ksp = "1.9.21-1.0.15" +dagger = "2.46.1" +room = "2.6.1" [libraries] core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" } @@ -31,10 +34,15 @@ ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" } material3 = { group = "androidx.compose.material3", name = "material3" } appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } material = { group = "com.google.android.material", name = "material", version.ref = "material" } +dagger = { module = "com.google.dagger:dagger", version.ref = "dagger" } +dagger-compiler = { module = "com.google.dagger:dagger-compiler", version.ref = "dagger" } +room = { module = "androidx.room:room-runtime", version.ref = "room" } +room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" } +room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" } [plugins] androidApplication = { id = "com.android.application", version.ref = "agp" } kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } androidLibrary = { id = "com.android.library", version.ref = "agp" } org-jetbrains-kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "org-jetbrains-kotlin-jvm" } - +ksp = { id = "com.google.devtools.ksp", version.ref = "ksp"} diff --git a/settings.gradle.kts b/settings.gradle.kts index 2beff7b..7b82154 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -23,4 +23,3 @@ rootProject.name = "NFS Most Wanted" include(":app") include(":devmenu") include(":devmenu:domain") -include(":devmenu:data")