cut devmenu
This commit is contained in:
+1
-16
@@ -50,21 +50,6 @@ 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
|
||||||
@@ -104,7 +89,7 @@ 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(project(mapOf("path" to ":devmenu")))
|
//implementation(project(mapOf("path" to ":devmenu")))
|
||||||
|
|
||||||
implementation ("commons-codec:commons-codec:1.15")
|
implementation ("commons-codec:commons-codec:1.15")
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
<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>
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/build
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
plugins {
|
|
||||||
alias(libs.plugins.androidLibrary)
|
|
||||||
alias(libs.plugins.kotlinAndroid)
|
|
||||||
kotlin("kapt")
|
|
||||||
//alias(libs.plugins.ksp)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
android {
|
|
||||||
namespace = "com.megboyzz.devmenu"
|
|
||||||
compileSdk = 34
|
|
||||||
|
|
||||||
defaultConfig {
|
|
||||||
minSdk = 21
|
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
|
||||||
consumerProguardFiles("consumer-rules.pro")
|
|
||||||
vectorDrawables {
|
|
||||||
useSupportLibrary = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buildTypes {
|
|
||||||
release {
|
|
||||||
isMinifyEnabled = false
|
|
||||||
proguardFiles(
|
|
||||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
|
||||||
"proguard-rules.pro"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
compileOptions {
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
isCoreLibraryDesugaringEnabled = true
|
|
||||||
}
|
|
||||||
kotlinOptions {
|
|
||||||
jvmTarget = "1.8"
|
|
||||||
}
|
|
||||||
buildFeatures {
|
|
||||||
compose = true
|
|
||||||
}
|
|
||||||
composeOptions {
|
|
||||||
kotlinCompilerExtensionVersion = "1.5.7"
|
|
||||||
}
|
|
||||||
packaging {
|
|
||||||
resources {
|
|
||||||
excludes += "/META-INF/{AL2.0,LGPL2.1}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
|
|
||||||
implementation(libs.core.ktx)
|
|
||||||
implementation(libs.appcompat)
|
|
||||||
implementation(libs.material)
|
|
||||||
implementation(libs.lifecycle.runtime.ktx)
|
|
||||||
implementation(libs.activity.compose)
|
|
||||||
implementation(platform(libs.compose.bom))
|
|
||||||
implementation(libs.ui)
|
|
||||||
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)
|
|
||||||
androidTestImplementation(platform(libs.compose.bom))
|
|
||||||
androidTestImplementation(libs.ui.test.junit4)
|
|
||||||
debugImplementation(libs.ui.tooling)
|
|
||||||
debugImplementation(libs.ui.test.manifest)
|
|
||||||
|
|
||||||
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.0.4")
|
|
||||||
|
|
||||||
implementation(libs.compose.settings.ui.m3)
|
|
||||||
|
|
||||||
implementation(libs.voyager.navigator)
|
|
||||||
implementation(libs.voyager.bottomSheetNavigator)
|
|
||||||
implementation(libs.voyager.transitions)
|
|
||||||
implementation(libs.voyager.screenModel)
|
|
||||||
|
|
||||||
implementation(libs.dagger)
|
|
||||||
kapt(libs.dagger.compiler)
|
|
||||||
implementation(libs.room)
|
|
||||||
kapt(libs.room.compiler)
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/build
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed
|
|
||||||
plugins {
|
|
||||||
alias(libs.plugins.androidLibrary)
|
|
||||||
alias(libs.plugins.kotlinAndroid)
|
|
||||||
}
|
|
||||||
|
|
||||||
android {
|
|
||||||
namespace = "com.megboyzz.devmenu.data"
|
|
||||||
compileSdk = 34
|
|
||||||
|
|
||||||
defaultConfig {
|
|
||||||
minSdk = 21
|
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
|
||||||
consumerProguardFiles("consumer-rules.pro")
|
|
||||||
}
|
|
||||||
|
|
||||||
buildTypes {
|
|
||||||
release {
|
|
||||||
isMinifyEnabled = false
|
|
||||||
proguardFiles(
|
|
||||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
|
||||||
"proguard-rules.pro"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
compileOptions {
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
}
|
|
||||||
kotlinOptions {
|
|
||||||
jvmTarget = "1.8"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
Vendored
-21
@@ -1,21 +0,0 @@
|
|||||||
# Add project specific ProGuard rules here.
|
|
||||||
# You can control the set of applied configuration files using the
|
|
||||||
# proguardFiles setting in build.gradle.
|
|
||||||
#
|
|
||||||
# For more details, see
|
|
||||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
|
||||||
|
|
||||||
# If your project uses WebView with JS, uncomment the following
|
|
||||||
# and specify the fully qualified class name to the JavaScript interface
|
|
||||||
# class:
|
|
||||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
|
||||||
# public *;
|
|
||||||
#}
|
|
||||||
|
|
||||||
# Uncomment this to preserve the line number information for
|
|
||||||
# debugging stack traces.
|
|
||||||
#-keepattributes SourceFile,LineNumberTable
|
|
||||||
|
|
||||||
# If you keep the line number information, uncomment this to
|
|
||||||
# hide the original source file name.
|
|
||||||
#-renamesourcefileattribute SourceFile
|
|
||||||
-24
@@ -1,24 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.data
|
|
||||||
|
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
|
||||||
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
|
|
||||||
import org.junit.Assert.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instrumented test, which will execute on an Android device.
|
|
||||||
*
|
|
||||||
* See [testing documentation](http://d.android.com/tools/testing).
|
|
||||||
*/
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
|
||||||
class ExampleInstrumentedTest {
|
|
||||||
@Test
|
|
||||||
fun useAppContext() {
|
|
||||||
// Context of the app under test.
|
|
||||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
|
||||||
assertEquals("com.megboyzz.devmenu.data.test", appContext.packageName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
</manifest>
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.data
|
|
||||||
|
|
||||||
import org.junit.Test
|
|
||||||
|
|
||||||
import org.junit.Assert.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Example local unit test, which will execute on the development machine (host).
|
|
||||||
*
|
|
||||||
* See [testing documentation](http://d.android.com/tools/testing).
|
|
||||||
*/
|
|
||||||
class ExampleUnitTest {
|
|
||||||
@Test
|
|
||||||
fun addition_isCorrect() {
|
|
||||||
assertEquals(4, 2 + 2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/build
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id("java-library")
|
|
||||||
alias(libs.plugins.org.jetbrains.kotlin.jvm)
|
|
||||||
}
|
|
||||||
|
|
||||||
java {
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
|
||||||
targetCompatibility = JavaVersion.VERSION_17
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation("javax.inject:javax.inject:1")
|
|
||||||
testImplementation("junit:junit:4.13.2")
|
|
||||||
//testImplementation("org.mockito:mockito-core:5.7.0")
|
|
||||||
//testImplementation("org.mockito.kotlin:mockito-kotlin:5.7.0")
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
sourceSets {
|
|
||||||
test {
|
|
||||||
java.srcDir("src/test/java") // Путь к исходным файлам тестов на Kotlin
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.entities
|
|
||||||
|
|
||||||
val devmenuId = "DevMenu"
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.entities
|
|
||||||
|
|
||||||
import java.util.Date
|
|
||||||
|
|
||||||
data class FileProps(
|
|
||||||
val fileName: String,
|
|
||||||
val size: Long,
|
|
||||||
val lastModify: Date
|
|
||||||
)
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.entities
|
|
||||||
|
|
||||||
enum class GameLang(private val lang: String) {
|
|
||||||
System("sys"),
|
|
||||||
Chinese("cn"),
|
|
||||||
Dutch("nl"),
|
|
||||||
English("en"),
|
|
||||||
French("fr"),
|
|
||||||
Deutsch("de"),
|
|
||||||
Italian("it"),
|
|
||||||
Japanese("ja"),
|
|
||||||
Korean("kr"),
|
|
||||||
Portuguese("br"),
|
|
||||||
Russian("ru"),
|
|
||||||
Spanish("es");
|
|
||||||
|
|
||||||
override fun toString() = lang
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.entities
|
|
||||||
|
|
||||||
import java.util.Date
|
|
||||||
|
|
||||||
data class SvmwProps(
|
|
||||||
val description: String,
|
|
||||||
val date: Date
|
|
||||||
)
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.entities
|
|
||||||
|
|
||||||
data class TrackingData(
|
|
||||||
val enabled: Boolean,
|
|
||||||
val pathToSave: String
|
|
||||||
)
|
|
||||||
-20
@@ -1,20 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.repository
|
|
||||||
|
|
||||||
import com.megboyzz.devmenu.domain.entities.FileProps
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
interface FilesRepository {
|
|
||||||
|
|
||||||
val internalRoot: File
|
|
||||||
|
|
||||||
val externalRoot: File
|
|
||||||
|
|
||||||
fun getFileProps(file: File): FileProps
|
|
||||||
|
|
||||||
suspend fun hideFile(file: File): Boolean
|
|
||||||
|
|
||||||
suspend fun unHideFile(file: File): Boolean
|
|
||||||
|
|
||||||
val allHidedFiles: List<File>
|
|
||||||
|
|
||||||
}
|
|
||||||
-13
@@ -1,13 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.repository
|
|
||||||
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
interface ReplacementRepository {
|
|
||||||
|
|
||||||
suspend fun replaceFile(what: File, to: File): Result<Boolean>
|
|
||||||
|
|
||||||
suspend fun recoverReplacement(replacement: File): Result<Boolean>
|
|
||||||
|
|
||||||
suspend fun getAllReplacements(): List<File>
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.repository
|
|
||||||
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
interface SaveRepository {
|
|
||||||
|
|
||||||
suspend fun loadSaveFile(file: File): Boolean
|
|
||||||
|
|
||||||
suspend fun uploadCurrentSaveFile(fileToUpload: File): Boolean
|
|
||||||
|
|
||||||
}
|
|
||||||
-9
@@ -1,9 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.repository
|
|
||||||
|
|
||||||
import com.megboyzz.devmenu.domain.entities.GameLang
|
|
||||||
|
|
||||||
interface SettingsRepository {
|
|
||||||
|
|
||||||
var gameLang: GameLang
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.repository
|
|
||||||
|
|
||||||
import com.megboyzz.devmenu.domain.entities.SvmwProps
|
|
||||||
import java.io.File
|
|
||||||
|
|
||||||
interface SvmwRepository {
|
|
||||||
|
|
||||||
suspend fun createSvmwFromCurrentSaveFileAndSetIt(): Boolean
|
|
||||||
|
|
||||||
suspend fun createSvmwFromCurrentSaveFile(fileToSave: File): Boolean
|
|
||||||
|
|
||||||
suspend fun createSvmw(fileToSave: File, saveFile: File): Boolean
|
|
||||||
|
|
||||||
suspend fun loadSvmw(svmw: File): Boolean
|
|
||||||
|
|
||||||
suspend fun getInfoAboutSvmw(svmw: File): SvmwProps?
|
|
||||||
|
|
||||||
suspend fun getInfoAboutLoadedSvmw(): SvmwProps?
|
|
||||||
|
|
||||||
}
|
|
||||||
-13
@@ -1,13 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.repository
|
|
||||||
|
|
||||||
import com.megboyzz.devmenu.domain.entities.TrackingData
|
|
||||||
|
|
||||||
interface TrackingRepository {
|
|
||||||
|
|
||||||
var trackingData: TrackingData
|
|
||||||
|
|
||||||
fun startTracking()
|
|
||||||
|
|
||||||
fun stopTracking()
|
|
||||||
|
|
||||||
}
|
|
||||||
-12
@@ -1,12 +0,0 @@
|
|||||||
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()
|
|
||||||
}
|
|
||||||
-17
@@ -1,17 +0,0 @@
|
|||||||
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()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-11
@@ -1,11 +0,0 @@
|
|||||||
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()
|
|
||||||
|
|
||||||
}
|
|
||||||
-11
@@ -1,11 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.usecases.files
|
|
||||||
|
|
||||||
import com.megboyzz.devmenu.domain.repository.FilesRepository
|
|
||||||
import java.io.File
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class GetExternalFilesUseCase @Inject constructor(
|
|
||||||
private val filesRepository: FilesRepository
|
|
||||||
) {
|
|
||||||
operator fun invoke(childPath: String = ""): File = File(filesRepository.externalRoot, childPath)
|
|
||||||
}
|
|
||||||
-12
@@ -1,12 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.usecases.files
|
|
||||||
|
|
||||||
import com.megboyzz.devmenu.domain.entities.FileProps
|
|
||||||
import com.megboyzz.devmenu.domain.repository.FilesRepository
|
|
||||||
import java.io.File
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class GetFilePropsUseCase @Inject constructor(
|
|
||||||
private val filesRepository: FilesRepository
|
|
||||||
) {
|
|
||||||
operator fun invoke(file: File): FileProps = filesRepository.getFileProps(file)
|
|
||||||
}
|
|
||||||
-13
@@ -1,13 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.usecases.files
|
|
||||||
|
|
||||||
import com.megboyzz.devmenu.domain.repository.FilesRepository
|
|
||||||
import java.io.File
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class GetInternalFilesUseCase @Inject constructor(
|
|
||||||
private val filesRepository: FilesRepository
|
|
||||||
) {
|
|
||||||
|
|
||||||
operator fun invoke(childPath: String = ""): File = File(filesRepository.internalRoot, childPath)
|
|
||||||
|
|
||||||
}
|
|
||||||
-8
@@ -1,8 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.usecases.files
|
|
||||||
|
|
||||||
import java.io.File
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class RemoveFileUseCase @Inject constructor() {
|
|
||||||
operator fun invoke(file: File): Boolean = file.delete()
|
|
||||||
}
|
|
||||||
-12
@@ -1,12 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.usecases.files
|
|
||||||
|
|
||||||
import java.io.File
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class RenameFileUseCase @Inject constructor() {
|
|
||||||
operator fun invoke(file: File, newName: String) =
|
|
||||||
if(file.exists())
|
|
||||||
file.renameTo(File(file.parent, newName))
|
|
||||||
else
|
|
||||||
false
|
|
||||||
}
|
|
||||||
-12
@@ -1,12 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.usecases.hidefiles
|
|
||||||
|
|
||||||
import com.megboyzz.devmenu.domain.repository.FilesRepository
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class GetAllHidedFilesUseCase @Inject constructor(
|
|
||||||
private val filesRepository: FilesRepository
|
|
||||||
) {
|
|
||||||
|
|
||||||
operator fun invoke() = filesRepository.allHidedFiles
|
|
||||||
|
|
||||||
}
|
|
||||||
-13
@@ -1,13 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.usecases.hidefiles
|
|
||||||
|
|
||||||
import com.megboyzz.devmenu.domain.repository.FilesRepository
|
|
||||||
import java.io.File
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class HideFileUseCase @Inject constructor(
|
|
||||||
private val filesRepository: FilesRepository
|
|
||||||
) {
|
|
||||||
|
|
||||||
suspend operator fun invoke(file: File) = filesRepository.hideFile(file)
|
|
||||||
|
|
||||||
}
|
|
||||||
-14
@@ -1,14 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.usecases.hidefiles
|
|
||||||
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class UnHideAllUseCase @Inject constructor(
|
|
||||||
private val unHideFileUseCase: UnHideFileUseCase,
|
|
||||||
private val getAllHidedFilesUseCase: GetAllHidedFilesUseCase
|
|
||||||
) {
|
|
||||||
|
|
||||||
suspend operator fun invoke() = getAllHidedFilesUseCase().forEach {
|
|
||||||
unHideFileUseCase(it)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-13
@@ -1,13 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.usecases.hidefiles
|
|
||||||
|
|
||||||
import com.megboyzz.devmenu.domain.repository.FilesRepository
|
|
||||||
import java.io.File
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class UnHideFileUseCase @Inject constructor(
|
|
||||||
private val filesRepository: FilesRepository
|
|
||||||
) {
|
|
||||||
|
|
||||||
suspend operator fun invoke(file: File) = filesRepository.unHideFile(file)
|
|
||||||
|
|
||||||
}
|
|
||||||
-10
@@ -1,10 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.usecases.replacement
|
|
||||||
|
|
||||||
import com.megboyzz.devmenu.domain.repository.ReplacementRepository
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class GetAllReplacedFilesUseCase @Inject constructor(
|
|
||||||
private val replacementRepository: ReplacementRepository
|
|
||||||
) {
|
|
||||||
suspend operator fun invoke() = replacementRepository.getAllReplacements()
|
|
||||||
}
|
|
||||||
-13
@@ -1,13 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.usecases.replacement
|
|
||||||
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class RecoverAllReplacementsUseCase @Inject constructor(
|
|
||||||
private val getAllReplacedFilesUseCase: GetAllReplacedFilesUseCase,
|
|
||||||
private val recoverReplacementUseCase: RecoverReplacementUseCase
|
|
||||||
) {
|
|
||||||
suspend operator fun invoke(){
|
|
||||||
val listReplacedFiles = getAllReplacedFilesUseCase()
|
|
||||||
listReplacedFiles.forEach { recoverReplacementUseCase(it) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-11
@@ -1,11 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.usecases.replacement
|
|
||||||
|
|
||||||
import com.megboyzz.devmenu.domain.repository.ReplacementRepository
|
|
||||||
import java.io.File
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class RecoverReplacementUseCase @Inject constructor(
|
|
||||||
private val replacementRepository: ReplacementRepository
|
|
||||||
) {
|
|
||||||
suspend operator fun invoke(replacement: File) = replacementRepository.recoverReplacement(replacement)
|
|
||||||
}
|
|
||||||
-14
@@ -1,14 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.usecases.replacement
|
|
||||||
|
|
||||||
import com.megboyzz.devmenu.domain.repository.ReplacementRepository
|
|
||||||
import java.io.File
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class ReplaceFileUseCase @Inject constructor(
|
|
||||||
private val replacementRepository: ReplacementRepository
|
|
||||||
) {
|
|
||||||
|
|
||||||
suspend operator fun invoke(what: File, to: File): Result<Boolean>
|
|
||||||
= replacementRepository.replaceFile(what, to)
|
|
||||||
|
|
||||||
}
|
|
||||||
-11
@@ -1,11 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.usecases.save
|
|
||||||
|
|
||||||
import com.megboyzz.devmenu.domain.repository.SaveRepository
|
|
||||||
import java.io.File
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class LoadSaveFileUseCase @Inject constructor(
|
|
||||||
private val saveRepository: SaveRepository
|
|
||||||
) {
|
|
||||||
suspend operator fun invoke(file: File) = if(file.exists()) saveRepository.loadSaveFile(file) else false
|
|
||||||
}
|
|
||||||
-15
@@ -1,15 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.usecases.save
|
|
||||||
|
|
||||||
import com.megboyzz.devmenu.domain.repository.SaveRepository
|
|
||||||
import java.io.File
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class UploadSaveFileUseCase @Inject constructor(
|
|
||||||
private val saveRepository: SaveRepository
|
|
||||||
) {
|
|
||||||
suspend operator fun invoke(fileToUpload: File) =
|
|
||||||
if(fileToUpload.exists())
|
|
||||||
saveRepository.uploadCurrentSaveFile(fileToUpload)
|
|
||||||
else
|
|
||||||
false
|
|
||||||
}
|
|
||||||
-10
@@ -1,10 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.usecases.settings
|
|
||||||
|
|
||||||
import com.megboyzz.devmenu.domain.usecases.files.GetInternalFilesUseCase
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class RemoveGameDataUseCase @Inject constructor(
|
|
||||||
private val getInternalFilesUseCase: GetInternalFilesUseCase
|
|
||||||
) {
|
|
||||||
operator fun invoke() = getInternalFilesUseCase().listFiles()?.forEach { it.delete() }
|
|
||||||
}
|
|
||||||
-15
@@ -1,15 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.usecases.settings
|
|
||||||
|
|
||||||
import com.megboyzz.devmenu.domain.entities.GameLang
|
|
||||||
import com.megboyzz.devmenu.domain.repository.SettingsRepository
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class SetGameLangUseCase @Inject constructor(
|
|
||||||
private val settingsRepository: SettingsRepository
|
|
||||||
) {
|
|
||||||
|
|
||||||
operator fun invoke(gameLang: GameLang){
|
|
||||||
settingsRepository.gameLang = gameLang
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-15
@@ -1,15 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
class SetTrackingSaveFileUseCase @Inject constructor(
|
|
||||||
private val trackingRepository: TrackingRepository
|
|
||||||
) {
|
|
||||||
|
|
||||||
operator fun invoke(enabled: Boolean, pathToSave: String) {
|
|
||||||
trackingRepository.trackingData = TrackingData(enabled, pathToSave)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-12
@@ -1,12 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.usecases.settings
|
|
||||||
|
|
||||||
import com.megboyzz.devmenu.domain.entities.devmenuId
|
|
||||||
import com.megboyzz.devmenu.domain.repository.FilesRepository
|
|
||||||
import java.io.File
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class TurnOffDevMenuUseCase @Inject constructor(
|
|
||||||
private val filesRepository: FilesRepository
|
|
||||||
) {
|
|
||||||
operator fun invoke() = File(filesRepository.externalRoot, devmenuId).delete()
|
|
||||||
}
|
|
||||||
-27
@@ -1,27 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.usecases.svmw
|
|
||||||
|
|
||||||
import com.megboyzz.devmenu.domain.repository.SvmwRepository
|
|
||||||
import java.io.File
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class CreateSvmwFileUseCase @Inject constructor(
|
|
||||||
private val svmwRepository: SvmwRepository
|
|
||||||
) {
|
|
||||||
|
|
||||||
suspend operator fun invoke(
|
|
||||||
fileToSave: File? = null,
|
|
||||||
saveFile: File? = null
|
|
||||||
){
|
|
||||||
|
|
||||||
val a = fileToSave != null
|
|
||||||
val b = saveFile != null
|
|
||||||
|
|
||||||
when {
|
|
||||||
a && b -> svmwRepository.createSvmw(fileToSave!!, saveFile!!)
|
|
||||||
a && !b -> svmwRepository.createSvmwFromCurrentSaveFile(fileToSave!!)
|
|
||||||
!a && !b -> svmwRepository.createSvmwFromCurrentSaveFileAndSetIt()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-11
@@ -1,11 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.usecases.svmw
|
|
||||||
|
|
||||||
import com.megboyzz.devmenu.domain.repository.SvmwRepository
|
|
||||||
import java.io.File
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class GetSvmwFilePropsUseCase @Inject constructor(
|
|
||||||
private val svmwRepository: SvmwRepository
|
|
||||||
) {
|
|
||||||
suspend operator fun invoke(file: File) = svmwRepository.getInfoAboutSvmw(file)
|
|
||||||
}
|
|
||||||
-10
@@ -1,10 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.usecases.svmw
|
|
||||||
|
|
||||||
import com.megboyzz.devmenu.domain.repository.SvmwRepository
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class GetSvmwPropsUseCase @Inject constructor(
|
|
||||||
private val svmwRepository: SvmwRepository
|
|
||||||
) {
|
|
||||||
suspend operator fun invoke() = svmwRepository.getInfoAboutLoadedSvmw()
|
|
||||||
}
|
|
||||||
-11
@@ -1,11 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.domain.usecases.svmw
|
|
||||||
|
|
||||||
import com.megboyzz.devmenu.domain.repository.SvmwRepository
|
|
||||||
import java.io.File
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class LoadSvmwUseCase @Inject constructor(
|
|
||||||
private val svmwRepository: SvmwRepository
|
|
||||||
) {
|
|
||||||
suspend operator fun invoke(file: File) = if(file.exists()) svmwRepository.loadSvmw(file) else false
|
|
||||||
}
|
|
||||||
Vendored
-21
@@ -1,21 +0,0 @@
|
|||||||
# Add project specific ProGuard rules here.
|
|
||||||
# You can control the set of applied configuration files using the
|
|
||||||
# proguardFiles setting in build.gradle.
|
|
||||||
#
|
|
||||||
# For more details, see
|
|
||||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
|
||||||
|
|
||||||
# If your project uses WebView with JS, uncomment the following
|
|
||||||
# and specify the fully qualified class name to the JavaScript interface
|
|
||||||
# class:
|
|
||||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
|
||||||
# public *;
|
|
||||||
#}
|
|
||||||
|
|
||||||
# Uncomment this to preserve the line number information for
|
|
||||||
# debugging stack traces.
|
|
||||||
#-keepattributes SourceFile,LineNumberTable
|
|
||||||
|
|
||||||
# If you keep the line number information, uncomment this to
|
|
||||||
# hide the original source file name.
|
|
||||||
#-renamesourcefileattribute SourceFile
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package com.megboyzz.devmenu
|
|
||||||
|
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
|
||||||
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
|
|
||||||
import org.junit.Assert.*
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Instrumented test, which will execute on an Android device.
|
|
||||||
*
|
|
||||||
* See [testing documentation](http://d.android.com/tools/testing).
|
|
||||||
*/
|
|
||||||
@RunWith(AndroidJUnit4::class)
|
|
||||||
class ExampleInstrumentedTest {
|
|
||||||
@Test
|
|
||||||
fun useAppContext() {
|
|
||||||
// Context of the app under test.
|
|
||||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
|
||||||
assertEquals("com.megboyzz.devmenu.test", appContext.packageName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
|
|
||||||
<application android:name=".App">
|
|
||||||
<activity
|
|
||||||
android:name=".MainActivity"
|
|
||||||
android:exported="true"/>
|
|
||||||
</application>
|
|
||||||
|
|
||||||
</manifest>
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
package com.megboyzz.devmenu
|
|
||||||
|
|
||||||
import android.app.Application
|
|
||||||
import com.megboyzz.devmenu.di.components.DaggerFilesUseCaseComponent
|
|
||||||
import com.megboyzz.devmenu.di.components.DaggerHideFilesUseCaseComponent
|
|
||||||
import com.megboyzz.devmenu.di.components.DaggerReplacementUseCaseComponent
|
|
||||||
import com.megboyzz.devmenu.di.components.DaggerSettingsUseCaseComponent
|
|
||||||
import com.megboyzz.devmenu.di.components.DaggerTrackingHandlerUseCaseComponent
|
|
||||||
import com.megboyzz.devmenu.di.components.FilesUseCaseComponent
|
|
||||||
import com.megboyzz.devmenu.di.components.HideFilesUseCaseComponent
|
|
||||||
import com.megboyzz.devmenu.di.components.ReplacementUseCaseComponent
|
|
||||||
import com.megboyzz.devmenu.di.components.SettingsUseCaseComponent
|
|
||||||
import com.megboyzz.devmenu.di.components.TrackingHandlerUseCaseComponent
|
|
||||||
import kotlinx.coroutines.coroutineScope
|
|
||||||
import kotlin.concurrent.thread
|
|
||||||
|
|
||||||
class App: Application() {
|
|
||||||
|
|
||||||
lateinit var filesUseCaseComponent: FilesUseCaseComponent
|
|
||||||
lateinit var hideFilesUseCaseComponent: HideFilesUseCaseComponent
|
|
||||||
lateinit var replacementUseCaseComponent: ReplacementUseCaseComponent
|
|
||||||
lateinit var settingsUseCaseComponent: SettingsUseCaseComponent
|
|
||||||
lateinit var trackingHandlerUseCaseComponent: TrackingHandlerUseCaseComponent
|
|
||||||
override fun onCreate() {
|
|
||||||
super.onCreate()
|
|
||||||
|
|
||||||
filesUseCaseComponent = DaggerFilesUseCaseComponent.builder().context(this).build()
|
|
||||||
hideFilesUseCaseComponent = DaggerHideFilesUseCaseComponent.builder().context(this).build()
|
|
||||||
replacementUseCaseComponent = DaggerReplacementUseCaseComponent.builder().context(this).build()
|
|
||||||
settingsUseCaseComponent = DaggerSettingsUseCaseComponent.builder().context(this).build()
|
|
||||||
trackingHandlerUseCaseComponent = DaggerTrackingHandlerUseCaseComponent.builder().context(this).build()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
package com.megboyzz.devmenu
|
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.os.Bundle
|
|
||||||
import androidx.activity.ComponentActivity
|
|
||||||
import androidx.activity.compose.setContent
|
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import cafe.adriel.voyager.navigator.Navigator
|
|
||||||
import cafe.adriel.voyager.navigator.bottomSheet.BottomSheetNavigator
|
|
||||||
import com.megboyzz.devmenu.ui.components.MainScaffold
|
|
||||||
import com.megboyzz.devmenu.ui.screens.HomeScreen
|
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
|
||||||
|
|
||||||
private fun runGame(){
|
|
||||||
|
|
||||||
val gameActivityClass = classLoader.loadClass("com.ea.ironmonkey.GameActivity")
|
|
||||||
val intent = Intent(this, gameActivityClass)
|
|
||||||
|
|
||||||
startActivity(intent)
|
|
||||||
finish()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
|
|
||||||
val isDevMenuEnabled = (application as App)
|
|
||||||
.trackingHandlerUseCaseComponent
|
|
||||||
.isDevMenuEnabledUseCase()
|
|
||||||
|
|
||||||
if(!isDevMenuEnabled){
|
|
||||||
runGame()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
setContent {
|
|
||||||
BottomSheetNavigator(
|
|
||||||
sheetShape = RoundedCornerShape(topStart = 10.dp, topEnd = 10.dp)
|
|
||||||
) {
|
|
||||||
Navigator(HomeScreen(::runGame))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
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)
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
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
|
|
||||||
)
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.di.components
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import com.megboyzz.devmenu.di.modules.DatabaseModule
|
|
||||||
import com.megboyzz.devmenu.di.modules.RepositoryModule
|
|
||||||
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 javax.inject.Singleton
|
|
||||||
|
|
||||||
@Component(
|
|
||||||
modules = [
|
|
||||||
DatabaseModule::class,
|
|
||||||
RepositoryModule::class
|
|
||||||
]
|
|
||||||
)
|
|
||||||
@Singleton
|
|
||||||
interface FilesUseCaseComponent {
|
|
||||||
|
|
||||||
val getExternalFilesUseCase: GetExternalFilesUseCase
|
|
||||||
|
|
||||||
val getInternalFilesUseCase: GetInternalFilesUseCase
|
|
||||||
|
|
||||||
val getFilePropsUseCase: GetFilePropsUseCase
|
|
||||||
|
|
||||||
val removeFileUseCase: RemoveFileUseCase
|
|
||||||
|
|
||||||
val renameFileUseCase: RenameFileUseCase
|
|
||||||
|
|
||||||
@Component.Builder
|
|
||||||
interface Builder{
|
|
||||||
|
|
||||||
@BindsInstance
|
|
||||||
fun context(context: Context): Builder
|
|
||||||
fun build(): FilesUseCaseComponent
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.di.components
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import com.megboyzz.devmenu.di.modules.DatabaseModule
|
|
||||||
import com.megboyzz.devmenu.di.modules.RepositoryModule
|
|
||||||
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.BindsInstance
|
|
||||||
import dagger.Component
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
@Component(
|
|
||||||
modules = [
|
|
||||||
DatabaseModule::class,
|
|
||||||
RepositoryModule::class
|
|
||||||
]
|
|
||||||
)
|
|
||||||
@Singleton
|
|
||||||
interface HideFilesUseCaseComponent {
|
|
||||||
|
|
||||||
val getAllHidedFilesUseCase: GetAllHidedFilesUseCase
|
|
||||||
|
|
||||||
val hideFileUseCase: HideFileUseCase
|
|
||||||
|
|
||||||
val unHideFileUseCase: UnHideFileUseCase
|
|
||||||
|
|
||||||
val unHideAllUseCase: UnHideAllUseCase
|
|
||||||
|
|
||||||
@Component.Builder
|
|
||||||
interface Builder{
|
|
||||||
|
|
||||||
@BindsInstance
|
|
||||||
fun context(context: Context): Builder
|
|
||||||
|
|
||||||
fun build(): HideFilesUseCaseComponent
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-39
@@ -1,39 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.di.components
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import com.megboyzz.devmenu.di.modules.DatabaseModule
|
|
||||||
import com.megboyzz.devmenu.di.modules.RepositoryModule
|
|
||||||
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.BindsInstance
|
|
||||||
import dagger.Component
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
@Component(
|
|
||||||
modules = [
|
|
||||||
DatabaseModule::class,
|
|
||||||
RepositoryModule::class
|
|
||||||
]
|
|
||||||
)
|
|
||||||
@Singleton
|
|
||||||
interface ReplacementUseCaseComponent {
|
|
||||||
|
|
||||||
val getAllReplacedFilesUseCase: GetAllReplacedFilesUseCase
|
|
||||||
|
|
||||||
val recoverAllReplacedFilesUseCase: RecoverAllReplacementsUseCase
|
|
||||||
|
|
||||||
val recoverReplacementUseCase: RecoverReplacementUseCase
|
|
||||||
|
|
||||||
val replaceFileUseCase: ReplaceFileUseCase
|
|
||||||
|
|
||||||
@Component.Builder
|
|
||||||
interface Builder{
|
|
||||||
|
|
||||||
@BindsInstance
|
|
||||||
fun context(context: Context): Builder
|
|
||||||
fun build(): ReplacementUseCaseComponent
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.di.components
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import com.megboyzz.devmenu.di.modules.DatabaseModule
|
|
||||||
import com.megboyzz.devmenu.di.modules.RepositoryModule
|
|
||||||
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.BindsInstance
|
|
||||||
import dagger.Component
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
@Component(
|
|
||||||
modules = [
|
|
||||||
DatabaseModule::class,
|
|
||||||
RepositoryModule::class
|
|
||||||
]
|
|
||||||
)
|
|
||||||
@Singleton
|
|
||||||
interface SettingsUseCaseComponent {
|
|
||||||
|
|
||||||
val removeGameDataUseCase: RemoveGameDataUseCase
|
|
||||||
|
|
||||||
val setGameLangUseCase: SetGameLangUseCase
|
|
||||||
|
|
||||||
val setTrackingSaveFileUseCase: SetTrackingSaveFileUseCase
|
|
||||||
|
|
||||||
val turnOffDevMenuUseCase: TurnOffDevMenuUseCase
|
|
||||||
|
|
||||||
@Component.Builder
|
|
||||||
interface Builder{
|
|
||||||
|
|
||||||
@BindsInstance
|
|
||||||
fun context(context: Context): Builder
|
|
||||||
fun build(): SettingsUseCaseComponent
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
-36
@@ -1,36 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.di.components
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import com.megboyzz.devmenu.di.modules.DatabaseModule
|
|
||||||
import com.megboyzz.devmenu.di.modules.RepositoryModule
|
|
||||||
import com.megboyzz.devmenu.domain.usecases.IsDevMenuEnabledUseCase
|
|
||||||
import com.megboyzz.devmenu.domain.usecases.StartTrackingUseCase
|
|
||||||
import com.megboyzz.devmenu.domain.usecases.StopTrackingUseCase
|
|
||||||
import dagger.BindsInstance
|
|
||||||
import dagger.Component
|
|
||||||
import javax.inject.Singleton
|
|
||||||
|
|
||||||
@Component(
|
|
||||||
modules = [
|
|
||||||
DatabaseModule::class,
|
|
||||||
RepositoryModule::class
|
|
||||||
]
|
|
||||||
)
|
|
||||||
@Singleton
|
|
||||||
interface TrackingHandlerUseCaseComponent {
|
|
||||||
|
|
||||||
val isDevMenuEnabledUseCase: IsDevMenuEnabledUseCase
|
|
||||||
|
|
||||||
val startTrackingUseCase: StartTrackingUseCase
|
|
||||||
|
|
||||||
val stopTrackingUseCase: StopTrackingUseCase
|
|
||||||
|
|
||||||
@Component.Builder
|
|
||||||
interface Builder{
|
|
||||||
|
|
||||||
@BindsInstance
|
|
||||||
fun context(context: Context): Builder
|
|
||||||
fun build(): TrackingHandlerUseCaseComponent
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
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)
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
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")
|
|
||||||
}
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
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())
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
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,66 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.ui
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import androidx.compose.foundation.layout.Spacer
|
|
||||||
import androidx.compose.foundation.layout.height
|
|
||||||
import androidx.compose.foundation.layout.width
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.res.painterResource
|
|
||||||
import androidx.compose.ui.res.stringResource
|
|
||||||
import androidx.compose.ui.unit.Dp
|
|
||||||
import java.text.CharacterIterator
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.text.StringCharacterIterator
|
|
||||||
import java.util.Date
|
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun Int.asPainter() = painterResource(this)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun Int.asString() = stringResource(this)
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun SpacerWidth(width: Dp) = Spacer(Modifier.width(width))
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun SpacerHeight(height: Dp) = Spacer(Modifier.height(height))
|
|
||||||
|
|
||||||
fun humanReadableByteCountSI(bytes: Long): String {
|
|
||||||
var b = bytes
|
|
||||||
if (-1000 < b && b < 1000) {
|
|
||||||
return "$b B"
|
|
||||||
}
|
|
||||||
val ci: CharacterIterator = StringCharacterIterator("kMGTPE")
|
|
||||||
while (b <= -999950 || b >= 999950) {
|
|
||||||
b /= 1000
|
|
||||||
ci.next()
|
|
||||||
}
|
|
||||||
return String.format("%.1f %cB", b / 1000.0, ci.current())
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("SimpleDateFormat")
|
|
||||||
fun formatDate(date: Date) = SimpleDateFormat("dd.MM.yyyy HH:mm:ss").format(date)
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Возвращает лямбду того типа которая требуется в Composable контексте<br>
|
|
||||||
* например есть функция
|
|
||||||
*
|
|
||||||
* fun example(
|
|
||||||
* a: @Composable () -> SomeType
|
|
||||||
* )
|
|
||||||
*
|
|
||||||
* Чтобы предать туда параметр нужно обернуть это в скобки<br>
|
|
||||||
*
|
|
||||||
* example(a = { SomeType() })
|
|
||||||
*
|
|
||||||
* а можно не создавать еще один уровень вложения и использовать asComposableLambda
|
|
||||||
*
|
|
||||||
* example(a = SomeType().asComposableLambda)
|
|
||||||
*/
|
|
||||||
val <T> T.asComposableLambda: @Composable () -> T
|
|
||||||
get() = { this }
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.ui.components
|
|
||||||
|
|
||||||
import androidx.compose.animation.core.tween
|
|
||||||
import androidx.compose.animation.expandIn
|
|
||||||
|
|
||||||
import androidx.compose.animation.shrinkOut
|
|
||||||
import androidx.compose.animation.slideInVertically
|
|
||||||
import androidx.compose.animation.slideOutVertically
|
|
||||||
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
|
|
||||||
val enter = expandIn(
|
|
||||||
expandFrom = Alignment.CenterStart,
|
|
||||||
animationSpec = tween(250)
|
|
||||||
)
|
|
||||||
|
|
||||||
val exit = shrinkOut(
|
|
||||||
shrinkTowards = Alignment.CenterStart,
|
|
||||||
animationSpec = tween(250)
|
|
||||||
)
|
|
||||||
|
|
||||||
fun searchFieldEnter(duration: Int) = slideInVertically(animationSpec = tween(durationMillis = duration)) {
|
|
||||||
-it / 3
|
|
||||||
}
|
|
||||||
|
|
||||||
fun searchFieldExit(duration: Int) = slideOutVertically(animationSpec = tween(durationMillis = duration)) {
|
|
||||||
-it / 3
|
|
||||||
}
|
|
||||||
@@ -1,290 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.ui.components
|
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
|
||||||
import androidx.compose.foundation.Image
|
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.ColumnScope
|
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
import androidx.compose.foundation.layout.wrapContentHeight
|
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
||||||
import androidx.compose.material3.Button
|
|
||||||
import androidx.compose.material3.Divider
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.draw.clip
|
|
||||||
import androidx.compose.ui.draw.shadow
|
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.graphics.painter.Painter
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import com.megboyzz.devmenu.R
|
|
||||||
import com.megboyzz.devmenu.ui.SpacerHeight
|
|
||||||
import com.megboyzz.devmenu.ui.asPainter
|
|
||||||
import com.megboyzz.devmenu.ui.models.FsElementModel
|
|
||||||
import com.megboyzz.devmenu.ui.formatDate
|
|
||||||
import com.megboyzz.devmenu.ui.humanReadableByteCountSI
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun ClickableMenuPosition(
|
|
||||||
name: String,
|
|
||||||
icon: Painter,
|
|
||||||
onClick: () -> Unit = {},
|
|
||||||
withEnd: Boolean = true
|
|
||||||
) {
|
|
||||||
|
|
||||||
Row(
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
|
||||||
modifier = Modifier
|
|
||||||
.clickableWithRipple(onClick = onClick, enabled = withEnd)
|
|
||||||
.padding(4.dp)
|
|
||||||
.fillMaxWidth()
|
|
||||||
) {
|
|
||||||
CoreMenuPosition(name = name, icon = icon)
|
|
||||||
if (withEnd) Image(painter = R.drawable.enter.asPainter(), contentDescription = null)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun CoreMenuPosition(
|
|
||||||
name: String,
|
|
||||||
icon: Painter
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(20.dp),
|
|
||||||
) {
|
|
||||||
Image(
|
|
||||||
painter = icon,
|
|
||||||
contentDescription = null,
|
|
||||||
Modifier.size(24.dp)
|
|
||||||
)
|
|
||||||
Text(text = name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun FsElementInContextMenu(
|
|
||||||
name: String,
|
|
||||||
type: ElementType,
|
|
||||||
) {
|
|
||||||
|
|
||||||
Row(
|
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(20.dp)
|
|
||||||
) {
|
|
||||||
|
|
||||||
val modifier = Modifier
|
|
||||||
.size(36.dp)
|
|
||||||
.clip(RoundedCornerShape(10.dp))
|
|
||||||
.shadow(elevation = 6.dp)
|
|
||||||
|
|
||||||
FsElementIcon(type, modifier)
|
|
||||||
Text(
|
|
||||||
text = name
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
enum class ContextMenuState {
|
|
||||||
Main,
|
|
||||||
Delete,
|
|
||||||
Props
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun FileContextMenu(
|
|
||||||
fsElementEntity: FsElementModel,
|
|
||||||
onRemoveElement: () -> Unit,
|
|
||||||
onUpdateType: (ElementType) -> ElementType?
|
|
||||||
) {
|
|
||||||
|
|
||||||
var innerType by remember { mutableStateOf(fsElementEntity.type) }
|
|
||||||
var state by remember { mutableStateOf(ContextMenuState.Main) }
|
|
||||||
|
|
||||||
|
|
||||||
CoreFileContextMenu(fsElementEntity = fsElementEntity) {
|
|
||||||
AnimatedBoxForContextMenuContent(isVisible = state == ContextMenuState.Main){
|
|
||||||
AnimatedBoxForContextMenuContent(isVisible = innerType == ElementType.isFile) {
|
|
||||||
ClickableMenuPosition(
|
|
||||||
name = "Заменить",
|
|
||||||
icon = R.drawable.star.asPainter(),
|
|
||||||
onClick = {
|
|
||||||
innerType = onUpdateType(ElementType.isReplaced) ?: ElementType.isReplaced
|
|
||||||
}
|
|
||||||
)
|
|
||||||
ClickableMenuPosition(
|
|
||||||
name = "Скрыть для игры",
|
|
||||||
icon = R.drawable.hide.asPainter(),
|
|
||||||
onClick = {
|
|
||||||
innerType = onUpdateType(ElementType.isHidden) ?: ElementType.isHidden
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
AnimatedBoxForContextMenuContent(isVisible = innerType == ElementType.isHidden) {
|
|
||||||
ClickableMenuPosition(
|
|
||||||
name = "Показать игре",
|
|
||||||
icon = R.drawable.unhide.asPainter(),
|
|
||||||
onClick = {
|
|
||||||
innerType = onUpdateType(ElementType.isFile) ?: ElementType.isFile
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
AnimatedBoxForContextMenuContent(isVisible = innerType == ElementType.isReplaced) {
|
|
||||||
ClickableMenuPosition(
|
|
||||||
name = "Воостановить",
|
|
||||||
icon = R.drawable.star.asPainter(),
|
|
||||||
onClick = {
|
|
||||||
innerType = onUpdateType(ElementType.isFile) ?: ElementType.isFile
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
ClickableMenuPosition(
|
|
||||||
name = "Свойства",
|
|
||||||
icon = R.drawable.info.asPainter(),
|
|
||||||
onClick = { state = ContextMenuState.Props }
|
|
||||||
)
|
|
||||||
ClickableMenuPosition(
|
|
||||||
name = "Удалить",
|
|
||||||
icon = R.drawable.trash.asPainter(),
|
|
||||||
onClick = { state = ContextMenuState.Delete }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimatedBoxForContextMenuContent(isVisible = state == ContextMenuState.Delete) {
|
|
||||||
ClickableMenuPosition(
|
|
||||||
name = "Удалить",
|
|
||||||
icon = R.drawable.trash.asPainter(),
|
|
||||||
withEnd = false
|
|
||||||
)
|
|
||||||
RemoveFileButtonsGroup(
|
|
||||||
onDelete = onRemoveElement,
|
|
||||||
onCancel = { state = ContextMenuState.Main }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
AnimatedBoxForContextMenuContent(isVisible = state == ContextMenuState.Props) {
|
|
||||||
ClickableMenuPosition(
|
|
||||||
name = "Свойства",
|
|
||||||
icon = R.drawable.info.asPainter(),
|
|
||||||
withEnd = false,
|
|
||||||
)
|
|
||||||
PropsView(fsElementEntity = fsElementEntity)
|
|
||||||
RemoveButton(text = "Назад") {
|
|
||||||
state = ContextMenuState.Main
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun PropsView(
|
|
||||||
fsElementEntity: FsElementModel
|
|
||||||
) {
|
|
||||||
|
|
||||||
Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
|
|
||||||
Text(text = "Изменен: ${formatDate(fsElementEntity.date)}")
|
|
||||||
Text(text = "Размер: ${humanReadableByteCountSI(fsElementEntity.size)} (${fsElementEntity.size} B)")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun AnimatedBoxForContextMenuContent(
|
|
||||||
isVisible: Boolean,
|
|
||||||
content: @Composable ColumnScope.() -> Unit
|
|
||||||
) {
|
|
||||||
AnimatedVisibility(
|
|
||||||
visible = isVisible,
|
|
||||||
enter = enter,
|
|
||||||
exit = exit
|
|
||||||
) {
|
|
||||||
Column(
|
|
||||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
|
||||||
content = content
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun RemoveFileButtonsGroup(
|
|
||||||
onDelete: () -> Unit,
|
|
||||||
onCancel: () -> Unit
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(12.dp),
|
|
||||||
) {
|
|
||||||
RemoveButton(text = "Удалить", onClick = onDelete, modifier = Modifier.weight(1f))
|
|
||||||
RemoveButton(text = "Отмена", onClick = onCancel, modifier = Modifier.weight(1f))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun RemoveButton(
|
|
||||||
text: String,
|
|
||||||
modifier: Modifier = Modifier,
|
|
||||||
onClick: () -> Unit
|
|
||||||
) {
|
|
||||||
Button(
|
|
||||||
onClick = onClick,
|
|
||||||
shape = RoundedCornerShape(10.dp),
|
|
||||||
modifier = modifier
|
|
||||||
) {
|
|
||||||
Text(text = text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun CoreFileContextMenu(
|
|
||||||
fsElementEntity: FsElementModel,
|
|
||||||
content: @Composable () -> Unit
|
|
||||||
) {
|
|
||||||
|
|
||||||
val shape = RoundedCornerShape(topStart = 10.dp, topEnd = 10.dp)
|
|
||||||
|
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.wrapContentHeight()
|
|
||||||
.fillMaxWidth()
|
|
||||||
//TODO отвязать от цвета
|
|
||||||
.clip(shape)
|
|
||||||
.background(Color.White),
|
|
||||||
contentAlignment = Alignment.TopCenter
|
|
||||||
) {
|
|
||||||
Image(
|
|
||||||
painter = R.drawable.clip.asPainter(),
|
|
||||||
contentDescription = null,
|
|
||||||
modifier = Modifier.padding(top = 8.dp)
|
|
||||||
)
|
|
||||||
Box(
|
|
||||||
modifier = Modifier.padding(
|
|
||||||
horizontal = 28.dp,
|
|
||||||
vertical = 32.dp
|
|
||||||
),
|
|
||||||
){
|
|
||||||
Column {
|
|
||||||
Column(verticalArrangement = Arrangement.spacedBy(16.dp)) {
|
|
||||||
FsElementInContextMenu(name = fsElementEntity.name, type = fsElementEntity.type)
|
|
||||||
Divider()
|
|
||||||
SpacerHeight(height = 0.dp)
|
|
||||||
}
|
|
||||||
content()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.ui.components
|
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import com.megboyzz.devmenu.ui.models.FsElementModel
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun FsElement(
|
|
||||||
fsElementEntity: FsElementModel,
|
|
||||||
onClick: () -> Unit,
|
|
||||||
onLongPressClick: () -> Unit
|
|
||||||
) {
|
|
||||||
|
|
||||||
Column(
|
|
||||||
verticalArrangement = Arrangement.spacedBy(10.dp),
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
|
||||||
modifier = Modifier.clickableWithRipple(
|
|
||||||
onClick = onClick,
|
|
||||||
onLongClick = onLongPressClick
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
FsElementIcon(type = fsElementEntity.type)
|
|
||||||
Text(text = fsElementEntity.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.ui.components
|
|
||||||
|
|
||||||
import androidx.compose.foundation.Image
|
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.layout.size
|
|
||||||
import androidx.compose.foundation.lazy.LazyRow
|
|
||||||
import androidx.compose.foundation.lazy.items
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import com.megboyzz.devmenu.R
|
|
||||||
import com.megboyzz.devmenu.ui.asPainter
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun CoreBar(folders: List<String>) {
|
|
||||||
|
|
||||||
LazyRow(verticalAlignment = Alignment.CenterVertically) {
|
|
||||||
items(folders){
|
|
||||||
Text(
|
|
||||||
text = it,
|
|
||||||
style = MaterialTheme.typography.labelSmall
|
|
||||||
)
|
|
||||||
Image(
|
|
||||||
painter = R.drawable.enter.asPainter(),
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(4.dp)
|
|
||||||
.size(8.dp),
|
|
||||||
contentDescription = null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun StatusBarInCurFolder(
|
|
||||||
path: String
|
|
||||||
) {
|
|
||||||
if(path.isEmpty()) return
|
|
||||||
val pathAsArray = path.split("/").filter { it.isNotEmpty() }
|
|
||||||
CoreBar(folders = pathAsArray)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Preview
|
|
||||||
@Composable
|
|
||||||
fun CoreBarPrev() {
|
|
||||||
val path = "/data/data/com.ea.games.nfs13_na/files/var/".split("/").filter { it.isNotEmpty() }
|
|
||||||
CoreBar(folders = path)
|
|
||||||
}
|
|
||||||
@@ -1,172 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.ui.components
|
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.border
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
|
||||||
import androidx.compose.foundation.layout.padding
|
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
||||||
import androidx.compose.foundation.text.BasicTextField
|
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.filled.PlayArrow
|
|
||||||
import androidx.compose.material.icons.outlined.Search
|
|
||||||
import androidx.compose.material.icons.outlined.Settings
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
||||||
import androidx.compose.material3.FloatingActionButton
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import com.megboyzz.devmenu.ui.theme.DevMenuTheme
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
|
||||||
fun MainScaffold(
|
|
||||||
onSettingsClick: () -> Unit,
|
|
||||||
searchValue: String,
|
|
||||||
onSearchValueChanged: (String) -> Unit,
|
|
||||||
onFloatingButtonClick: () -> Unit,
|
|
||||||
content: @Composable (PaddingValues) -> Unit
|
|
||||||
) {
|
|
||||||
|
|
||||||
var searchValue by remember { mutableStateOf(searchValue) }
|
|
||||||
|
|
||||||
Scaffold(
|
|
||||||
|
|
||||||
topBar = {
|
|
||||||
TopBar(
|
|
||||||
searchValue = searchValue,
|
|
||||||
onSearchValueChanged = {
|
|
||||||
searchValue = it
|
|
||||||
onSearchValueChanged(it)
|
|
||||||
},
|
|
||||||
onSettingsClick = onSettingsClick
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|
|
||||||
floatingActionButton = {
|
|
||||||
FloatingActionButton(
|
|
||||||
onClick = onFloatingButtonClick,
|
|
||||||
shape = CircleShape,
|
|
||||||
content = {Icon(imageVector = Icons.Default.PlayArrow, contentDescription = null)}
|
|
||||||
)
|
|
||||||
},
|
|
||||||
|
|
||||||
content = content
|
|
||||||
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
|
||||||
fun TopBar(
|
|
||||||
searchValue: String,
|
|
||||||
onSearchValueChanged: (String) -> Unit,
|
|
||||||
onSettingsClick: () -> Unit
|
|
||||||
) {
|
|
||||||
|
|
||||||
var isSearching by remember { mutableStateOf(false) }
|
|
||||||
val context = LocalContext.current
|
|
||||||
TopAppBar(
|
|
||||||
title = {
|
|
||||||
if(isSearching){
|
|
||||||
SearchFileTextField(
|
|
||||||
value = searchValue,
|
|
||||||
onValueChange = onSearchValueChanged
|
|
||||||
)
|
|
||||||
}else Text("NFSMW DevMenu")
|
|
||||||
},
|
|
||||||
actions = {
|
|
||||||
SearchButton {
|
|
||||||
isSearching = !isSearching
|
|
||||||
}
|
|
||||||
SettingsButton(onClick = onSettingsClick)
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun SettingsButton(
|
|
||||||
onClick: () -> Unit
|
|
||||||
) {
|
|
||||||
IconButton(onClick) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Outlined.Settings,
|
|
||||||
contentDescription = null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun SearchButton(
|
|
||||||
onClick: () -> Unit
|
|
||||||
) {
|
|
||||||
IconButton(onClick) {
|
|
||||||
Icon(
|
|
||||||
imageVector = Icons.Outlined.Search,
|
|
||||||
contentDescription = null
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Preview
|
|
||||||
@Composable
|
|
||||||
fun ScaffoldPreview() {
|
|
||||||
DevMenuTheme {
|
|
||||||
MainScaffold(
|
|
||||||
onSettingsClick = { /*TODO*/ },
|
|
||||||
onSearchValueChanged = {},
|
|
||||||
searchValue = "",
|
|
||||||
onFloatingButtonClick = { /*TODO*/ }
|
|
||||||
) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun SearchFileTextField(
|
|
||||||
value: String,
|
|
||||||
onValueChange: (String) -> Unit
|
|
||||||
) {
|
|
||||||
BasicTextField(
|
|
||||||
value = value,
|
|
||||||
onValueChange = onValueChange,
|
|
||||||
decorationBox = { innerTextField ->
|
|
||||||
Box(Modifier.padding(end = 12.dp)) {
|
|
||||||
Row(
|
|
||||||
Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.background(Color.White, RoundedCornerShape(percent = 30))
|
|
||||||
.border(1.dp, Color.Black, RoundedCornerShape(percent = 30))
|
|
||||||
.padding(start = 12.dp),
|
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
|
||||||
verticalAlignment = Alignment.CenterVertically
|
|
||||||
) {
|
|
||||||
Box(Modifier.padding(vertical = 4.dp)) {
|
|
||||||
innerTextField()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,211 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.ui.components
|
|
||||||
|
|
||||||
import android.media.audiofx.Equalizer.Settings
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.foundation.layout.ColumnScope
|
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.filled.ArrowBack
|
|
||||||
import androidx.compose.material.icons.filled.Settings
|
|
||||||
import androidx.compose.material.icons.sharp.Home
|
|
||||||
import androidx.compose.material.icons.sharp.List
|
|
||||||
import androidx.compose.material.icons.sharp.Notifications
|
|
||||||
import androidx.compose.material3.AlertDialog
|
|
||||||
import androidx.compose.material3.Divider
|
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.IconButton
|
|
||||||
import androidx.compose.material3.Scaffold
|
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.material3.TextButton
|
|
||||||
import androidx.compose.material3.TopAppBar
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import com.alorma.compose.settings.storage.base.getValue
|
|
||||||
import com.alorma.compose.settings.storage.base.rememberBooleanSettingState
|
|
||||||
import com.alorma.compose.settings.storage.base.rememberIntSettingState
|
|
||||||
import com.alorma.compose.settings.ui.SettingsCheckbox
|
|
||||||
import com.alorma.compose.settings.ui.SettingsList
|
|
||||||
import com.alorma.compose.settings.ui.SettingsMenuLink
|
|
||||||
import com.alorma.compose.settings.ui.SettingsSwitch
|
|
||||||
import com.megboyzz.devmenu.R
|
|
||||||
import com.megboyzz.devmenu.ui.SpacerHeight
|
|
||||||
import com.megboyzz.devmenu.ui.asPainter
|
|
||||||
import com.megboyzz.devmenu.ui.models.GameLangModel
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun SettingsScaffold(
|
|
||||||
onBackClick: () -> Unit,
|
|
||||||
content: @Composable ColumnScope.() -> Unit
|
|
||||||
) {
|
|
||||||
Scaffold(
|
|
||||||
topBar = { SettingsTopBar(onBackClick = onBackClick) },
|
|
||||||
){
|
|
||||||
Column {
|
|
||||||
SpacerHeight(height = it.calculateTopPadding())
|
|
||||||
content(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
|
||||||
@Composable
|
|
||||||
fun SettingsTopBar(
|
|
||||||
onBackClick: () -> Unit
|
|
||||||
) {
|
|
||||||
TopAppBar(
|
|
||||||
navigationIcon = {
|
|
||||||
IconButton(onClick = onBackClick) {
|
|
||||||
Icon(imageVector = Icons.Filled.ArrowBack, contentDescription = null)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
title = { Text("Настройки") }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun LangDialog(
|
|
||||||
langModel: GameLangModel,
|
|
||||||
onUpdateLanguage: (GameLangModel) -> Unit
|
|
||||||
) {
|
|
||||||
|
|
||||||
val items = GameLangModel.values().map { it.name }
|
|
||||||
|
|
||||||
val curItem = items.indexOf(langModel.name)
|
|
||||||
|
|
||||||
val lang = rememberIntSettingState(curItem)
|
|
||||||
|
|
||||||
SettingsList(
|
|
||||||
icon = { Icon(painter = R.drawable.lang.asPainter(), contentDescription = null) },
|
|
||||||
title = { Text(text = "Сменить язык") },
|
|
||||||
items = items,
|
|
||||||
state = lang,
|
|
||||||
onItemSelected = { index, _ ->
|
|
||||||
onUpdateLanguage(GameLangModel.values()[index])
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun DevMenuOffDialog(
|
|
||||||
onDevMenuOff: () -> Unit,
|
|
||||||
onDismiss: () -> Unit,
|
|
||||||
) {
|
|
||||||
AlertDialog(
|
|
||||||
title = {
|
|
||||||
Text(text = "Выключить DevMenu")
|
|
||||||
},
|
|
||||||
text = {
|
|
||||||
Text(text = "Уверен что хочешь выключить DevMenu? Чтобы его включить нужно будет создать пустой файл c именем DevMenu в корне кэша игры")
|
|
||||||
},
|
|
||||||
onDismissRequest = onDismiss,
|
|
||||||
confirmButton = {
|
|
||||||
TextButton(
|
|
||||||
onClick = onDevMenuOff
|
|
||||||
) {
|
|
||||||
Text("OK")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dismissButton = {
|
|
||||||
TextButton(
|
|
||||||
onClick = onDismiss
|
|
||||||
) {
|
|
||||||
Text("Отмена")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun SettingsScreenContent(
|
|
||||||
onBackClick: () -> Unit,
|
|
||||||
langModel: GameLangModel,
|
|
||||||
onUpdateLanguage: (GameLangModel) -> Unit,
|
|
||||||
isTrackingSaveFile: Boolean,
|
|
||||||
onUpdateTrackingSaveFileState: (Boolean) -> Unit,
|
|
||||||
onChooseTrackingPathToSave: () -> Unit,
|
|
||||||
onUploadSaveFile: () -> Unit,
|
|
||||||
onDownloadSaveFile: () -> Unit,
|
|
||||||
onDevMenuOff: () -> Unit
|
|
||||||
) {
|
|
||||||
|
|
||||||
var isDevMenuOffDialog by remember { mutableStateOf(false) }
|
|
||||||
|
|
||||||
if(isDevMenuOffDialog){
|
|
||||||
DevMenuOffDialog(
|
|
||||||
onDevMenuOff = {
|
|
||||||
onDevMenuOff()
|
|
||||||
isDevMenuOffDialog =! isDevMenuOffDialog
|
|
||||||
},
|
|
||||||
onDismiss = { isDevMenuOffDialog =! isDevMenuOffDialog }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsScaffold(onBackClick = onBackClick) {
|
|
||||||
LangDialog(langModel = langModel, onUpdateLanguage = onUpdateLanguage)
|
|
||||||
Divider()
|
|
||||||
SettingsSwitch(
|
|
||||||
icon = {
|
|
||||||
Icon(painter = R.drawable.tracking.asPainter(), contentDescription = null)
|
|
||||||
},
|
|
||||||
title = {
|
|
||||||
Text(text = "Отслеживание файла сохранения")
|
|
||||||
},
|
|
||||||
state = rememberBooleanSettingState(isTrackingSaveFile),
|
|
||||||
onCheckedChange = onUpdateTrackingSaveFileState
|
|
||||||
)
|
|
||||||
SettingsMenuLink(
|
|
||||||
icon = { Icon(painter = R.drawable.folder.asPainter(), contentDescription = null) },
|
|
||||||
title = { Text(text = "Выбрать путь сохранения отслеживаемого сохранения") },
|
|
||||||
onClick = onChooseTrackingPathToSave,
|
|
||||||
)
|
|
||||||
Divider()
|
|
||||||
SettingsMenuLink(
|
|
||||||
icon = { Icon(painter = R.drawable.download.asPainter(), contentDescription = null) },
|
|
||||||
title = { Text(text = "Выгрузить файл сохранения") },
|
|
||||||
subtitle = { Text(text = "Получить текущий nfstr_save.sb") },
|
|
||||||
onClick = onDownloadSaveFile,
|
|
||||||
)
|
|
||||||
SettingsMenuLink(
|
|
||||||
icon = { Icon(painter = R.drawable.upload.asPainter(), contentDescription = null) },
|
|
||||||
title = { Text(text = "Загрузить файл сохранения") },
|
|
||||||
subtitle = { Text(text = "Загрузить в игру nfstr_save.sb") },
|
|
||||||
onClick = onUploadSaveFile,
|
|
||||||
)
|
|
||||||
Divider()
|
|
||||||
SettingsMenuLink(
|
|
||||||
title = {
|
|
||||||
Text(
|
|
||||||
text = "Выключить DevMenu",
|
|
||||||
color = Color.Red
|
|
||||||
)
|
|
||||||
},
|
|
||||||
onClick = { isDevMenuOffDialog =! isDevMenuOffDialog },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Preview
|
|
||||||
@Composable
|
|
||||||
fun SettingsTopBarPreview() {
|
|
||||||
SettingsScreenContent(
|
|
||||||
onBackClick = { /*TODO*/ },
|
|
||||||
langModel = GameLangModel.System,
|
|
||||||
onUpdateLanguage = {},
|
|
||||||
isTrackingSaveFile = false,
|
|
||||||
onUpdateTrackingSaveFileState = {},
|
|
||||||
onChooseTrackingPathToSave = { /*TODO*/ },
|
|
||||||
onUploadSaveFile = { /*TODO*/ },
|
|
||||||
onDownloadSaveFile = { /*TODO*/ },
|
|
||||||
onDevMenuOff = {})
|
|
||||||
}
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.ui.components
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
|
||||||
import androidx.compose.foundation.Image
|
|
||||||
import androidx.compose.foundation.combinedClickable
|
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
||||||
import androidx.compose.material.ripple.rememberRipple
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.unit.Dp
|
|
||||||
import com.megboyzz.devmenu.R
|
|
||||||
import com.megboyzz.devmenu.ui.asPainter
|
|
||||||
|
|
||||||
enum class ElementType {
|
|
||||||
isHidden,
|
|
||||||
isReplaced,
|
|
||||||
isFile,
|
|
||||||
isDir
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("ModifierFactoryUnreferencedReceiver")
|
|
||||||
@OptIn(ExperimentalFoundationApi::class)
|
|
||||||
@Composable
|
|
||||||
fun Modifier.clickableWithRipple(
|
|
||||||
onClick: () -> Unit,
|
|
||||||
onLongClick: () -> Unit = {},
|
|
||||||
enabled: Boolean = true
|
|
||||||
): Modifier {
|
|
||||||
return Modifier.combinedClickable(
|
|
||||||
enabled = enabled,
|
|
||||||
interactionSource = remember { MutableInteractionSource() },
|
|
||||||
indication = rememberRipple(),
|
|
||||||
onClick = onClick,
|
|
||||||
onLongClick = onLongClick
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun FsElementIcon(
|
|
||||||
type: ElementType,
|
|
||||||
modifier: Modifier = Modifier
|
|
||||||
) {
|
|
||||||
|
|
||||||
val painter = when(type){
|
|
||||||
ElementType.isHidden -> R.drawable.icon_hidden_file.asPainter()
|
|
||||||
ElementType.isFile -> R.drawable.icon_file.asPainter()
|
|
||||||
ElementType.isDir -> R.drawable.icon_folder.asPainter()
|
|
||||||
ElementType.isReplaced -> R.drawable.icon_replaced_file.asPainter()
|
|
||||||
}
|
|
||||||
|
|
||||||
Image(painter = painter, contentDescription = null, modifier)
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.ui.models
|
|
||||||
|
|
||||||
import com.megboyzz.devmenu.ui.components.ElementType
|
|
||||||
import java.util.Date
|
|
||||||
|
|
||||||
data class FsElementModel(
|
|
||||||
val name: String,
|
|
||||||
val type: ElementType,
|
|
||||||
val size: Long,
|
|
||||||
val date: Date
|
|
||||||
)
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.ui.models
|
|
||||||
|
|
||||||
enum class GameLangModel(private val lang: String) {
|
|
||||||
System("sys"),
|
|
||||||
Chinese("cn"),
|
|
||||||
Dutch("nl"),
|
|
||||||
English("en"),
|
|
||||||
French("fr"),
|
|
||||||
Deutsch("de"),
|
|
||||||
Italian("it"),
|
|
||||||
Japanese("ja"),
|
|
||||||
Korean("kr"),
|
|
||||||
Portuguese("br"),
|
|
||||||
Russian("ru"),
|
|
||||||
Spanish("es");
|
|
||||||
|
|
||||||
override fun toString() = lang
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.ui.screens
|
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import cafe.adriel.voyager.core.screen.Screen
|
|
||||||
import com.megboyzz.devmenu.ui.components.FileContextMenu
|
|
||||||
import com.megboyzz.devmenu.ui.models.FsElementModel
|
|
||||||
|
|
||||||
class FileContextMenuScreen(
|
|
||||||
private val fsElementModel: FsElementModel,
|
|
||||||
private val onRemoveFile: () -> Unit,
|
|
||||||
) : Screen {
|
|
||||||
@Composable
|
|
||||||
override fun Content() = FileContextMenu(
|
|
||||||
fsElementEntity = fsElementModel,
|
|
||||||
onRemoveElement = onRemoveFile,
|
|
||||||
onUpdateType = {null}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.ui.screens
|
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import cafe.adriel.voyager.core.screen.Screen
|
|
||||||
import cafe.adriel.voyager.navigator.bottomSheet.LocalBottomSheetNavigator
|
|
||||||
import com.megboyzz.devmenu.ui.SpacerHeight
|
|
||||||
import com.megboyzz.devmenu.ui.components.ElementType
|
|
||||||
import com.megboyzz.devmenu.ui.components.FsElement
|
|
||||||
import com.megboyzz.devmenu.ui.components.MainScaffold
|
|
||||||
import com.megboyzz.devmenu.ui.models.FsElementModel
|
|
||||||
import java.util.Date
|
|
||||||
|
|
||||||
class HomeScreen(
|
|
||||||
private val onFloatingButtonClick: () -> Unit
|
|
||||||
): Screen {
|
|
||||||
@Composable
|
|
||||||
override fun Content() {
|
|
||||||
|
|
||||||
val bottomSheetNavigator = LocalBottomSheetNavigator.current
|
|
||||||
|
|
||||||
var searchValue by remember{ mutableStateOf("") }
|
|
||||||
|
|
||||||
val fsElementModel = FsElementModel(
|
|
||||||
name = "my_txt.txt",
|
|
||||||
type = ElementType.isHidden,
|
|
||||||
size = 123,
|
|
||||||
date = Date()
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MainScaffold(
|
|
||||||
onSettingsClick = { /*TODO Переход к настройкам */ },
|
|
||||||
onSearchValueChanged = { searchValue = it },
|
|
||||||
searchValue = searchValue,
|
|
||||||
onFloatingButtonClick = onFloatingButtonClick
|
|
||||||
) {
|
|
||||||
Column {
|
|
||||||
SpacerHeight(height = it.calculateTopPadding())
|
|
||||||
FsElement(
|
|
||||||
fsElementEntity = fsElementModel,
|
|
||||||
onClick = { /*TODO*/ },
|
|
||||||
onLongPressClick = {
|
|
||||||
bottomSheetNavigator.show(
|
|
||||||
FileContextMenuScreen(
|
|
||||||
fsElementModel = fsElementModel,
|
|
||||||
onRemoveFile = {}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.ui.screens
|
|
||||||
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import cafe.adriel.voyager.core.screen.Screen
|
|
||||||
|
|
||||||
class SettingsScreen : Screen {
|
|
||||||
@Composable
|
|
||||||
override fun Content() {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.ui.theme
|
|
||||||
|
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
|
|
||||||
val Purple80 = Color(0xFFD0BCFF)
|
|
||||||
val PurpleGrey80 = Color(0xFFCCC2DC)
|
|
||||||
val Pink80 = Color(0xFFEFB8C8)
|
|
||||||
|
|
||||||
val Purple40 = Color(0xFF6650a4)
|
|
||||||
val PurpleGrey40 = Color(0xFF625b71)
|
|
||||||
val Pink40 = Color(0xFF7D5260)
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.ui.theme
|
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import android.os.Build
|
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.darkColorScheme
|
|
||||||
import androidx.compose.material3.dynamicDarkColorScheme
|
|
||||||
import androidx.compose.material3.dynamicLightColorScheme
|
|
||||||
import androidx.compose.material3.lightColorScheme
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.SideEffect
|
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.graphics.toArgb
|
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.platform.LocalView
|
|
||||||
import androidx.core.view.WindowCompat
|
|
||||||
|
|
||||||
private val DarkColorScheme = darkColorScheme(
|
|
||||||
primary = Purple80,
|
|
||||||
secondary = PurpleGrey80,
|
|
||||||
tertiary = Pink80
|
|
||||||
)
|
|
||||||
|
|
||||||
private val LightColorScheme = lightColorScheme(
|
|
||||||
primary = Color(0xFF36A0EA),
|
|
||||||
secondary = PurpleGrey40,
|
|
||||||
tertiary = Pink40,
|
|
||||||
background = Color(0xFFF2F7FA),
|
|
||||||
surface = Color(0xFFFFFBFE),
|
|
||||||
onPrimary = Color.White,
|
|
||||||
onSecondary = Color.White,
|
|
||||||
onTertiary = Color.White,
|
|
||||||
onBackground = Color(0xFF1B3D54),
|
|
||||||
onSurface = Color(0xFF1C1B1F),
|
|
||||||
)
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun DevMenuTheme(
|
|
||||||
darkTheme: Boolean = isSystemInDarkTheme(),
|
|
||||||
// Dynamic color is available on Android 12+
|
|
||||||
dynamicColor: Boolean = true,
|
|
||||||
content: @Composable () -> Unit
|
|
||||||
) {
|
|
||||||
val colorScheme = when {
|
|
||||||
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
|
|
||||||
val context = LocalContext.current
|
|
||||||
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
|
|
||||||
}
|
|
||||||
|
|
||||||
darkTheme -> DarkColorScheme
|
|
||||||
else -> LightColorScheme
|
|
||||||
}
|
|
||||||
val view = LocalView.current
|
|
||||||
if (!view.isInEditMode) {
|
|
||||||
SideEffect {
|
|
||||||
val window = (view.context as Activity).window
|
|
||||||
window.statusBarColor = colorScheme.primary.toArgb()
|
|
||||||
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MaterialTheme(
|
|
||||||
colorScheme = colorScheme,
|
|
||||||
typography = Typography,
|
|
||||||
content = content
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.ui.theme
|
|
||||||
|
|
||||||
import androidx.compose.material3.Typography
|
|
||||||
import androidx.compose.ui.text.TextStyle
|
|
||||||
import androidx.compose.ui.text.font.FontFamily
|
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
|
||||||
import androidx.compose.ui.unit.sp
|
|
||||||
|
|
||||||
// Set of Material typography styles to start with
|
|
||||||
val Typography = Typography(
|
|
||||||
bodyLarge = TextStyle(
|
|
||||||
fontFamily = FontFamily.Default,
|
|
||||||
fontWeight = FontWeight.Normal,
|
|
||||||
fontSize = 16.sp,
|
|
||||||
lineHeight = 24.sp,
|
|
||||||
letterSpacing = 0.5.sp
|
|
||||||
),
|
|
||||||
titleLarge = TextStyle(
|
|
||||||
fontFamily = FontFamily.Default,
|
|
||||||
fontWeight = FontWeight.Normal,
|
|
||||||
fontSize = 22.sp,
|
|
||||||
lineHeight = 28.sp,
|
|
||||||
letterSpacing = 0.sp
|
|
||||||
),
|
|
||||||
labelSmall = TextStyle(
|
|
||||||
fontFamily = FontFamily.Default,
|
|
||||||
fontWeight = FontWeight.Medium,
|
|
||||||
fontSize = 11.sp,
|
|
||||||
lineHeight = 16.sp,
|
|
||||||
letterSpacing = 0.5.sp
|
|
||||||
)
|
|
||||||
)
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.util
|
|
||||||
|
|
||||||
import android.os.FileObserver
|
|
||||||
import android.util.Log
|
|
||||||
import java.io.File
|
|
||||||
import java.io.FileInputStream
|
|
||||||
import java.io.FileOutputStream
|
|
||||||
import java.util.LinkedList
|
|
||||||
import java.util.Queue
|
|
||||||
import java.util.zip.ZipEntry
|
|
||||||
import java.util.zip.ZipOutputStream
|
|
||||||
|
|
||||||
abstract class BaseObserver(source: String) : FileObserver(source) {
|
|
||||||
|
|
||||||
private val eventQueue : Queue<Int> = LinkedList()
|
|
||||||
|
|
||||||
@OptIn(ExperimentalStdlibApi::class)
|
|
||||||
final override fun onEvent(event: Int, path: String?) {
|
|
||||||
|
|
||||||
val e = FileEvent.entries.find { it.value == event }
|
|
||||||
|
|
||||||
val fileEvent = e ?: FileEvent.UNKNOWN
|
|
||||||
|
|
||||||
Log.i("BaseObserver", "event code = ${event.toHexString()}, FileEvent is $fileEvent")
|
|
||||||
|
|
||||||
onEvent(fileEvent, path)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun hasLastThreeEvents() = runCatching {
|
|
||||||
eventQueue.size == 3 && eventQueue.poll() == OPEN && eventQueue.poll() == ACCESS && eventQueue.poll() == CLOSE_NOWRITE
|
|
||||||
}.getOrNull() ?: false
|
|
||||||
|
|
||||||
abstract fun onEvent(event: FileEvent, path: String?)
|
|
||||||
|
|
||||||
protected fun File.list(regex: String = ".") =
|
|
||||||
this.list { dir, _ -> Regex(regex).matches(dir.absolutePath) }?.asList() ?: listOf()
|
|
||||||
|
|
||||||
|
|
||||||
protected infix fun File.copyToThe(destination: File){
|
|
||||||
this.copyTo(destination, overwrite = true)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun zipAll(outputFolder: String, filesToCompress: List<String>) {
|
|
||||||
if(filesToCompress.isEmpty()){
|
|
||||||
Log.i("BaseObserver", "no files exit!")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
// Проверяем, существует ли выходная папка. Если нет, создаем её.
|
|
||||||
val outputDir = File(outputFolder)
|
|
||||||
if (!outputDir.exists()) outputDir.mkdirs()
|
|
||||||
|
|
||||||
// Генерируем имя ZIP-архива на основе времени
|
|
||||||
val timestamp = System.currentTimeMillis()
|
|
||||||
val zipFileName = "$outputFolder/saves_$timestamp.zip"
|
|
||||||
val zipOutputStream = ZipOutputStream(FileOutputStream(zipFileName))
|
|
||||||
|
|
||||||
for (fileToCompress in filesToCompress) {
|
|
||||||
// Проверяем, существует ли файл
|
|
||||||
val inputFile = File(fileToCompress)
|
|
||||||
if (inputFile.exists()) {
|
|
||||||
// Создаем объект ZipEntry для каждого файла
|
|
||||||
val zipEntry = ZipEntry(inputFile.name)
|
|
||||||
zipOutputStream.putNextEntry(zipEntry)
|
|
||||||
|
|
||||||
// Читаем содержимое файла и записываем его в ZIP-архив
|
|
||||||
val fileInputStream = FileInputStream(inputFile)
|
|
||||||
val buffer = ByteArray(1024)
|
|
||||||
var len: Int
|
|
||||||
while (fileInputStream.read(buffer).also { len = it } > 0) {
|
|
||||||
zipOutputStream.write(buffer, 0, len)
|
|
||||||
}
|
|
||||||
fileInputStream.close()
|
|
||||||
|
|
||||||
// Закрываем текущий ZipEntry
|
|
||||||
zipOutputStream.closeEntry()
|
|
||||||
} else {
|
|
||||||
Log.i("SaveFileObserver", "Файл не существует: $fileToCompress")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Закрываем ZipOutputStream
|
|
||||||
zipOutputStream.close()
|
|
||||||
Log.i("SaveFileObserver", "Архивация завершена. Архив создан: $zipFileName")
|
|
||||||
} catch (e: Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.util
|
|
||||||
|
|
||||||
import android.os.FileObserver
|
|
||||||
|
|
||||||
enum class FileEvent(val value: Int) {
|
|
||||||
|
|
||||||
ACCESS(FileObserver.ACCESS),
|
|
||||||
MODIFY(FileObserver.MODIFY),
|
|
||||||
ATTRIB(FileObserver.ATTRIB),
|
|
||||||
CLOSE_WRITE(FileObserver.CLOSE_WRITE),
|
|
||||||
CLOSE_NOWRITE(FileObserver.CLOSE_NOWRITE),
|
|
||||||
OPEN(FileObserver.OPEN),
|
|
||||||
MOVED_FROM(FileObserver.MOVED_FROM),
|
|
||||||
MOVED_TO(FileObserver.MOVED_TO),
|
|
||||||
CREATE(FileObserver.CREATE),
|
|
||||||
DELETE(FileObserver.DELETE),
|
|
||||||
DELETE_SELF(FileObserver.DELETE_SELF),
|
|
||||||
MOVE_SELF(FileObserver.MOVE_SELF),
|
|
||||||
UNKNOWN(-1);
|
|
||||||
|
|
||||||
override fun toString() = this.name
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
package com.megboyzz.devmenu.util
|
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import java.io.File
|
|
||||||
import kotlin.concurrent.thread
|
|
||||||
|
|
||||||
|
|
||||||
class SaveFileObserver(
|
|
||||||
private val source: String,
|
|
||||||
private val destinationFolder: String
|
|
||||||
) : BaseObserver(source) {
|
|
||||||
|
|
||||||
private var countSnapshots: Int = 1
|
|
||||||
|
|
||||||
private val checkList = listOf(
|
|
||||||
//FileEvent.CLOSE_WRITE,
|
|
||||||
//FileEvent.MODIFY,
|
|
||||||
//FileEvent.DELETE,
|
|
||||||
//FileEvent.CREATE,
|
|
||||||
//FileEvent.ACCESS,
|
|
||||||
//FileEvent.OPEN,
|
|
||||||
FileEvent.CLOSE_NOWRITE
|
|
||||||
)
|
|
||||||
init {
|
|
||||||
val dest = File(destinationFolder)
|
|
||||||
if(dest.isFile) dest.delete()
|
|
||||||
if(!dest.exists()) dest.mkdir()
|
|
||||||
val list = dest.list{
|
|
||||||
dir, name -> name.endsWith(".sb")
|
|
||||||
}
|
|
||||||
list?.forEach { File(dest, it).delete() }
|
|
||||||
File(source) copyToThe File(destinationFolder, "BASE.sb")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onEvent(event: FileEvent, path: String?) {
|
|
||||||
Log.i("SaveFileObserver", "onEvent $event")
|
|
||||||
if (event in checkList) {
|
|
||||||
Log.d("SaveFileObserver", "File created or modified: $source")
|
|
||||||
File(source) copyToThe File(destinationFolder, "$event-$countSnapshots.sb")
|
|
||||||
countSnapshots++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun stopWatching() {
|
|
||||||
super.stopWatching()
|
|
||||||
val filesList = File(destinationFolder).list{ _, name -> name.endsWith(".sb") }?.map { it }
|
|
||||||
if (filesList != null) {
|
|
||||||
zipAll(destinationFolder, filesList)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="30dp"
|
|
||||||
android:height="3dp"
|
|
||||||
android:viewportWidth="30"
|
|
||||||
android:viewportHeight="3">
|
|
||||||
<path
|
|
||||||
android:pathData="M1.5,0L28.5,0A1.5,1.5 0,0 1,30 1.5L30,1.5A1.5,1.5 0,0 1,28.5 3L1.5,3A1.5,1.5 0,0 1,0 1.5L0,1.5A1.5,1.5 0,0 1,1.5 0z"
|
|
||||||
android:fillColor="#C9C9C9"/>
|
|
||||||
</vector>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="960"
|
|
||||||
android:viewportHeight="960">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FF000000"
|
|
||||||
android:pathData="M480,640 L280,440l56,-58 104,104v-326h80v326l104,-104 56,58 -200,200ZM240,800q-33,0 -56.5,-23.5T160,720v-120h80v120h480v-120h80v120q0,33 -23.5,56.5T720,800L240,800Z"/>
|
|
||||||
</vector>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="12dp"
|
|
||||||
android:height="12dp"
|
|
||||||
android:viewportWidth="12"
|
|
||||||
android:viewportHeight="12">
|
|
||||||
<path
|
|
||||||
android:pathData="M3.45,10.613C3.358,10.512 3.311,10.396 3.306,10.262C3.302,10.129 3.35,10.012 3.45,9.913L7.388,5.975L3.45,2.038C3.358,1.946 3.311,1.831 3.306,1.694C3.302,1.556 3.35,1.438 3.45,1.338C3.542,1.238 3.656,1.185 3.794,1.181C3.931,1.177 4.05,1.225 4.15,1.325L8.538,5.713C8.579,5.754 8.608,5.796 8.625,5.838C8.642,5.879 8.65,5.925 8.65,5.975C8.65,6.025 8.642,6.071 8.625,6.113C8.608,6.154 8.579,6.196 8.538,6.238L4.15,10.625C4.058,10.717 3.944,10.762 3.806,10.762C3.669,10.762 3.55,10.712 3.45,10.613Z"
|
|
||||||
android:fillColor="#1B3D54"/>
|
|
||||||
</vector>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="960"
|
|
||||||
android:viewportHeight="960">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FF000000"
|
|
||||||
android:pathData="M160,800q-33,0 -56.5,-23.5T80,720v-480q0,-33 23.5,-56.5T160,160h240l80,80h320q33,0 56.5,23.5T880,320v400q0,33 -23.5,56.5T800,800L160,800ZM160,720h640v-400L447,320l-80,-80L160,240v480ZM160,720v-480,480Z"/>
|
|
||||||
</vector>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path
|
|
||||||
android:pathData="M16.1,13.3L14.65,11.85C14.8,11.067 14.575,10.333 13.975,9.65C13.375,8.967 12.6,8.7 11.65,8.85L10.2,7.4C10.483,7.267 10.771,7.167 11.063,7.1C11.354,7.033 11.667,7 12,7C13.25,7 14.313,7.437 15.188,8.312C16.063,9.187 16.5,10.25 16.5,11.5C16.5,11.833 16.467,12.146 16.4,12.438C16.333,12.729 16.233,13.017 16.1,13.3ZM19.3,16.45L17.85,15.05C18.483,14.567 19.046,14.038 19.538,13.462C20.029,12.887 20.45,12.233 20.8,11.5C19.967,9.817 18.771,8.479 17.212,7.487C15.654,6.496 13.917,6 12,6C11.517,6 11.042,6.033 10.575,6.1C10.108,6.167 9.65,6.267 9.2,6.4L7.65,4.85C8.333,4.567 9.033,4.354 9.75,4.212C10.467,4.071 11.217,4 12,4C14.517,4 16.758,4.696 18.725,6.087C20.692,7.479 22.117,9.283 23,11.5C22.617,12.483 22.112,13.396 21.487,14.238C20.862,15.079 20.133,15.817 19.3,16.45ZM19.8,22.6L15.6,18.45C15.017,18.633 14.429,18.771 13.837,18.862C13.246,18.954 12.633,19 12,19C9.483,19 7.242,18.304 5.275,16.913C3.308,15.521 1.883,13.717 1,11.5C1.35,10.617 1.792,9.796 2.325,9.037C2.858,8.279 3.467,7.6 4.15,7L1.4,4.2L2.8,2.8L21.2,21.2L19.8,22.6ZM5.55,8.4C5.067,8.833 4.625,9.308 4.225,9.825C3.825,10.342 3.483,10.9 3.2,11.5C4.033,13.183 5.229,14.521 6.787,15.512C8.346,16.504 10.083,17 12,17C12.333,17 12.658,16.979 12.975,16.938C13.292,16.896 13.617,16.85 13.95,16.8L13.05,15.85C12.867,15.9 12.692,15.938 12.525,15.962C12.358,15.988 12.183,16 12,16C10.75,16 9.688,15.563 8.813,14.688C7.938,13.813 7.5,12.75 7.5,11.5C7.5,11.317 7.512,11.142 7.537,10.975C7.563,10.808 7.6,10.633 7.65,10.45L5.55,8.4Z"
|
|
||||||
android:fillColor="#1B3D54"/>
|
|
||||||
</vector>
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="55dp"
|
|
||||||
android:height="54dp"
|
|
||||||
android:viewportWidth="55"
|
|
||||||
android:viewportHeight="54">
|
|
||||||
<path
|
|
||||||
android:pathData="M10,0L44.857,0A10,10 0,0 1,54.857 10L54.857,43.053A10,10 0,0 1,44.857 53.053L10,53.053A10,10 0,0 1,0 43.053L0,10A10,10 0,0 1,10 0z"
|
|
||||||
android:fillColor="#36A0EA"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M31.629,23.289C30.292,23.289 29.01,22.824 28.065,21.995C27.12,21.166 26.589,20.041 26.589,18.868V12.974H19.869C18.978,12.974 18.123,13.284 17.493,13.837C16.863,14.39 16.509,15.139 16.509,15.921V35.079C16.509,35.861 16.863,36.61 17.493,37.163C18.123,37.716 18.978,38.026 19.869,38.026H34.989C35.88,38.026 36.734,37.716 37.364,37.163C37.995,36.61 38.349,35.861 38.349,35.079V23.289H31.629ZM28.269,18.868C28.269,19.65 28.623,20.4 29.253,20.952C29.883,21.505 30.737,21.816 31.629,21.816H37.66L28.269,13.578V18.868ZM19.869,11.5H28.269L40.029,21.816V35.079C40.029,36.251 39.498,37.376 38.552,38.205C37.607,39.034 36.325,39.5 34.989,39.5H19.869C18.532,39.5 17.25,39.034 16.305,38.205C15.36,37.376 14.829,36.251 14.829,35.079V15.921C14.829,14.748 15.36,13.624 16.305,12.795C17.25,11.966 18.532,11.5 19.869,11.5Z"
|
|
||||||
android:fillColor="#ffffff"/>
|
|
||||||
</vector>
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="55dp"
|
|
||||||
android:height="54dp"
|
|
||||||
android:viewportWidth="55"
|
|
||||||
android:viewportHeight="54">
|
|
||||||
<path
|
|
||||||
android:pathData="M10,0L44.857,0A10,10 0,0 1,54.857 10L54.857,43.053A10,10 0,0 1,44.857 53.053L10,53.053A10,10 0,0 1,0 43.053L0,10A10,10 0,0 1,10 0z"
|
|
||||||
android:fillColor="#36A0EA"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M17.165,14.092H23.481L28.218,19.066H37.692C38.948,19.066 40.153,19.59 41.041,20.522C41.93,21.455 42.429,22.72 42.429,24.039V33.987C42.429,35.306 41.93,36.571 41.041,37.504C40.153,38.437 38.948,38.96 37.692,38.96H17.165C15.909,38.96 14.704,38.437 13.816,37.504C12.928,36.571 12.429,35.306 12.429,33.987V19.066C12.429,17.747 12.928,16.482 13.816,15.549C14.704,14.616 15.909,14.092 17.165,14.092ZM17.165,15.75C16.328,15.75 15.525,16.099 14.932,16.721C14.34,17.343 14.007,18.186 14.007,19.066V33.987C14.007,34.866 14.34,35.71 14.932,36.332C15.525,36.953 16.328,37.303 17.165,37.303H37.692C38.529,37.303 39.333,36.953 39.925,36.332C40.517,35.71 40.85,34.866 40.85,33.987V24.039C40.85,23.16 40.517,22.317 39.925,21.695C39.333,21.073 38.529,20.724 37.692,20.724H27.571L22.834,15.75H17.165Z"
|
|
||||||
android:fillColor="#ffffff"/>
|
|
||||||
</vector>
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="55dp"
|
|
||||||
android:height="54dp"
|
|
||||||
android:viewportWidth="55"
|
|
||||||
android:viewportHeight="54">
|
|
||||||
<path
|
|
||||||
android:pathData="M10,0L44.857,0A10,10 0,0 1,54.857 10L54.857,43.053A10,10 0,0 1,44.857 53.053L10,53.053A10,10 0,0 1,0 43.053L0,10A10,10 0,0 1,10 0z"
|
|
||||||
android:fillColor="#36A0EA"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M31.629,23.289C30.292,23.289 29.01,22.824 28.065,21.995C27.12,21.166 26.589,20.041 26.589,18.868V12.974H19.869C18.978,12.974 18.123,13.284 17.493,13.837C16.863,14.39 16.509,15.139 16.509,15.921V35.079C16.509,35.861 16.863,36.61 17.493,37.163C18.123,37.716 18.978,38.026 19.869,38.026H34.989C35.88,38.026 36.734,37.716 37.364,37.163C37.995,36.61 38.349,35.861 38.349,35.079V23.289H31.629ZM28.269,18.868C28.269,19.65 28.623,20.4 29.253,20.952C29.883,21.505 30.737,21.816 31.629,21.816H37.66L28.269,13.578V18.868ZM19.869,11.5H28.269L40.029,21.816V35.079C40.029,36.251 39.498,37.376 38.552,38.205C37.607,39.034 36.325,39.5 34.989,39.5H19.869C18.532,39.5 17.25,39.034 16.305,38.205C15.36,37.376 14.829,36.251 14.829,35.079V15.921C14.829,14.748 15.36,13.624 16.305,12.795C17.25,11.966 18.532,11.5 19.869,11.5Z"
|
|
||||||
android:fillColor="#ffffff"/>
|
|
||||||
<group>
|
|
||||||
<clip-path
|
|
||||||
android:pathData="M21.429,23h12v12h-12z"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M29.479,29.65L28.754,28.925C28.829,28.533 28.716,28.167 28.416,27.825C28.116,27.483 27.729,27.35 27.254,27.425L26.529,26.7C26.67,26.633 26.814,26.583 26.96,26.55C27.106,26.517 27.262,26.5 27.429,26.5C28.054,26.5 28.585,26.719 29.022,27.156C29.46,27.594 29.679,28.125 29.679,28.75C29.679,28.917 29.662,29.073 29.629,29.219C29.595,29.365 29.545,29.508 29.479,29.65ZM31.079,31.225L30.354,30.525C30.67,30.283 30.951,30.019 31.197,29.731C31.443,29.444 31.654,29.117 31.829,28.75C31.412,27.908 30.814,27.24 30.035,26.744C29.256,26.248 28.387,26 27.429,26C27.187,26 26.949,26.017 26.716,26.05C26.483,26.083 26.254,26.133 26.029,26.2L25.254,25.425C25.595,25.283 25.945,25.177 26.304,25.106C26.662,25.035 27.037,25 27.429,25C28.687,25 29.808,25.348 30.791,26.044C31.774,26.74 32.487,27.642 32.929,28.75C32.737,29.242 32.485,29.698 32.172,30.119C31.86,30.54 31.495,30.908 31.079,31.225ZM31.329,34.3L29.229,32.225C28.937,32.317 28.643,32.385 28.347,32.431C28.052,32.477 27.745,32.5 27.429,32.5C26.17,32.5 25.049,32.152 24.066,31.456C23.083,30.76 22.37,29.858 21.929,28.75C22.104,28.308 22.324,27.898 22.591,27.519C22.858,27.14 23.162,26.8 23.504,26.5L22.129,25.1L22.829,24.4L32.029,33.6L31.329,34.3ZM24.204,27.2C23.962,27.417 23.741,27.654 23.541,27.913C23.341,28.171 23.17,28.45 23.029,28.75C23.445,29.592 24.043,30.26 24.822,30.756C25.601,31.252 26.47,31.5 27.429,31.5C27.595,31.5 27.758,31.49 27.916,31.469C28.074,31.448 28.237,31.425 28.404,31.4L27.954,30.925C27.862,30.95 27.774,30.969 27.691,30.981C27.608,30.994 27.52,31 27.429,31C26.804,31 26.272,30.781 25.835,30.344C25.397,29.906 25.179,29.375 25.179,28.75C25.179,28.658 25.185,28.571 25.197,28.487C25.21,28.404 25.229,28.317 25.254,28.225L24.204,27.2Z"
|
|
||||||
android:fillColor="#ffffff"/>
|
|
||||||
</group>
|
|
||||||
</vector>
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="55dp"
|
|
||||||
android:height="54dp"
|
|
||||||
android:viewportWidth="55"
|
|
||||||
android:viewportHeight="54">
|
|
||||||
<path
|
|
||||||
android:pathData="M10,0L44.857,0A10,10 0,0 1,54.857 10L54.857,43.053A10,10 0,0 1,44.857 53.053L10,53.053A10,10 0,0 1,0 43.053L0,10A10,10 0,0 1,10 0z"
|
|
||||||
android:fillColor="#36A0EA"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M31.629,23.289C30.292,23.289 29.01,22.824 28.065,21.995C27.12,21.166 26.589,20.041 26.589,18.868V12.974H19.869C18.978,12.974 18.123,13.284 17.493,13.837C16.863,14.39 16.509,15.139 16.509,15.921V35.079C16.509,35.861 16.863,36.61 17.493,37.163C18.123,37.716 18.978,38.026 19.869,38.026H34.989C35.88,38.026 36.734,37.716 37.364,37.163C37.995,36.61 38.349,35.861 38.349,35.079V23.289H31.629ZM28.269,18.868C28.269,19.65 28.623,20.4 29.253,20.952C29.883,21.505 30.737,21.816 31.629,21.816H37.66L28.269,13.578V18.868ZM19.869,11.5H28.269L40.029,21.816V35.079C40.029,36.251 39.498,37.376 38.552,38.205C37.607,39.034 36.325,39.5 34.989,39.5H19.869C18.532,39.5 17.25,39.034 16.305,38.205C15.36,37.376 14.829,36.251 14.829,35.079V15.921C14.829,14.748 15.36,13.624 16.305,12.795C17.25,11.966 18.532,11.5 19.869,11.5Z"
|
|
||||||
android:fillColor="#ffffff"/>
|
|
||||||
<path
|
|
||||||
android:pathData="M25.09,32.409L27.428,31.009L29.765,32.425L29.147,29.775L31.204,27.998L28.491,27.759L27.428,25.266L26.365,27.744L23.652,27.982L25.709,29.766L25.09,32.409ZM27.428,31.84L24.749,33.45C24.681,33.486 24.612,33.503 24.542,33.5C24.472,33.496 24.408,33.475 24.351,33.435C24.294,33.394 24.25,33.342 24.222,33.276C24.193,33.211 24.189,33.138 24.21,33.057L24.915,30.026L22.558,27.979C22.494,27.926 22.454,27.865 22.439,27.796C22.423,27.727 22.426,27.659 22.447,27.592C22.463,27.528 22.5,27.475 22.555,27.432C22.61,27.388 22.678,27.363 22.759,27.357L25.877,27.083L27.09,24.216C27.124,24.146 27.172,24.092 27.234,24.055C27.295,24.018 27.36,24 27.428,24C27.496,24 27.56,24.018 27.622,24.055C27.684,24.092 27.732,24.146 27.766,24.216L28.979,27.083L32.097,27.357C32.178,27.363 32.246,27.388 32.301,27.432C32.356,27.475 32.394,27.528 32.415,27.592C32.432,27.659 32.433,27.727 32.417,27.796C32.402,27.865 32.362,27.926 32.298,27.979L29.941,30.026L30.652,33.057C30.669,33.138 30.663,33.211 30.634,33.276C30.605,33.342 30.563,33.394 30.505,33.435C30.448,33.475 30.384,33.496 30.314,33.5C30.244,33.503 30.175,33.486 30.107,33.45L27.428,31.84Z"
|
|
||||||
android:fillColor="#ffffff"/>
|
|
||||||
</vector>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="24dp"
|
|
||||||
android:height="24dp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path
|
|
||||||
android:pathData="M11,17H13V11H11V17ZM12,9C12.283,9 12.521,8.904 12.712,8.712C12.904,8.521 13,8.283 13,8C13,7.717 12.904,7.479 12.712,7.287C12.521,7.096 12.283,7 12,7C11.717,7 11.479,7.096 11.288,7.287C11.096,7.479 11,7.717 11,8C11,8.283 11.096,8.521 11.288,8.712C11.479,8.904 11.717,9 12,9ZM12,22C10.617,22 9.317,21.737 8.1,21.212C6.883,20.688 5.825,19.975 4.925,19.075C4.025,18.175 3.313,17.117 2.787,15.9C2.263,14.683 2,13.383 2,12C2,10.617 2.263,9.317 2.787,8.1C3.313,6.883 4.025,5.825 4.925,4.925C5.825,4.025 6.883,3.313 8.1,2.787C9.317,2.263 10.617,2 12,2C13.383,2 14.683,2.263 15.9,2.787C17.117,3.313 18.175,4.025 19.075,4.925C19.975,5.825 20.688,6.883 21.212,8.1C21.737,9.317 22,10.617 22,12C22,13.383 21.737,14.683 21.212,15.9C20.688,17.117 19.975,18.175 19.075,19.075C18.175,19.975 17.117,20.688 15.9,21.212C14.683,21.737 13.383,22 12,22ZM12,20C14.233,20 16.125,19.225 17.675,17.675C19.225,16.125 20,14.233 20,12C20,9.767 19.225,7.875 17.675,6.325C16.125,4.775 14.233,4 12,4C9.767,4 7.875,4.775 6.325,6.325C4.775,7.875 4,9.767 4,12C4,14.233 4.775,16.125 6.325,17.675C7.875,19.225 9.767,20 12,20Z"
|
|
||||||
android:fillColor="#1B3D54"/>
|
|
||||||
</vector>
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user