done context menu, and fix controllers in wsa
This commit is contained in:
@@ -5,38 +5,25 @@ import android.app.AlertDialog
|
|||||||
import android.content.DialogInterface
|
import android.content.DialogInterface
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.ActivityInfo
|
import android.content.pm.ActivityInfo
|
||||||
import android.graphics.BitmapFactory
|
|
||||||
import android.hardware.SensorManager
|
import android.hardware.SensorManager
|
||||||
import android.hardware.input.InputManager
|
|
||||||
import android.media.AudioManager
|
import android.media.AudioManager
|
||||||
import android.opengl.GLES20
|
import android.opengl.GLES20
|
||||||
import android.opengl.GLUtils
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.PowerManager
|
import android.os.PowerManager
|
||||||
import android.os.PowerManager.WakeLock
|
import android.os.PowerManager.WakeLock
|
||||||
import android.util.DisplayMetrics
|
import android.util.DisplayMetrics
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.InputDevice
|
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import com.bda.controller.StateEvent
|
|
||||||
import com.ea.EAIO.EAIO
|
import com.ea.EAIO.EAIO
|
||||||
import com.ea.EAMIO.StorageDirectory
|
import com.ea.EAMIO.StorageDirectory
|
||||||
import com.ea.easp.EASPHandler
|
import com.ea.easp.EASPHandler
|
||||||
import com.ea.games.nfs13_na.BuildConfig
|
import com.ea.games.nfs13_na.BuildConfig
|
||||||
import com.ea.games.nfs13_na.R
|
|
||||||
import com.ea.nimble.ApplicationLifecycle
|
import com.ea.nimble.ApplicationLifecycle
|
||||||
import com.megboyzz.actionForAllControllers
|
|
||||||
import com.megboyzz.androidKeyEventToBda
|
|
||||||
import com.megboyzz.androidMotionEventToBda
|
|
||||||
import com.megboyzz.createConnectEvent
|
|
||||||
import com.megboyzz.createDisconnectEvent
|
|
||||||
import com.megboyzz.registerControllerHandlers
|
|
||||||
import java.io.BufferedReader
|
import java.io.BufferedReader
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileReader
|
import java.io.FileReader
|
||||||
@@ -299,23 +286,20 @@ class GameActivity : ComponentActivity(), DrawFrameListener {
|
|||||||
ApplicationLifecycle.onActivityResult(requestCode, resultCode, data, this)
|
ApplicationLifecycle.onActivityResult(requestCode, resultCode, data, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBackPressed() {
|
|
||||||
//ApplicationLifecycle.onBackPressed()
|
|
||||||
}
|
|
||||||
|
|
||||||
public override fun onCreate(bundle: Bundle?) {
|
public override fun onCreate(bundle: Bundle?) {
|
||||||
|
|
||||||
super.onCreate(bundle)
|
super.onCreate(bundle)
|
||||||
|
|
||||||
registerControllerHandlers(
|
MogaController.registerControllerHandlers(
|
||||||
|
context = baseContext,
|
||||||
onInputDeviceAdded = {
|
onInputDeviceAdded = {
|
||||||
Log.i("Controller", "controller is connected!")
|
Log.i("Controller", "controller is connected!")
|
||||||
val event = createConnectEvent(it)
|
val event = MogaController.createConnectEvent(it)
|
||||||
MogaController.nativeOnStateEvent(event)
|
MogaController.nativeOnStateEvent(event)
|
||||||
},
|
},
|
||||||
onInputDeviceRemoved = {
|
onInputDeviceRemoved = {
|
||||||
Log.i("Controller", "controller is disconnected!")
|
Log.i("Controller", "controller is disconnected!")
|
||||||
val event = createDisconnectEvent(it)
|
val event = MogaController.createDisconnectEvent(it)
|
||||||
MogaController.nativeOnStateEvent(event)
|
MogaController.nativeOnStateEvent(event)
|
||||||
},
|
},
|
||||||
onInputDeviceChanged = {
|
onInputDeviceChanged = {
|
||||||
@@ -393,7 +377,8 @@ class GameActivity : ComponentActivity(), DrawFrameListener {
|
|||||||
override fun dispatchGenericMotionEvent(ev: MotionEvent?): Boolean {
|
override fun dispatchGenericMotionEvent(ev: MotionEvent?): Boolean {
|
||||||
Log.i("GameActivity", ev.toString())
|
Log.i("GameActivity", ev.toString())
|
||||||
|
|
||||||
MogaController.onMotionEvent(androidMotionEventToBda(ev!!))
|
if (MogaController.deviceIsController(ev?.deviceId!!))
|
||||||
|
MogaController.onMotionEvent(MogaController.androidMotionEventToBda(ev))
|
||||||
|
|
||||||
return super.dispatchGenericMotionEvent(ev)
|
return super.dispatchGenericMotionEvent(ev)
|
||||||
}
|
}
|
||||||
@@ -401,7 +386,8 @@ class GameActivity : ComponentActivity(), DrawFrameListener {
|
|||||||
@SuppressLint("RestrictedApi")
|
@SuppressLint("RestrictedApi")
|
||||||
override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
|
override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
|
||||||
|
|
||||||
MogaController.onKeyEvent(androidKeyEventToBda(event!!))
|
if (MogaController.deviceIsController(event?.deviceId!!))
|
||||||
|
MogaController.onKeyEvent(MogaController.androidKeyEventToBda(event))
|
||||||
|
|
||||||
return super.dispatchKeyEvent(event)
|
return super.dispatchKeyEvent(event)
|
||||||
}
|
}
|
||||||
@@ -409,8 +395,6 @@ class GameActivity : ComponentActivity(), DrawFrameListener {
|
|||||||
|
|
||||||
|
|
||||||
override fun onDrawFrame(gl10: GL10) {
|
override fun onDrawFrame(gl10: GL10) {
|
||||||
//InputDevice.getDeviceIds()
|
|
||||||
//InputDevice.getDevice(0).sources
|
|
||||||
Log.d(this.localClassName, "onDrawFrame state=$state")
|
Log.d(this.localClassName, "onDrawFrame state=$state")
|
||||||
var isStarted = false
|
var isStarted = false
|
||||||
when (state) {
|
when (state) {
|
||||||
@@ -522,8 +506,8 @@ class GameActivity : ComponentActivity(), DrawFrameListener {
|
|||||||
gameGLSurfaceView.onResume()
|
gameGLSurfaceView.onResume()
|
||||||
ApplicationLifecycle.onActivityResume(this)
|
ApplicationLifecycle.onActivityResume(this)
|
||||||
nativeOnResume()
|
nativeOnResume()
|
||||||
actionForAllControllers {
|
MogaController.doForAllControllers {
|
||||||
val event = createConnectEvent(it)
|
val event = MogaController.createConnectEvent(it)
|
||||||
MogaController.nativeOnStateEvent(event)
|
MogaController.nativeOnStateEvent(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
package com.ea.ironmonkey
|
package com.ea.ironmonkey
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.hardware.input.InputManager
|
||||||
|
import android.util.Log
|
||||||
|
import android.view.InputDevice
|
||||||
|
import androidx.activity.ComponentActivity
|
||||||
import com.bda.controller.ControllerListener
|
import com.bda.controller.ControllerListener
|
||||||
import com.bda.controller.KeyEvent
|
import com.bda.controller.KeyEvent
|
||||||
import com.bda.controller.MotionEvent
|
import com.bda.controller.MotionEvent
|
||||||
@@ -19,4 +24,94 @@ object MogaController : ControllerListener {
|
|||||||
override fun onStateEvent(stateEvent: StateEvent) {
|
override fun onStateEvent(stateEvent: StateEvent) {
|
||||||
nativeOnStateEvent(stateEvent)
|
nativeOnStateEvent(stateEvent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun doForAllControllers(
|
||||||
|
action: (Int) -> Unit
|
||||||
|
){
|
||||||
|
val deviceIds = InputDevice.getDeviceIds()
|
||||||
|
|
||||||
|
deviceIds.forEach {
|
||||||
|
if(deviceIsController(it)) action(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
infix fun Int.isFlag(flag: Int) = this and flag == flag
|
||||||
|
|
||||||
|
fun deviceIsController(deviceId: Int): Boolean {
|
||||||
|
val inputDevice = InputDevice.getDevice(deviceId) ?: return false
|
||||||
|
Log.i("Controller", inputDevice.toString())
|
||||||
|
|
||||||
|
val b = (inputDevice.sources isFlag InputDevice.SOURCE_GAMEPAD) &&
|
||||||
|
(inputDevice.sources isFlag InputDevice.SOURCE_JOYSTICK)
|
||||||
|
|
||||||
|
Log.i("Controller", b.toString())
|
||||||
|
|
||||||
|
if(inputDevice.id == -1) return false
|
||||||
|
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
fun registerControllerHandlers(
|
||||||
|
context: Context,
|
||||||
|
onInputDeviceAdded: (Int) -> Unit,
|
||||||
|
onInputDeviceRemoved: (Int) -> Unit,
|
||||||
|
onInputDeviceChanged: (Int) -> Unit = {},
|
||||||
|
){
|
||||||
|
|
||||||
|
val inputManager = context.getSystemService(ComponentActivity.INPUT_SERVICE) as InputManager
|
||||||
|
|
||||||
|
inputManager.registerInputDeviceListener(object : InputManager.InputDeviceListener {
|
||||||
|
|
||||||
|
var lastControllerId: Int = 0;
|
||||||
|
|
||||||
|
override fun onInputDeviceAdded(deviceId: Int) {
|
||||||
|
if(deviceIsController(deviceId)) {
|
||||||
|
lastControllerId = deviceId
|
||||||
|
onInputDeviceAdded(deviceId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onInputDeviceRemoved(deviceId: Int) {
|
||||||
|
|
||||||
|
if(deviceIsController(deviceId) || lastControllerId == deviceId) onInputDeviceRemoved(deviceId)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onInputDeviceChanged(deviceId: Int) {
|
||||||
|
if(deviceIsController(deviceId)) onInputDeviceChanged(deviceId)
|
||||||
|
}
|
||||||
|
}, null)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createDisconnectEvent(deviceId: Int) = StateEvent(
|
||||||
|
System.currentTimeMillis(),
|
||||||
|
deviceId,
|
||||||
|
StateEvent.STATE_UNKNOWN,
|
||||||
|
StateEvent.ACTION_DISCONNECTED
|
||||||
|
)
|
||||||
|
|
||||||
|
fun createConnectEvent(deviceId: Int) = StateEvent(
|
||||||
|
System.currentTimeMillis(),
|
||||||
|
deviceId,
|
||||||
|
StateEvent.STATE_CONNECTION,
|
||||||
|
StateEvent.ACTION_CONNECTED
|
||||||
|
)
|
||||||
|
|
||||||
|
fun androidKeyEventToBda(keyEvent: android.view.KeyEvent) = KeyEvent(
|
||||||
|
keyEvent.eventTime,
|
||||||
|
keyEvent.deviceId,
|
||||||
|
keyEvent.keyCode,
|
||||||
|
keyEvent.action
|
||||||
|
)
|
||||||
|
|
||||||
|
fun androidMotionEventToBda(motionEvent: android.view.MotionEvent) = MotionEvent(
|
||||||
|
motionEvent.eventTime,
|
||||||
|
motionEvent.deviceId,
|
||||||
|
motionEvent.x,
|
||||||
|
motionEvent.y,
|
||||||
|
motionEvent.rawX,
|
||||||
|
motionEvent.rawY,
|
||||||
|
motionEvent.xPrecision,
|
||||||
|
motionEvent.yPrecision
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,91 +0,0 @@
|
|||||||
package com.megboyzz
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.hardware.input.InputManager
|
|
||||||
import android.view.InputDevice
|
|
||||||
import androidx.activity.ComponentActivity
|
|
||||||
import com.bda.controller.KeyEvent
|
|
||||||
import com.bda.controller.MotionEvent
|
|
||||||
import android.view.KeyEvent as androidKeyEvent
|
|
||||||
import android.view.MotionEvent as androidMotionEvent
|
|
||||||
import com.bda.controller.StateEvent
|
|
||||||
|
|
||||||
|
|
||||||
fun actionForAllControllers(
|
|
||||||
action: (Int) -> Unit
|
|
||||||
){
|
|
||||||
val deviceIds = InputDevice.getDeviceIds()
|
|
||||||
deviceIds.forEach {
|
|
||||||
if(deviceIsController(it)) action(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deviceIsController(deviceId: Int): Boolean {
|
|
||||||
val inputDevice = InputDevice.getDevice(deviceId) ?: return false
|
|
||||||
|
|
||||||
return (inputDevice.sources and InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD ||
|
|
||||||
(inputDevice.sources and InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_JOYSTICK
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Context.registerControllerHandlers(
|
|
||||||
onInputDeviceAdded: (Int) -> Unit,
|
|
||||||
onInputDeviceRemoved: (Int) -> Unit,
|
|
||||||
onInputDeviceChanged: (Int) -> Unit = {},
|
|
||||||
){
|
|
||||||
|
|
||||||
val inputManager = getSystemService(ComponentActivity.INPUT_SERVICE) as InputManager
|
|
||||||
|
|
||||||
inputManager.registerInputDeviceListener(object : InputManager.InputDeviceListener {
|
|
||||||
|
|
||||||
var lastControllerId: Int = 0;
|
|
||||||
|
|
||||||
override fun onInputDeviceAdded(deviceId: Int) {
|
|
||||||
if(deviceIsController(deviceId)) {
|
|
||||||
lastControllerId = deviceId
|
|
||||||
onInputDeviceAdded(deviceId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onInputDeviceRemoved(deviceId: Int) {
|
|
||||||
|
|
||||||
if(deviceIsController(deviceId) || lastControllerId == deviceId) onInputDeviceRemoved(deviceId)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onInputDeviceChanged(deviceId: Int) {
|
|
||||||
if(deviceIsController(deviceId)) onInputDeviceChanged(deviceId)
|
|
||||||
}
|
|
||||||
}, null)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun createDisconnectEvent(deviceId: Int) = StateEvent(
|
|
||||||
System.currentTimeMillis(),
|
|
||||||
deviceId,
|
|
||||||
StateEvent.STATE_UNKNOWN,
|
|
||||||
StateEvent.ACTION_DISCONNECTED
|
|
||||||
)
|
|
||||||
|
|
||||||
fun createConnectEvent(deviceId: Int) = StateEvent(
|
|
||||||
System.currentTimeMillis(),
|
|
||||||
deviceId,
|
|
||||||
StateEvent.STATE_CONNECTION,
|
|
||||||
StateEvent.ACTION_CONNECTED
|
|
||||||
)
|
|
||||||
|
|
||||||
fun androidKeyEventToBda(keyEvent: androidKeyEvent) = KeyEvent(
|
|
||||||
keyEvent.eventTime,
|
|
||||||
keyEvent.deviceId,
|
|
||||||
keyEvent.keyCode,
|
|
||||||
keyEvent.action
|
|
||||||
)
|
|
||||||
|
|
||||||
fun androidMotionEventToBda(motionEvent: androidMotionEvent) = MotionEvent(
|
|
||||||
motionEvent.eventTime,
|
|
||||||
motionEvent.deviceId,
|
|
||||||
motionEvent.x,
|
|
||||||
motionEvent.y,
|
|
||||||
motionEvent.rawX,
|
|
||||||
motionEvent.rawY,
|
|
||||||
motionEvent.xPrecision,
|
|
||||||
motionEvent.yPrecision
|
|
||||||
)
|
|
||||||
@@ -71,6 +71,11 @@ dependencies {
|
|||||||
debugImplementation(libs.ui.tooling)
|
debugImplementation(libs.ui.tooling)
|
||||||
debugImplementation(libs.ui.test.manifest)
|
debugImplementation(libs.ui.test.manifest)
|
||||||
|
|
||||||
|
implementation(libs.voyager.navigator)
|
||||||
|
implementation(libs.voyager.bottomSheetNavigator)
|
||||||
|
implementation(libs.voyager.transitions)
|
||||||
|
implementation(libs.voyager.screenModel)
|
||||||
|
|
||||||
implementation(libs.dagger)
|
implementation(libs.dagger)
|
||||||
kapt(libs.dagger.compiler)
|
kapt(libs.dagger.compiler)
|
||||||
implementation(libs.room)
|
implementation(libs.room)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import android.content.Intent
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
|
import cafe.adriel.voyager.navigator.bottomSheet.BottomSheetNavigator
|
||||||
import com.megboyzz.devmenu.ui.components.MainScaffold
|
import com.megboyzz.devmenu.ui.components.MainScaffold
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : ComponentActivity() {
|
||||||
@@ -30,6 +31,11 @@ class MainActivity : ComponentActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
|
|
||||||
|
BottomSheetNavigator {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
MainScaffold(
|
MainScaffold(
|
||||||
onSettingsClick = { /*TODO*/ },
|
onSettingsClick = { /*TODO*/ },
|
||||||
onSearchValueChanged = {},
|
onSearchValueChanged = {},
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
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.ui.Alignment
|
||||||
|
|
||||||
|
val enter = expandIn(
|
||||||
|
expandFrom = Alignment.CenterStart,
|
||||||
|
animationSpec = tween(250)
|
||||||
|
)
|
||||||
|
|
||||||
|
val exit = shrinkOut(
|
||||||
|
shrinkTowards = Alignment.CenterStart,
|
||||||
|
animationSpec = tween(250)
|
||||||
|
)
|
||||||
@@ -1,26 +1,20 @@
|
|||||||
package com.megboyzz.devmenu.ui.components
|
package com.megboyzz.devmenu.ui.components
|
||||||
|
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.BoxScope
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.ColumnScope
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.RowScope
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.layout.wrapContentHeight
|
import androidx.compose.foundation.layout.wrapContentHeight
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
|
||||||
import androidx.compose.material.icons.filled.KeyboardArrowRight
|
|
||||||
import androidx.compose.material.icons.outlined.Star
|
|
||||||
import androidx.compose.material3.Button
|
import androidx.compose.material3.Button
|
||||||
import androidx.compose.material3.Divider
|
import androidx.compose.material3.Divider
|
||||||
import androidx.compose.material3.Icon
|
|
||||||
import androidx.compose.material3.OutlinedTextField
|
|
||||||
import androidx.compose.material3.Surface
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
@@ -33,7 +27,6 @@ import androidx.compose.ui.draw.clip
|
|||||||
import androidx.compose.ui.draw.shadow
|
import androidx.compose.ui.draw.shadow
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.painter.Painter
|
import androidx.compose.ui.graphics.painter.Painter
|
||||||
import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.megboyzz.devmenu.R
|
import com.megboyzz.devmenu.R
|
||||||
@@ -68,7 +61,7 @@ fun CoreMenuPosition(
|
|||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
horizontalArrangement = Arrangement.spacedBy(20.dp),
|
||||||
) {
|
) {
|
||||||
Image(
|
Image(
|
||||||
painter = icon,
|
painter = icon,
|
||||||
@@ -87,11 +80,11 @@ fun FsElementInContextMenu(
|
|||||||
|
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
horizontalArrangement = Arrangement.spacedBy(20.dp)
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val modifier = Modifier
|
val modifier = Modifier
|
||||||
.size(32.dp)
|
.size(36.dp)
|
||||||
.clip(RoundedCornerShape(10.dp))
|
.clip(RoundedCornerShape(10.dp))
|
||||||
.shadow(elevation = 6.dp)
|
.shadow(elevation = 6.dp)
|
||||||
|
|
||||||
@@ -108,55 +101,92 @@ fun FileContextMenu(
|
|||||||
name: String,
|
name: String,
|
||||||
type: ElementType,
|
type: ElementType,
|
||||||
onRemoveElement: () -> Unit,
|
onRemoveElement: () -> Unit,
|
||||||
onUpdateType: (ElementType) -> Unit
|
onUpdateType: (ElementType) -> ElementType?
|
||||||
) {
|
) {
|
||||||
|
|
||||||
var innerType by remember { mutableStateOf(type) }
|
var innerType by remember { mutableStateOf(type) }
|
||||||
var isMain by remember { mutableStateOf(true) }
|
var isMain by remember { mutableStateOf(true) }
|
||||||
|
|
||||||
|
|
||||||
CoreFileContextMenu {
|
CoreFileContextMenu {
|
||||||
Column(verticalArrangement = Arrangement.spacedBy(20.dp)) {
|
FsElementInContextMenu(name = name, type = type)
|
||||||
FsElementInContextMenu(name = name, type = type)
|
Divider()
|
||||||
Divider()
|
AnimatedBoxForContextMenuContent(isVisible = isMain){
|
||||||
if (isMain) {
|
AnimatedBoxForContextMenuContent(isVisible = innerType == ElementType.isFile) {
|
||||||
ClickableMenuPosition(
|
ClickableMenuPosition(
|
||||||
name = "Заменить",
|
name = "Заменить",
|
||||||
icon = R.drawable.star.asPainter(),
|
icon = R.drawable.star.asPainter(),
|
||||||
onClick = {
|
onClick = {
|
||||||
innerType = ElementType.isReplaced
|
innerType = onUpdateType(ElementType.isReplaced) ?: ElementType.isReplaced
|
||||||
onUpdateType(innerType)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
ClickableMenuPosition(
|
ClickableMenuPosition(
|
||||||
name = "Скрыть для игры",
|
name = "Скрыть для игры",
|
||||||
icon = R.drawable.hide.asPainter(),
|
icon = R.drawable.hide.asPainter(),
|
||||||
onClick = {
|
onClick = {
|
||||||
innerType = ElementType.isHidden
|
innerType = onUpdateType(ElementType.isHidden) ?: ElementType.isHidden
|
||||||
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
AnimatedBoxForContextMenuContent(isVisible = innerType == ElementType.isHidden) {
|
||||||
ClickableMenuPosition(
|
ClickableMenuPosition(
|
||||||
name = "Свойства",
|
name = "Показать игре",
|
||||||
icon = R.drawable.info.asPainter(),
|
icon = R.drawable.unhide.asPainter(),
|
||||||
onClick = {}
|
onClick = {
|
||||||
)
|
innerType = onUpdateType(ElementType.isFile) ?: ElementType.isFile
|
||||||
ClickableMenuPosition(
|
}
|
||||||
name = "Удалить",
|
|
||||||
icon = R.drawable.trash.asPainter(),
|
|
||||||
onClick = { isMain = !isMain }
|
|
||||||
)
|
|
||||||
}else{
|
|
||||||
ClickableMenuPosition(
|
|
||||||
name = "Удалить",
|
|
||||||
icon = R.drawable.trash.asPainter(),
|
|
||||||
withEnd = false
|
|
||||||
)
|
|
||||||
RemoveFileButtonsGroup(
|
|
||||||
onDelete = onRemoveElement,
|
|
||||||
onCancel = { isMain =! isMain }
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
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 = {}
|
||||||
|
)
|
||||||
|
ClickableMenuPosition(
|
||||||
|
name = "Удалить",
|
||||||
|
icon = R.drawable.trash.asPainter(),
|
||||||
|
onClick = { isMain = !isMain }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AnimatedBoxForContextMenuContent(isVisible = !isMain) {
|
||||||
|
ClickableMenuPosition(
|
||||||
|
name = "Удалить",
|
||||||
|
icon = R.drawable.trash.asPainter(),
|
||||||
|
withEnd = false
|
||||||
|
)
|
||||||
|
RemoveFileButtonsGroup(
|
||||||
|
onDelete = onRemoveElement,
|
||||||
|
onCancel = { isMain = !isMain }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun AnimatedBoxForContextMenuContent(
|
||||||
|
isVisible: Boolean,
|
||||||
|
content: @Composable ColumnScope.() -> Unit
|
||||||
|
) {
|
||||||
|
AnimatedVisibility(
|
||||||
|
visible = isVisible,
|
||||||
|
enter = enter,
|
||||||
|
exit = exit
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||||
|
content = content
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,31 +204,6 @@ fun RemoveFileButtonsGroup(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview
|
|
||||||
@Composable
|
|
||||||
fun TwoButtonsRow() {
|
|
||||||
Surface(
|
|
||||||
modifier = Modifier.fillMaxWidth()
|
|
||||||
) {
|
|
||||||
Row(
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
) {
|
|
||||||
Button(
|
|
||||||
onClick = { /* Действие для первой кнопки */ },
|
|
||||||
modifier = Modifier.weight(1f) // Каждая кнопка занимает равное количество места (50%)
|
|
||||||
) {
|
|
||||||
// Ваш текст и стиль для первой кнопки
|
|
||||||
}
|
|
||||||
|
|
||||||
Button(
|
|
||||||
onClick = { /* Действие для второй кнопки */ },
|
|
||||||
modifier = Modifier.weight(1f) // Каждая кнопка занимает равное количество места (50%)
|
|
||||||
) {
|
|
||||||
// Ваш текст и стиль для второй кнопки
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RemoveButton(
|
fun RemoveButton(
|
||||||
@@ -206,38 +211,46 @@ fun RemoveButton(
|
|||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
onClick: () -> Unit
|
onClick: () -> Unit
|
||||||
) {
|
) {
|
||||||
Row() {
|
Button(
|
||||||
Button(
|
onClick = onClick,
|
||||||
onClick = onClick,
|
shape = RoundedCornerShape(10.dp),
|
||||||
shape = RoundedCornerShape(10.dp),
|
modifier = modifier
|
||||||
modifier = modifier
|
) {
|
||||||
) {
|
Text(text = text)
|
||||||
Text(text = text)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CoreFileContextMenu(
|
fun CoreFileContextMenu(
|
||||||
content: @Composable BoxScope.() -> Unit
|
content: @Composable () -> Unit
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
val shape = RoundedCornerShape(topStart = 10.dp, topEnd = 10.dp)
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.wrapContentHeight()
|
.wrapContentHeight()
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
//TODO отвязать от цвета
|
//TODO отвязать от цвета
|
||||||
.background(Color.White)
|
.clip(shape)
|
||||||
.clip(RoundedCornerShape(10.dp)),
|
.background(Color.White),
|
||||||
contentAlignment = Alignment.TopCenter
|
contentAlignment = Alignment.TopCenter
|
||||||
) {
|
) {
|
||||||
|
Image(
|
||||||
|
painter = R.drawable.clip.asPainter(),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.padding(top = 8.dp)
|
||||||
|
)
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.padding(
|
modifier = Modifier.padding(
|
||||||
horizontal = 32.dp,
|
horizontal = 28.dp,
|
||||||
vertical = 24.dp
|
vertical = 32.dp
|
||||||
),
|
),
|
||||||
content = content
|
){
|
||||||
)
|
Column(verticalArrangement = Arrangement.spacedBy(20.dp)) {
|
||||||
|
content()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,7 +263,7 @@ fun ClicablePreview() {
|
|||||||
name = "my_file.txt",
|
name = "my_file.txt",
|
||||||
type = ElementType.isFile,
|
type = ElementType.isFile,
|
||||||
onRemoveElement = {},
|
onRemoveElement = {},
|
||||||
onUpdateType = {}
|
onUpdateType = {null}
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -44,10 +44,10 @@ fun FsElementIcon(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
val painter = when(type){
|
val painter = when(type){
|
||||||
ElementType.isHidden -> R.drawable.icon_hidden_file.asPainter()
|
ElementType.isHidden -> R.drawable.icon_hidden_file.asPainter()
|
||||||
ElementType.isFile -> R.drawable.icon_file.asPainter()
|
ElementType.isFile -> R.drawable.icon_file.asPainter()
|
||||||
ElementType.isDir -> R.drawable.icon_folder.asPainter()
|
ElementType.isDir -> R.drawable.icon_folder.asPainter()
|
||||||
ElementType.isReplaced -> R.drawable.icon_replaced_file.asPainter()
|
ElementType.isReplaced -> R.drawable.icon_replaced_file.asPainter()
|
||||||
}
|
}
|
||||||
|
|
||||||
Image(painter = painter, contentDescription = null, modifier)
|
Image(painter = painter, contentDescription = null, modifier)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ org-jetbrains-kotlin-jvm = "1.9.0"
|
|||||||
ksp = "1.9.21-1.0.15"
|
ksp = "1.9.21-1.0.15"
|
||||||
dagger = "2.46.1"
|
dagger = "2.46.1"
|
||||||
room = "2.6.1"
|
room = "2.6.1"
|
||||||
|
voyager = "1.0.0"
|
||||||
|
|
||||||
[libraries]
|
[libraries]
|
||||||
core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" }
|
core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "core-ktx" }
|
||||||
@@ -40,6 +41,11 @@ room = { module = "androidx.room:room-runtime", version.ref = "room" }
|
|||||||
room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
|
room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }
|
||||||
room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" }
|
room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" }
|
||||||
|
|
||||||
|
voyager-navigator = { module = "cafe.adriel.voyager:voyager-navigator", version.ref = "voyager" }
|
||||||
|
voyager-screenModel = { module = "cafe.adriel.voyager:voyager-screenmodel", version.ref = "voyager" }
|
||||||
|
voyager-bottomSheetNavigator = { module = "cafe.adriel.voyager:voyager-bottom-sheet-navigator", version.ref = "voyager" }
|
||||||
|
voyager-transitions = { module = "cafe.adriel.voyager:voyager-transitions", version.ref = "voyager" }
|
||||||
|
|
||||||
[plugins]
|
[plugins]
|
||||||
androidApplication = { id = "com.android.application", version.ref = "agp" }
|
androidApplication = { id = "com.android.application", version.ref = "agp" }
|
||||||
kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
kotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
||||||
|
|||||||
Reference in New Issue
Block a user