diff --git a/app/src/main/java/com/ea/ironmonkey/devmenu/util/UtilitiesAndData.java b/app/src/main/java/com/ea/ironmonkey/devmenu/util/UtilitiesAndData.java
index 378a0af..7b22749 100644
--- a/app/src/main/java/com/ea/ironmonkey/devmenu/util/UtilitiesAndData.java
+++ b/app/src/main/java/com/ea/ironmonkey/devmenu/util/UtilitiesAndData.java
@@ -63,7 +63,7 @@ public class UtilitiesAndData {
public static void printLog(String msg){
try{
if(isLoggerEnabled())
- stream.write(msg.getBytes(StandardCharsets.UTF_8));
+ stream.write(msg.getBytes(StandardCharsets.UTF_8));
} catch (IOException e) {
Log.wtf(LOG_TAG, "cant write to stream(((");
e.printStackTrace();
diff --git a/devmenu/build.gradle.kts b/devmenu/build.gradle.kts
index 8aa93bd..4889a0e 100644
--- a/devmenu/build.gradle.kts
+++ b/devmenu/build.gradle.kts
@@ -32,6 +32,7 @@ android {
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
+ isCoreLibraryDesugaringEnabled = true
}
kotlinOptions {
jvmTarget = "1.8"
@@ -71,6 +72,10 @@ dependencies {
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)
diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/MainActivity.kt b/devmenu/src/main/java/com/megboyzz/devmenu/MainActivity.kt
index 421a887..f862884 100644
--- a/devmenu/src/main/java/com/megboyzz/devmenu/MainActivity.kt
+++ b/devmenu/src/main/java/com/megboyzz/devmenu/MainActivity.kt
@@ -4,6 +4,8 @@ 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
@@ -34,7 +36,9 @@ class MainActivity : ComponentActivity() {
}
setContent {
- BottomSheetNavigator {
+ BottomSheetNavigator(
+ sheetShape = RoundedCornerShape(topStart = 10.dp, topEnd = 10.dp)
+ ) {
Navigator(HomeScreen(::runGame))
}
}
diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/ui/Utlil.kt b/devmenu/src/main/java/com/megboyzz/devmenu/ui/Utlil.kt
index f5a6eaf..34d25d6 100644
--- a/devmenu/src/main/java/com/megboyzz/devmenu/ui/Utlil.kt
+++ b/devmenu/src/main/java/com/megboyzz/devmenu/ui/Utlil.kt
@@ -1,5 +1,6 @@
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
@@ -8,6 +9,11 @@ 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)
@@ -23,6 +29,22 @@ 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 контексте
diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/AnimationSpec.kt b/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/AnimationSpec.kt
index c6aac93..e20e5bf 100644
--- a/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/AnimationSpec.kt
+++ b/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/AnimationSpec.kt
@@ -4,6 +4,8 @@ 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
@@ -15,4 +17,12 @@ val enter = expandIn(
val exit = shrinkOut(
shrinkTowards = Alignment.CenterStart,
animationSpec = tween(250)
-)
\ No newline at end of file
+)
+
+fun searchFieldEnter(duration: Int) = slideInVertically(animationSpec = tween(durationMillis = duration)) {
+ -it / 3
+}
+
+fun searchFieldExit(duration: Int) = slideOutVertically(animationSpec = tween(durationMillis = duration)) {
+ -it / 3
+}
\ No newline at end of file
diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/ContextMenuState.kt b/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/ContextMenuState.kt
index 503e1dc..417e758 100644
--- a/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/ContextMenuState.kt
+++ b/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/ContextMenuState.kt
@@ -29,8 +29,11 @@ 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.entities.FsElementModel
+import com.megboyzz.devmenu.ui.models.FsElementModel
+import com.megboyzz.devmenu.ui.formatDate
+import com.megboyzz.devmenu.ui.humanReadableByteCountSI
@Composable
fun ClickableMenuPosition(
@@ -112,9 +115,7 @@ fun FileContextMenu(
var state by remember { mutableStateOf(ContextMenuState.Main) }
- CoreFileContextMenu {
- FsElementInContextMenu(name = fsElementEntity.name, type = fsElementEntity.type)
- Divider()
+ CoreFileContextMenu(fsElementEntity = fsElementEntity) {
AnimatedBoxForContextMenuContent(isVisible = state == ContextMenuState.Main){
AnimatedBoxForContextMenuContent(isVisible = innerType == ElementType.isFile) {
ClickableMenuPosition(
@@ -154,7 +155,7 @@ fun FileContextMenu(
ClickableMenuPosition(
name = "Свойства",
icon = R.drawable.info.asPainter(),
- onClick = {}
+ onClick = { state = ContextMenuState.Props }
)
ClickableMenuPosition(
name = "Удалить",
@@ -181,6 +182,7 @@ fun FileContextMenu(
icon = R.drawable.info.asPainter(),
withEnd = false,
)
+ PropsView(fsElementEntity = fsElementEntity)
RemoveButton(text = "Назад") {
state = ContextMenuState.Main
}
@@ -188,6 +190,17 @@ fun FileContextMenu(
}
}
+@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
@@ -215,9 +228,8 @@ fun RemoveFileButtonsGroup(
Row(
horizontalArrangement = Arrangement.spacedBy(12.dp),
) {
- val m = Modifier.weight(1f)
- RemoveButton(text = "Удалить", onClick = onDelete, modifier = m)
- RemoveButton(text = "Отмена", onClick = onCancel, modifier = m)
+ RemoveButton(text = "Удалить", onClick = onDelete, modifier = Modifier.weight(1f))
+ RemoveButton(text = "Отмена", onClick = onCancel, modifier = Modifier.weight(1f))
}
}
@@ -239,6 +251,7 @@ fun RemoveButton(
@Composable
fun CoreFileContextMenu(
+ fsElementEntity: FsElementModel,
content: @Composable () -> Unit
) {
@@ -264,7 +277,12 @@ fun CoreFileContextMenu(
vertical = 32.dp
),
){
- Column(verticalArrangement = Arrangement.spacedBy(20.dp)) {
+ Column {
+ Column(verticalArrangement = Arrangement.spacedBy(16.dp)) {
+ FsElementInContextMenu(name = fsElementEntity.name, type = fsElementEntity.type)
+ Divider()
+ SpacerHeight(height = 0.dp)
+ }
content()
}
}
diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/Files.kt b/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/Files.kt
index 9dbbc8e..051a869 100644
--- a/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/Files.kt
+++ b/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/Files.kt
@@ -7,7 +7,7 @@ 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.entities.FsElementModel
+import com.megboyzz.devmenu.ui.models.FsElementModel
@Composable
fun FsElement(
diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/FolderStatusBar.kt b/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/FolderStatusBar.kt
new file mode 100644
index 0000000..0fd4519
--- /dev/null
+++ b/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/FolderStatusBar.kt
@@ -0,0 +1,55 @@
+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) {
+
+ 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)
+}
\ No newline at end of file
diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/Scaffold.kt b/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/HomeScaffold.kt
similarity index 81%
rename from devmenu/src/main/java/com/megboyzz/devmenu/ui/components/Scaffold.kt
rename to devmenu/src/main/java/com/megboyzz/devmenu/ui/components/HomeScaffold.kt
index e4c64fd..3b628d3 100644
--- a/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/Scaffold.kt
+++ b/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/HomeScaffold.kt
@@ -1,10 +1,5 @@
package com.megboyzz.devmenu.ui.components
-import android.widget.Toast
-import androidx.compose.animation.AnimatedVisibility
-import androidx.compose.animation.core.tween
-import androidx.compose.animation.slideInVertically
-import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
@@ -38,7 +33,6 @@ 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.asComposableLambda
import com.megboyzz.devmenu.ui.theme.DevMenuTheme
@OptIn(ExperimentalMaterial3Api::class)
@@ -92,28 +86,15 @@ fun TopBar(
val context = LocalContext.current
TopAppBar(
title = {
- Box {
- AnimatedVisibility(
- visible = isSearching,
- enter = slideInVertically(animationSpec = tween(durationMillis = 200)) {
- -it / 3
- },
- exit = slideOutVertically(animationSpec = tween(durationMillis = 200)) {
- -it / 3
- }
- ) {
- SearchFileTextField(
- value = searchValue,
- onValueChange = onSearchValueChanged
- )
- }
- if(!isSearching) Text("NFSMW DevMenu")
- }
-
+ if(isSearching){
+ SearchFileTextField(
+ value = searchValue,
+ onValueChange = onSearchValueChanged
+ )
+ }else Text("NFSMW DevMenu")
},
actions = {
SearchButton {
- Toast.makeText(context, "hh", Toast.LENGTH_LONG).show()
isSearching = !isSearching
}
SettingsButton(onClick = onSettingsClick)
@@ -169,9 +150,7 @@ fun SearchFileTextField(
value = value,
onValueChange = onValueChange,
decorationBox = { innerTextField ->
- Box(
-
- ) {
+ Box(Modifier.padding(end = 12.dp)) {
Row(
Modifier
.fillMaxWidth()
diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/Settings.kt b/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/Settings.kt
new file mode 100644
index 0000000..82b3ce6
--- /dev/null
+++ b/devmenu/src/main/java/com/megboyzz/devmenu/ui/components/Settings.kt
@@ -0,0 +1,211 @@
+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 = {})
+}
\ No newline at end of file
diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/ui/entities/FsElementModel.kt b/devmenu/src/main/java/com/megboyzz/devmenu/ui/models/FsElementModel.kt
similarity index 82%
rename from devmenu/src/main/java/com/megboyzz/devmenu/ui/entities/FsElementModel.kt
rename to devmenu/src/main/java/com/megboyzz/devmenu/ui/models/FsElementModel.kt
index 303d277..0b92b39 100644
--- a/devmenu/src/main/java/com/megboyzz/devmenu/ui/entities/FsElementModel.kt
+++ b/devmenu/src/main/java/com/megboyzz/devmenu/ui/models/FsElementModel.kt
@@ -1,4 +1,4 @@
-package com.megboyzz.devmenu.ui.entities
+package com.megboyzz.devmenu.ui.models
import com.megboyzz.devmenu.ui.components.ElementType
import java.util.Date
diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/ui/models/GameLangModel.kt b/devmenu/src/main/java/com/megboyzz/devmenu/ui/models/GameLangModel.kt
new file mode 100644
index 0000000..f270738
--- /dev/null
+++ b/devmenu/src/main/java/com/megboyzz/devmenu/ui/models/GameLangModel.kt
@@ -0,0 +1,19 @@
+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
+
+}
\ No newline at end of file
diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/ui/screens/FileContextMenuScreen.kt b/devmenu/src/main/java/com/megboyzz/devmenu/ui/screens/FileContextMenuScreen.kt
index aaadbff..ef84bb6 100644
--- a/devmenu/src/main/java/com/megboyzz/devmenu/ui/screens/FileContextMenuScreen.kt
+++ b/devmenu/src/main/java/com/megboyzz/devmenu/ui/screens/FileContextMenuScreen.kt
@@ -3,22 +3,16 @@ 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.entities.FsElementModel
+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}
- )
-
- }
+ override fun Content() = FileContextMenu(
+ fsElementEntity = fsElementModel,
+ onRemoveElement = onRemoveFile,
+ onUpdateType = {null}
+ )
}
\ No newline at end of file
diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/ui/screens/HomeScreen.kt b/devmenu/src/main/java/com/megboyzz/devmenu/ui/screens/HomeScreen.kt
index 2138e07..25fd2c0 100644
--- a/devmenu/src/main/java/com/megboyzz/devmenu/ui/screens/HomeScreen.kt
+++ b/devmenu/src/main/java/com/megboyzz/devmenu/ui/screens/HomeScreen.kt
@@ -1,5 +1,6 @@
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
@@ -7,10 +8,11 @@ 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.entities.FsElementModel
+import com.megboyzz.devmenu.ui.models.FsElementModel
import java.util.Date
class HomeScreen(
@@ -38,18 +40,22 @@ class HomeScreen(
searchValue = searchValue,
onFloatingButtonClick = onFloatingButtonClick
) {
- FsElement(
- fsElementEntity = fsElementModel,
- onClick = { /*TODO*/ },
- onLongPressClick = {
- bottomSheetNavigator.show(
- FileContextMenuScreen(
- fsElementModel = fsElementModel,
- onRemoveFile = {}
+ Column {
+ SpacerHeight(height = it.calculateTopPadding())
+ FsElement(
+ fsElementEntity = fsElementModel,
+ onClick = { /*TODO*/ },
+ onLongPressClick = {
+ bottomSheetNavigator.show(
+ FileContextMenuScreen(
+ fsElementModel = fsElementModel,
+ onRemoveFile = {}
+ )
)
- )
- }
- )
+ }
+ )
+ }
+
}
}
diff --git a/devmenu/src/main/java/com/megboyzz/devmenu/ui/screens/SettingsScreen.kt b/devmenu/src/main/java/com/megboyzz/devmenu/ui/screens/SettingsScreen.kt
new file mode 100644
index 0000000..1f0da10
--- /dev/null
+++ b/devmenu/src/main/java/com/megboyzz/devmenu/ui/screens/SettingsScreen.kt
@@ -0,0 +1,11 @@
+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")
+ }
+}
\ No newline at end of file
diff --git a/devmenu/src/main/res/drawable/download.xml b/devmenu/src/main/res/drawable/download.xml
new file mode 100644
index 0000000..844165f
--- /dev/null
+++ b/devmenu/src/main/res/drawable/download.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/devmenu/src/main/res/drawable/folder.xml b/devmenu/src/main/res/drawable/folder.xml
new file mode 100644
index 0000000..d0a9fe7
--- /dev/null
+++ b/devmenu/src/main/res/drawable/folder.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/devmenu/src/main/res/drawable/lang.xml b/devmenu/src/main/res/drawable/lang.xml
new file mode 100644
index 0000000..f6e7b46
--- /dev/null
+++ b/devmenu/src/main/res/drawable/lang.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/devmenu/src/main/res/drawable/tracking.xml b/devmenu/src/main/res/drawable/tracking.xml
new file mode 100644
index 0000000..8ed1fb1
--- /dev/null
+++ b/devmenu/src/main/res/drawable/tracking.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/devmenu/src/main/res/drawable/upload.xml b/devmenu/src/main/res/drawable/upload.xml
new file mode 100644
index 0000000..4f812f7
--- /dev/null
+++ b/devmenu/src/main/res/drawable/upload.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 1c80f76..18af5c6 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -1,5 +1,6 @@
[versions]
agp = "8.1.2"
+compose-settings-ui-m3 = "1.0.3"
junit-junit = "4.13.2"
kotlin = "1.9.21"
core-ktx = "1.12.0"
@@ -18,6 +19,7 @@ room = "2.6.1"
voyager = "1.0.0"
[libraries]
+compose-settings-ui-m3 = { module = "com.github.alorma:compose-settings-ui-m3", version.ref = "compose-settings-ui-m3" }
core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-test-ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test-ext-junit" }
diff --git a/mpcore/.gitignore b/mpcore/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/mpcore/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/mpcore/build.gradle.kts b/mpcore/build.gradle.kts
new file mode 100644
index 0000000..2146e56
--- /dev/null
+++ b/mpcore/build.gradle.kts
@@ -0,0 +1,55 @@
+@Suppress("DSL_SCOPE_VIOLATION") // TODO: Remove once KTIJ-19369 is fixed
+plugins {
+ alias(libs.plugins.androidLibrary)
+ alias(libs.plugins.kotlinAndroid)
+}
+
+android {
+ namespace = "ru.megboyzz.mpcore"
+ compileSdk = 33
+
+ defaultConfig {
+ minSdk = 21
+
+ testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
+ consumerProguardFiles("consumer-rules.pro")
+ externalNativeBuild {
+ cmake {
+ cppFlags("-std=c++17")
+ }
+ }
+ }
+
+ buildTypes {
+ release {
+ isMinifyEnabled = false
+ proguardFiles(
+ getDefaultProguardFile("proguard-android-optimize.txt"),
+ "proguard-rules.pro"
+ )
+ }
+ }
+ externalNativeBuild {
+ cmake {
+ path("src/main/cpp/CMakeLists.txt")
+ version = "3.22.1"
+ }
+ }
+ 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)
+ testImplementation(libs.junit)
+ androidTestImplementation(libs.androidx.test.ext.junit)
+ androidTestImplementation(libs.espresso.core)
+}
\ No newline at end of file
diff --git a/mpcore/consumer-rules.pro b/mpcore/consumer-rules.pro
new file mode 100644
index 0000000..e69de29
diff --git a/mpcore/proguard-rules.pro b/mpcore/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/mpcore/proguard-rules.pro
@@ -0,0 +1,21 @@
+# 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
\ No newline at end of file
diff --git a/mpcore/src/androidTest/java/ru/megboyzz/mpcore/ExampleInstrumentedTest.kt b/mpcore/src/androidTest/java/ru/megboyzz/mpcore/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000..d79a849
--- /dev/null
+++ b/mpcore/src/androidTest/java/ru/megboyzz/mpcore/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package ru.megboyzz.mpcore
+
+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("ru.megboyzz.mpcore.test", appContext.packageName)
+ }
+}
\ No newline at end of file
diff --git a/mpcore/src/main/AndroidManifest.xml b/mpcore/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..a5918e6
--- /dev/null
+++ b/mpcore/src/main/AndroidManifest.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/mpcore/src/main/cpp/CMakeLists.txt b/mpcore/src/main/cpp/CMakeLists.txt
new file mode 100644
index 0000000..f125423
--- /dev/null
+++ b/mpcore/src/main/cpp/CMakeLists.txt
@@ -0,0 +1,10 @@
+cmake_minimum_required(VERSION 3.22.1)
+
+project("mpcore")
+
+add_library(${CMAKE_PROJECT_NAME} SHARED
+ mpcore.cpp)
+
+target_link_libraries(${CMAKE_PROJECT_NAME}
+ android
+ log)
\ No newline at end of file
diff --git a/mpcore/src/main/cpp/mpcore.cpp b/mpcore/src/main/cpp/mpcore.cpp
new file mode 100644
index 0000000..be67627
--- /dev/null
+++ b/mpcore/src/main/cpp/mpcore.cpp
@@ -0,0 +1,10 @@
+#include
+#include
+
+extern "C" JNIEXPORT jstring JNICALL
+Java_ru_megboyzz_mpcore_NativeLib_stringFromJNI(
+ JNIEnv* env,
+ jobject /* this */) {
+ std::string hello = "Hello from C++";
+ return env->NewStringUTF(hello.c_str());
+}
\ No newline at end of file
diff --git a/mpcore/src/main/java/ru/megboyzz/mpcore/NativeLib.kt b/mpcore/src/main/java/ru/megboyzz/mpcore/NativeLib.kt
new file mode 100644
index 0000000..9afb60d
--- /dev/null
+++ b/mpcore/src/main/java/ru/megboyzz/mpcore/NativeLib.kt
@@ -0,0 +1,12 @@
+package ru.megboyzz.mpcore
+
+class NativeLib {
+
+ external fun stringFromJNI(): String
+
+ companion object {
+ init {
+ System.loadLibrary("mpcore")
+ }
+ }
+}
\ No newline at end of file
diff --git a/mpcore/src/test/java/ru/megboyzz/mpcore/ExampleUnitTest.kt b/mpcore/src/test/java/ru/megboyzz/mpcore/ExampleUnitTest.kt
new file mode 100644
index 0000000..7341df8
--- /dev/null
+++ b/mpcore/src/test/java/ru/megboyzz/mpcore/ExampleUnitTest.kt
@@ -0,0 +1,17 @@
+package ru.megboyzz.mpcore
+
+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)
+ }
+}
\ No newline at end of file
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 7b82154..f7ac2d7 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -23,3 +23,4 @@ rootProject.name = "NFS Most Wanted"
include(":app")
include(":devmenu")
include(":devmenu:domain")
+include(":mpcore")