Update project structure and impl all domain layer

This commit is contained in:
2023-12-09 21:15:22 +03:00
parent 0e195b0aee
commit 5c8a58beac
41 changed files with 705 additions and 83 deletions
+17 -1
View File
@@ -49,6 +49,23 @@ android {
) )
} }
} }
productFlavors {
flavorDimensions.add("nfsmw")
create("devmenu") {
dimension = "nfsmw"
minSdk = 21
}
create("no_devmenu") {
dimension = "nfsmw"
minSdk = 21
}
}
compileOptions { compileOptions {
sourceCompatibility = JavaVersion.VERSION_11 sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11
@@ -79,7 +96,6 @@ dependencies {
implementation(libs.ui.graphics) implementation(libs.ui.graphics)
implementation(libs.ui.tooling.preview) implementation(libs.ui.tooling.preview)
implementation(libs.material3) implementation(libs.material3)
implementation(project(":devmenu:data"))
testImplementation(libs.junit.v412) testImplementation(libs.junit.v412)
//testImplementation(libs.junit) //testImplementation(libs.junit)
androidTestImplementation(libs.androidx.test.ext.junit) androidTestImplementation(libs.androidx.test.ext.junit)
+13
View File
@@ -0,0 +1,13 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity android:name="com.ea.ironmonkey.devmenu.MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
+1 -7
View File
@@ -34,13 +34,7 @@
<activity android:name="com.ea.ironmonkey.devmenu.PuppetActivity" > <activity android:name="com.ea.ironmonkey.devmenu.PuppetActivity" >
</activity> </activity>
<activity android:name="com.ea.ironmonkey.devmenu.MainActivity" <activity android:name="com.ea.ironmonkey.devmenu.MainActivity"/>
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity <activity
android:name="com.ea.ironmonkey.devmenu.SettingsActivity" android:name="com.ea.ironmonkey.devmenu.SettingsActivity"
@@ -25,7 +25,7 @@ import com.ea.easp.EASPHandler
import com.ea.games.nfs13_na.BuildConfig import com.ea.games.nfs13_na.BuildConfig
import com.ea.games.nfs13_na.R import com.ea.games.nfs13_na.R
import com.ea.nimble.ApplicationLifecycle import com.ea.nimble.ApplicationLifecycle
import com.megboyzz.devmenu.data.util.SaveFileObserver import com.megboyzz.devmenu.util.SaveFileObserver
import java.io.BufferedReader import java.io.BufferedReader
import java.io.File import java.io.File
import java.io.FileReader import java.io.FileReader
@@ -60,7 +60,7 @@ class GameActivity : ComponentActivity(), DrawFrameListener {
private val saveFile = "/data/data/${BuildConfig.APPLICATION_ID}/files/var/nfstr_save.sb" private val saveFile = "/data/data/${BuildConfig.APPLICATION_ID}/files/var/nfstr_save.sb"
private val dest = "/sdcard/Android/data/${BuildConfig.APPLICATION_ID}/files/saveTracking" private val dest = "/sdcard/Android/data/${BuildConfig.APPLICATION_ID}/files/saveTracking"
private val saveFileObserver = SaveFileObserver(saveFile, dest) private val saveFileObserver = com.megboyzz.devmenu.util.SaveFileObserver(saveFile, dest)
companion object { companion object {
@@ -0,0 +1,13 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity android:name="com.ea.ironmonkey.GameActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
+7 -1
View File
@@ -1,7 +1,7 @@
@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed
plugins { plugins {
alias(libs.plugins.androidLibrary) alias(libs.plugins.androidLibrary)
alias(libs.plugins.kotlinAndroid) alias(libs.plugins.kotlinAndroid)
alias(libs.plugins.ksp)
} }
android { android {
@@ -59,6 +59,7 @@ dependencies {
implementation(libs.ui.graphics) implementation(libs.ui.graphics)
implementation(libs.ui.tooling.preview) implementation(libs.ui.tooling.preview)
implementation(libs.material3) implementation(libs.material3)
implementation(project(mapOf("path" to ":devmenu:domain")))
testImplementation(libs.junit) testImplementation(libs.junit)
androidTestImplementation(libs.androidx.test.ext.junit) androidTestImplementation(libs.androidx.test.ext.junit)
androidTestImplementation(libs.espresso.core) androidTestImplementation(libs.espresso.core)
@@ -66,4 +67,9 @@ dependencies {
androidTestImplementation(libs.ui.test.junit4) androidTestImplementation(libs.ui.test.junit4)
debugImplementation(libs.ui.tooling) debugImplementation(libs.ui.tooling)
debugImplementation(libs.ui.test.manifest) debugImplementation(libs.ui.test.manifest)
implementation(libs.dagger)
ksp(libs.dagger.compiler)
implementation(libs.room)
ksp(libs.room.compiler)
} }
+1
View File
@@ -38,6 +38,7 @@ dependencies {
implementation(libs.core.ktx) implementation(libs.core.ktx)
implementation(libs.appcompat) implementation(libs.appcompat)
implementation(libs.material) implementation(libs.material)
implementation(project(mapOf("path" to ":devmenu:domain")))
testImplementation(libs.junit) testImplementation(libs.junit)
androidTestImplementation(libs.androidx.test.ext.junit) androidTestImplementation(libs.androidx.test.ext.junit)
androidTestImplementation(libs.espresso.core) androidTestImplementation(libs.espresso.core)
@@ -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)
}
}
@@ -4,6 +4,6 @@ import java.util.Date
data class FileProps( data class FileProps(
val fileName: String, val fileName: String,
val size: Int, val size: Long,
val dateOfCreation: Date val lastModify: Date
) )
@@ -0,0 +1,6 @@
package com.megboyzz.devmenu.domain.entities
data class TrackingData(
val enabled: Boolean,
val pathToSave: String
)
@@ -4,7 +4,6 @@ import com.megboyzz.devmenu.domain.entities.GameLang
interface SettingsRepository { interface SettingsRepository {
fun setGameLang(lang: GameLang): Boolean var gameLang: GameLang
} }
@@ -1,7 +1,13 @@
package com.megboyzz.devmenu.domain.repository package com.megboyzz.devmenu.domain.repository
import com.megboyzz.devmenu.domain.entities.TrackingData
interface TrackingRepository { interface TrackingRepository {
fun setTracking(enabled: Boolean, pathToSave: String): Boolean var trackingData: TrackingData
fun startTracking()
fun stopTracking()
} }
@@ -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()
}
@@ -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()
}
}
@@ -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()
}
@@ -8,6 +8,8 @@ class SetGameLangUseCase @Inject constructor(
private val settingsRepository: SettingsRepository private val settingsRepository: SettingsRepository
) { ) {
operator fun invoke(gameLang: GameLang) = settingsRepository.setGameLang(gameLang) operator fun invoke(gameLang: GameLang){
settingsRepository.gameLang = gameLang
}
} }
@@ -1,5 +1,6 @@
package com.megboyzz.devmenu.domain.usecases.settings package com.megboyzz.devmenu.domain.usecases.settings
import com.megboyzz.devmenu.domain.entities.TrackingData
import com.megboyzz.devmenu.domain.repository.TrackingRepository import com.megboyzz.devmenu.domain.repository.TrackingRepository
import javax.inject.Inject import javax.inject.Inject
@@ -7,7 +8,8 @@ class SetTrackingSaveFileUseCase @Inject constructor(
private val trackingRepository: TrackingRepository private val trackingRepository: TrackingRepository
) { ) {
operator fun invoke(enabled: Boolean, pathToSave: String) = operator fun invoke(enabled: Boolean, pathToSave: String) {
trackingRepository.setTracking(enabled, pathToSave) trackingRepository.trackingData = TrackingData(enabled, pathToSave)
}
} }
@@ -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()
}
}
@@ -3,10 +3,14 @@ package com.megboyzz.devmenu
import android.os.Bundle import android.os.Bundle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import com.megboyzz.devmenu.di.components.AppComponent
import dagger.internal.DaggerGenerated
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContent {} setContent {}
} }
} }
@@ -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
}
@@ -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<Replacement>
@Insert
fun addReplacement(replacement: Replacement)
@Query("SELECT * FROM replacement WHERE original_file_name=:originalFileName")
fun getReplacementByOriginalName(originalFileName: String): Replacement
@Delete
fun removeReplacement(replacement: Replacement)
}
@@ -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
)
@@ -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
}
}
@@ -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
}
}
@@ -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
}
}
@@ -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
}
}
@@ -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
}
}
@@ -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
}
}
@@ -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
}
@@ -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)
}
@@ -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
@@ -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<File>
get() = TODO("Not yet implemented")
}
@@ -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<Boolean> {
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<Boolean> {
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<File> {
return replacementDao.all.map {
File(it.originalFileName)
}
}
}
@@ -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
}
}
@@ -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())
}
}
@@ -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()
}
}
@@ -1,4 +1,4 @@
package com.megboyzz.devmenu.data.util package com.megboyzz.devmenu.util
import android.os.FileObserver import android.os.FileObserver
import android.util.Log import android.util.Log
@@ -1,4 +1,4 @@
package com.megboyzz.devmenu.data.util package com.megboyzz.devmenu.util
import android.os.FileObserver import android.os.FileObserver
@@ -1,4 +1,4 @@
package com.megboyzz.devmenu.data.util package com.megboyzz.devmenu.util
import android.util.Log import android.util.Log
import java.io.File import java.io.File
@@ -13,10 +13,10 @@ class SaveFileObserver(
private var countSnapshots: Int = 1 private var countSnapshots: Int = 1
private val checkList = listOf( private val checkList = listOf(
FileEvent.CLOSE_WRITE, //FileEvent.CLOSE_WRITE,
FileEvent.MODIFY, //FileEvent.MODIFY,
//FileEvent.DELETE, //FileEvent.DELETE,
FileEvent.CREATE, //FileEvent.CREATE,
//FileEvent.ACCESS, //FileEvent.ACCESS,
//FileEvent.OPEN, //FileEvent.OPEN,
FileEvent.CLOSE_NOWRITE FileEvent.CLOSE_NOWRITE
+9 -1
View File
@@ -12,6 +12,9 @@ compose-bom = "2023.08.00"
appcompat = "1.6.1" appcompat = "1.6.1"
material = "1.10.0" material = "1.10.0"
org-jetbrains-kotlin-jvm = "1.9.0" org-jetbrains-kotlin-jvm = "1.9.0"
ksp = "1.9.21-1.0.15"
dagger = "2.46.1"
room = "2.6.1"
[libraries] [libraries]
core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" } 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" } material3 = { group = "androidx.compose.material3", name = "material3" }
appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" } appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" } 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] [plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" } androidApplication = { id = "com.android.application", version.ref = "agp" }
kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
androidLibrary = { id = "com.android.library", version.ref = "agp" } androidLibrary = { id = "com.android.library", version.ref = "agp" }
org-jetbrains-kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "org-jetbrains-kotlin-jvm" } org-jetbrains-kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "org-jetbrains-kotlin-jvm" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp"}
-1
View File
@@ -23,4 +23,3 @@ rootProject.name = "NFS Most Wanted"
include(":app") include(":app")
include(":devmenu") include(":devmenu")
include(":devmenu:domain") include(":devmenu:domain")
include(":devmenu:data")