mirror of
https://github.com/KDE/kdeconnect-android
synced 2025-08-31 06:05:12 +00:00
Update Presenter activity to use Compose
The Presenter activity including its layout file and related Java class were replaced with Compose UI. Additionally, the androidx.compose.material3:material3 was updated from version 1.1.0 to version 1.1.1.
This commit is contained in:
committed by
Albert Vaca Cintora
parent
ad83f76ad1
commit
c5c780b5ce
@@ -1,81 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2023 Albert Vaca Cintora <albertvaka@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
-->
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context="org.kde.kdeconnect.Plugins.PresenterPlugin.PresenterActivity">
|
||||
|
||||
<include layout="@layout/toolbar" android:id="@+id/toolbar_layout" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/mpris_control_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="12dp"
|
||||
android:orientation="vertical"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<TextView
|
||||
style="@android:style/TextAppearance.Medium"
|
||||
android:id="@+id/textView"
|
||||
android:layout_weight="0"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/presenter_lock_tip" />
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:orientation="horizontal"
|
||||
android:layout_weight="1">
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/previous_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:contentDescription="@string/mpris_rew"
|
||||
android:layout_weight="0.25"
|
||||
android:layout_marginEnd="3dp"
|
||||
app:icon="@drawable/ic_previous_black"
|
||||
style="@style/KdeConnectButton.IconButton" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/next_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:layout_marginStart="3dp"
|
||||
android:layout_weight="0.25"
|
||||
android:contentDescription="@string/mpris_ff"
|
||||
app:icon="@drawable/ic_next_black"
|
||||
style="@style/KdeConnectButton.IconButton" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/pointer_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_marginBottom="6dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0.30"
|
||||
android:visibility="gone"
|
||||
android:text="@string/presenter_pointer"
|
||||
style="@style/KdeConnectButton.IconButton.Secondary"
|
||||
tools:visibility="visible" />
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
@@ -1,18 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2023 Albert Vaca Cintora <albertvaka@gmail.com>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
-->
|
||||
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
android:id="@+id/fullscreen"
|
||||
android:title="@string/presenter_fullscreen" />
|
||||
|
||||
<item
|
||||
android:id="@+id/exit_presentation"
|
||||
android:title="@string/presenter_exit" />
|
||||
</menu>
|
@@ -15,9 +15,7 @@ import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.Send
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@@ -74,10 +72,10 @@ class ComposeSendActivity : AppCompatActivity() {
|
||||
}
|
||||
val plugin = KdeConnect.getInstance().getDevicePlugin(deviceId, MousePadPlugin::class.java)
|
||||
if (plugin == null) {
|
||||
finish();
|
||||
return;
|
||||
finish()
|
||||
return
|
||||
}
|
||||
plugin.sendKeyboardPacket(np);
|
||||
plugin.sendKeyboardPacket(np)
|
||||
}
|
||||
|
||||
private fun sendComposed() {
|
||||
@@ -89,7 +87,6 @@ class ComposeSendActivity : AppCompatActivity() {
|
||||
userInput.value = String()
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun ComposeSendScreen() {
|
||||
Mdc3Theme {
|
||||
@@ -97,7 +94,6 @@ class ComposeSendActivity : AppCompatActivity() {
|
||||
topBar = {
|
||||
KdeTopAppBar(
|
||||
title = stringResource(R.string.compose_send_title),
|
||||
navIcon = Icons.Default.ArrowBack,
|
||||
navIconOnClick = { onBackPressedDispatcher.onBackPressed() },
|
||||
actions = {
|
||||
KdeTextButton(
|
||||
|
@@ -1,185 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2014 Ahmed I. Khalil <ahmedibrahimkhali@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.Plugins.PresenterPlugin;
|
||||
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.PowerManager;
|
||||
import android.support.v4.media.session.MediaSessionCompat;
|
||||
import android.support.v4.media.session.PlaybackStateCompat;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.media.VolumeProviderCompat;
|
||||
|
||||
import org.kde.kdeconnect.KdeConnect;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
import org.kde.kdeconnect_tp.databinding.ActivityPresenterBinding;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class PresenterActivity extends AppCompatActivity implements SensorEventListener {
|
||||
private ActivityPresenterBinding binding;
|
||||
|
||||
private MediaSessionCompat mMediaSession;
|
||||
|
||||
private PresenterPlugin plugin;
|
||||
|
||||
private SensorManager sensorManager;
|
||||
|
||||
static final float SENSITIVITY = 0.03f; //TODO: Make configurable?
|
||||
|
||||
public void gyroscopeEvent(SensorEvent event) {
|
||||
float xPos = -event.values[2] * SENSITIVITY;
|
||||
float yPos = -event.values[0] * SENSITIVITY;
|
||||
|
||||
plugin.sendPointer(xPos, yPos);
|
||||
}
|
||||
|
||||
public void onSensorChanged(SensorEvent event) {
|
||||
if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE) {
|
||||
gyroscopeEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||
//Ignored
|
||||
}
|
||||
|
||||
void enablePointer() {
|
||||
if (sensorManager != null) {
|
||||
return; //Already enabled
|
||||
}
|
||||
sensorManager = ContextCompat.getSystemService(this, SensorManager.class);
|
||||
binding.pointerButton.setVisibility(View.VISIBLE);
|
||||
binding.pointerButton.setOnTouchListener((v, event) -> {
|
||||
if(event.getAction() == MotionEvent.ACTION_DOWN){
|
||||
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE), SensorManager.SENSOR_DELAY_GAME);
|
||||
v.performClick(); // The linter complains if this is not called
|
||||
}
|
||||
else if (event.getAction() == MotionEvent.ACTION_UP) {
|
||||
sensorManager.unregisterListener(this);
|
||||
plugin.stopPointer();
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
binding = ActivityPresenterBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
|
||||
setSupportActionBar(binding.toolbarLayout.toolbar);
|
||||
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setDisplayShowHomeEnabled(true);
|
||||
|
||||
String deviceId = getIntent().getStringExtra("deviceId");
|
||||
this.plugin = KdeConnect.getInstance().getDevicePlugin(deviceId, PresenterPlugin.class);
|
||||
|
||||
binding.nextButton.setOnClickListener(v -> plugin.sendNext());
|
||||
binding.previousButton.setOnClickListener(v -> plugin.sendPrevious());
|
||||
if (plugin.isPointerSupported()) {
|
||||
enablePointer();
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.menu_presenter, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
if (id == R.id.fullscreen) {
|
||||
plugin.sendFullscreen();
|
||||
return true;
|
||||
} else if (id == R.id.exit_presentation) {
|
||||
plugin.sendEsc();
|
||||
return true;
|
||||
} else {
|
||||
return super.onContextItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
if (mMediaSession != null) {
|
||||
mMediaSession.setActive(true);
|
||||
return;
|
||||
}
|
||||
createMediaSession();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
|
||||
if (sensorManager != null) {
|
||||
// Make sure we don't leave the listener on
|
||||
sensorManager.unregisterListener(this);
|
||||
}
|
||||
|
||||
if (mMediaSession != null) {
|
||||
PowerManager pm = ContextCompat.getSystemService(this, PowerManager.class);
|
||||
boolean screenOn = pm.isInteractive();
|
||||
if (screenOn) {
|
||||
mMediaSession.release();
|
||||
} // else we are in the lockscreen, keep the mediasession
|
||||
}
|
||||
}
|
||||
|
||||
private void createMediaSession() {
|
||||
mMediaSession = new MediaSessionCompat(this, "kdeconnect");
|
||||
|
||||
// Deprecated flags not required in Build.VERSION_CODES.O and later
|
||||
mMediaSession.setFlags(MediaSessionCompat.FLAG_HANDLES_MEDIA_BUTTONS |
|
||||
MediaSessionCompat.FLAG_HANDLES_TRANSPORT_CONTROLS);
|
||||
mMediaSession.setPlaybackState(new PlaybackStateCompat.Builder()
|
||||
.setState(PlaybackStateCompat.STATE_PLAYING, 0, 0)
|
||||
.build());
|
||||
mMediaSession.setPlaybackToRemote(getVolumeProvider());
|
||||
mMediaSession.setActive(true);
|
||||
}
|
||||
|
||||
private VolumeProviderCompat getVolumeProvider() {
|
||||
final int VOLUME_UP = 1;
|
||||
final int VOLUME_DOWN = -1;
|
||||
return new VolumeProviderCompat(VolumeProviderCompat.VOLUME_CONTROL_RELATIVE, 1, 0) {
|
||||
@Override
|
||||
public void onAdjustVolume(int direction) {
|
||||
if (direction == VOLUME_UP) {
|
||||
plugin.sendNext();
|
||||
}
|
||||
else if (direction == VOLUME_DOWN) {
|
||||
plugin.sendPrevious();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onSupportNavigateUp() {
|
||||
super.onBackPressed();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Dmitry Yudin <dgyudin@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
package org.kde.kdeconnect.Plugins.PresenterPlugin
|
||||
|
||||
import android.hardware.Sensor
|
||||
import android.hardware.SensorEvent
|
||||
import android.hardware.SensorEventListener
|
||||
import android.hardware.SensorManager
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.PowerManager
|
||||
import android.support.v4.media.session.MediaSessionCompat
|
||||
import android.support.v4.media.session.PlaybackStateCompat
|
||||
import android.view.MotionEvent
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.ArrowForward
|
||||
import androidx.compose.material.icons.filled.MoreVert
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.pointer.pointerInteropFilter
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.media.VolumeProviderCompat
|
||||
import com.google.accompanist.themeadapter.material3.Mdc3Theme
|
||||
import org.kde.kdeconnect.KdeConnect
|
||||
import org.kde.kdeconnect.UserInterface.compose.KdeButton
|
||||
import org.kde.kdeconnect.UserInterface.compose.KdeTopAppBar
|
||||
import org.kde.kdeconnect_tp.R
|
||||
|
||||
private const val VOLUME_UP = 1
|
||||
private const val VOLUME_DOWN = -1
|
||||
|
||||
class PresenterActivity : AppCompatActivity(), SensorEventListener {
|
||||
|
||||
private val offScreenControlsSupported = Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU
|
||||
private val mediaSession by lazy {
|
||||
if (offScreenControlsSupported) MediaSessionCompat(this, "kdeconnect") else null
|
||||
}
|
||||
private val powerManager by lazy { getSystemService(POWER_SERVICE) as PowerManager }
|
||||
private val plugin: PresenterPlugin by lazy {
|
||||
KdeConnect.getInstance().getDevicePlugin(intent.getStringExtra("deviceId"), PresenterPlugin::class.java)
|
||||
}
|
||||
|
||||
//TODO: make configurable
|
||||
private val sensitivity = 0.03f
|
||||
override fun onSensorChanged(event: SensorEvent?) {
|
||||
if (event?.sensor?.type == Sensor.TYPE_GYROSCOPE) {
|
||||
val xPos = -event.values[2] * sensitivity
|
||||
val yPos = -event.values[0] * sensitivity
|
||||
|
||||
plugin.sendPointer(xPos, yPos)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) {
|
||||
//ignored
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContent { PresenterScreen() }
|
||||
createMediaSession()
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
mediaSession?.setActive(false)
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
//fixme watch for isInteractive in background
|
||||
mediaSession?.setActive(!powerManager.isInteractive)
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
mediaSession?.release()
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
private fun createMediaSession() {
|
||||
mediaSession?.setPlaybackState(
|
||||
PlaybackStateCompat.Builder().setState(PlaybackStateCompat.STATE_PLAYING, 0, 0f).build()
|
||||
)
|
||||
mediaSession?.setPlaybackToRemote(volumeProvider)
|
||||
|
||||
}
|
||||
|
||||
private val volumeProvider = object : VolumeProviderCompat(VOLUME_CONTROL_RELATIVE, 1, 0) {
|
||||
override fun onAdjustVolume(direction: Int) {
|
||||
if (direction == VOLUME_UP) {
|
||||
plugin.sendNext()
|
||||
} else if (direction == VOLUME_DOWN) {
|
||||
plugin.sendPrevious()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalComposeUiApi::class)
|
||||
@Preview
|
||||
@Composable
|
||||
private fun PresenterScreen() {
|
||||
|
||||
val sensorManager = LocalContext.current.getSystemService(SENSOR_SERVICE) as? SensorManager
|
||||
|
||||
Mdc3Theme {
|
||||
Scaffold(topBar = { PresenterAppBar() }) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize().padding(it).padding(16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(20.dp),
|
||||
) {
|
||||
if (offScreenControlsSupported) Text(
|
||||
text = stringResource(R.string.presenter_lock_tip),
|
||||
modifier = Modifier.padding(bottom = 8.dp).padding(horizontal = 16.dp),
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier.fillMaxSize().weight(3f),
|
||||
horizontalArrangement = Arrangement.spacedBy(20.dp),
|
||||
) {
|
||||
KdeButton(
|
||||
onClick = { plugin.sendPrevious() },
|
||||
modifier = Modifier.fillMaxSize().weight(1f),
|
||||
icon = Icons.Default.ArrowBack,
|
||||
)
|
||||
KdeButton(
|
||||
onClick = { plugin.sendNext() },
|
||||
modifier = Modifier.fillMaxSize().weight(1f),
|
||||
icon = Icons.Default.ArrowForward,
|
||||
)
|
||||
}
|
||||
if (sensorManager != null) KdeButton(
|
||||
onClick = {},
|
||||
colors = ButtonDefaults.filledTonalButtonColors(),
|
||||
modifier = Modifier.fillMaxSize().weight(1f).pointerInteropFilter { event ->
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
sensorManager.registerListener(
|
||||
this@PresenterActivity,
|
||||
sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE),
|
||||
SensorManager.SENSOR_DELAY_GAME
|
||||
)
|
||||
}
|
||||
|
||||
MotionEvent.ACTION_UP -> {
|
||||
sensorManager.unregisterListener(this@PresenterActivity)
|
||||
plugin.stopPointer()
|
||||
false
|
||||
}
|
||||
|
||||
else -> false
|
||||
}
|
||||
},
|
||||
text = stringResource(R.string.presenter_pointer),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun PresenterAppBar() {
|
||||
|
||||
var dropdownShownState by remember { mutableStateOf(false) }
|
||||
|
||||
KdeTopAppBar(navIconOnClick = { onBackPressedDispatcher.onBackPressed() }, actions = {
|
||||
IconButton(onClick = { dropdownShownState = true }) {
|
||||
Icon(Icons.Default.MoreVert, stringResource(R.string.extra_options))
|
||||
}
|
||||
DropdownMenu(expanded = dropdownShownState, onDismissRequest = { dropdownShownState = false }) {
|
||||
DropdownMenuItem(
|
||||
onClick = { plugin.sendFullscreen() },
|
||||
text = { Text(stringResource(R.string.presenter_fullscreen)) },
|
||||
)
|
||||
DropdownMenuItem(
|
||||
onClick = { plugin.sendEsc() },
|
||||
text = { Text(stringResource(R.string.presenter_exit)) },
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@@ -9,12 +9,16 @@ package org.kde.kdeconnect.UserInterface.compose
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Build
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.text.style.TextOverflow.Companion.Ellipsis
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
@@ -39,4 +43,46 @@ fun KdeTextButton(
|
||||
Text(text = text)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun KdeButton(
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
colors: ButtonColors = ButtonDefaults.buttonColors(),
|
||||
text: String? = null,
|
||||
icon: ImageVector? = null,
|
||||
) {
|
||||
//TODO uncomment when button is widely used
|
||||
// val interactionSource = remember { MutableInteractionSource() }
|
||||
// val pressedState = interactionSource.collectIsPressedAsState()
|
||||
// val cornerSize by animateDpAsState(
|
||||
// targetValue = if (pressedState.value) 24.dp else 48.dp,
|
||||
// label = "Corner size change on press"
|
||||
// )
|
||||
|
||||
Button(
|
||||
onClick = onClick,
|
||||
modifier = modifier,
|
||||
// shape = RoundedCornerShape(cornerSize),
|
||||
shape = RoundedCornerShape(24.dp),
|
||||
colors = colors,
|
||||
// interactionSource = interactionSource,
|
||||
content = {
|
||||
icon?.let { Icon(imageVector = it, contentDescription = text) }
|
||||
text?.let { Text(it, maxLines = 1, overflow = Ellipsis) }
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun IconButtonPreview() {
|
||||
KdeButton(
|
||||
{},
|
||||
Modifier.width(120.dp),
|
||||
ButtonDefaults.buttonColors(Color.Gray, Color.DarkGray),
|
||||
"Button Text",
|
||||
Icons.Default.Build,
|
||||
)
|
||||
}
|
@@ -7,7 +7,6 @@
|
||||
package org.kde.kdeconnect.UserInterface.compose
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.OutlinedTextField
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.*
|
||||
@@ -17,7 +16,6 @@ import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import org.kde.kdeconnect_tp.R
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun KdeTextField(modifier: Modifier = Modifier, input: MutableState<String>, label: String) {
|
||||
var value by rememberSaveable { input }
|
||||
|
@@ -7,20 +7,20 @@
|
||||
package org.kde.kdeconnect.UserInterface.compose
|
||||
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material3.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import org.kde.kdeconnect_tp.R
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun KdeTopAppBar(
|
||||
title: String,
|
||||
navIcon: ImageVector,
|
||||
navIconOnClick: () -> Unit,
|
||||
title: String = stringResource(R.string.kde_connect),
|
||||
navIcon: ImageVector = Icons.Default.ArrowBack,
|
||||
navIconOnClick: () -> Unit, // = { onBackPressedDispatcher.onBackPressed() }
|
||||
actions: @Composable (RowScope.() -> Unit) = {},
|
||||
) {
|
||||
TopAppBar(
|
||||
|
Reference in New Issue
Block a user