mirror of
https://github.com/KDE/kdeconnect-android
synced 2025-08-31 06:05:12 +00:00
Modernize ComposeSendActivity
* UI update for the old compose send screen. * Introduces Jetpack Compose. * Migrates activity to Kotlin. * Fixes "send" button being next to "clear".
This commit is contained in:
committed by
Albert Vaca Cintora
parent
921d0ee884
commit
e9bc90d91a
@@ -275,9 +275,10 @@
|
||||
</activity>
|
||||
<activity
|
||||
android:name="org.kde.kdeconnect.Plugins.MousePadPlugin.ComposeSendActivity"
|
||||
android:label="Compose send"
|
||||
android:label="@string/compose_send_title"
|
||||
android:exported="false"
|
||||
android:parentActivityName="org.kde.kdeconnect.Plugins.MousePadPlugin.MousePadActivity">
|
||||
android:parentActivityName="org.kde.kdeconnect.Plugins.MousePadPlugin.MousePadActivity"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value="org.kde.kdeconnect.Plugins.MousePadPlugin.MousePadActivity" />
|
||||
|
12
build.gradle
12
build.gradle
@@ -29,7 +29,13 @@ android {
|
||||
}
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
compose true
|
||||
}
|
||||
|
||||
composeOptions {
|
||||
kotlinCompilerExtensionVersion = "1.4.2"
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
@@ -139,6 +145,12 @@ ext {
|
||||
dependencies {
|
||||
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.0.3'
|
||||
|
||||
implementation 'androidx.compose.material3:material3:1.0.1'
|
||||
implementation 'androidx.compose.ui:ui-tooling-preview:1.4.2'
|
||||
implementation 'androidx.activity:activity-compose:1.7.1'
|
||||
implementation 'com.google.accompanist:accompanist-themeadapter-material3:0.31.0-alpha'
|
||||
implementation 'androidx.constraintlayout:constraintlayout-compose:1.0.1'
|
||||
|
||||
implementation 'androidx.media:media:1.6.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||
implementation 'androidx.core:core-ktx:1.10.0'
|
||||
|
@@ -16,7 +16,8 @@
|
||||
android:id="@+id/coordinatorLayout"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent"
|
||||
tools:context="org.kde.kdeconnect.UserInterface.MainActivity">
|
||||
tools:context="org.kde.kdeconnect.UserInterface.MainActivity"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<include layout="@layout/toolbar" android:id="@+id/toolbar_layout" />
|
||||
|
||||
|
@@ -5,7 +5,8 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context="org.kde.kdeconnect.UserInterface.About.AboutKDEActivity">
|
||||
tools:context="org.kde.kdeconnect.UserInterface.About.AboutKDEActivity"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<include layout="@layout/toolbar" android:id="@+id/toolbar_layout" />
|
||||
|
||||
|
@@ -1,50 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/appBarLayout2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<EditText
|
||||
android:id="@+id/compose"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:ems="10"
|
||||
android:hint="@string/click_here_to_type"
|
||||
android:imeActionLabel="@string/send_compose"
|
||||
android:imeOptions="actionSend|actionDone"
|
||||
android:importantForAutofill="no"
|
||||
android:inputType="textLongMessage|textMultiLine"
|
||||
android:isScrollContainer="true"
|
||||
android:saveEnabled="true"
|
||||
android:scrollbars="vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/appBarLayout2"
|
||||
app:layout_constraintVertical_bias="1.0"
|
||||
tools:ignore="SpeakableTextPresentCheck,TextContrastCheck" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
@@ -6,7 +6,8 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context="org.kde.kdeconnect.UserInterface.CustomDevicesActivity">
|
||||
tools:context="org.kde.kdeconnect.UserInterface.CustomDevicesActivity"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<include layout="@layout/toolbar" android:id="@+id/toolbar_layout" />
|
||||
|
||||
|
@@ -4,6 +4,7 @@
|
||||
android:layout_height="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:fitsSystemWindows="true"
|
||||
tools:context="org.kde.kdeconnect.UserInterface.About.LicensesActivity">
|
||||
|
||||
<include layout="@layout/toolbar" android:id="@+id/toolbar_layout" />
|
||||
|
@@ -7,14 +7,14 @@
|
||||
<androidx.drawerlayout.widget.DrawerLayout
|
||||
android:id="@+id/drawer_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"> <!-- fitSystemWindows to make the drawer slide below the Lollipop transparent status bar -->
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:id="@+id/coordinatorLayout"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_width="match_parent"
|
||||
tools:context="org.kde.kdeconnect.UserInterface.MainActivity">
|
||||
tools:context="org.kde.kdeconnect.UserInterface.MainActivity"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<include layout="@layout/toolbar" android:id="@+id/toolbar_layout"/>
|
||||
|
||||
|
@@ -9,9 +9,7 @@
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:elevation="8dp"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.ActionBar">
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
@@ -21,10 +19,7 @@
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/mpris_tabs"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/toolbar_color"
|
||||
app:tabIndicatorColor="?android:textColorPrimary"
|
||||
app:tabSelectedTextColor="?android:textColorPrimary" />
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
|
@@ -6,7 +6,8 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
tools:context="org.kde.kdeconnect.UserInterface.PluginSettingsActivity">
|
||||
tools:context="org.kde.kdeconnect.UserInterface.PluginSettingsActivity"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<include layout="@layout/toolbar" android:id="@+id/toolbar_layout" />
|
||||
|
||||
|
@@ -5,12 +5,11 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.ActionBar">
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:elevation="8dp"
|
||||
app:title="@string/kde_connect"/>
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
@@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:kdeconnect="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_send_compose"
|
||||
android:icon="@android:drawable/ic_menu_send"
|
||||
android:title="@string/send_compose"
|
||||
kdeconnect:showAsAction="ifRoom" />
|
||||
<item
|
||||
android:id="@+id/menu_clear_compose"
|
||||
android:title="@string/clear_compose"
|
||||
kdeconnect:showAsAction="always" />
|
||||
|
||||
</menu>
|
@@ -6,13 +6,13 @@
|
||||
android:id="@+id/menu_rise_up"
|
||||
android:icon="@drawable/ic_arrow_upward_black_24dp"
|
||||
android:title="@string/rise_up"
|
||||
android:iconTint="@color/text_color"
|
||||
kdeconnect:iconTint="?colorOnSurfaceVariant"
|
||||
kdeconnect:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_rise_down"
|
||||
android:icon="@drawable/ic_arrow_downward_black_24dp"
|
||||
android:title="@string/rise_down"
|
||||
android:iconTint="@color/text_color"
|
||||
kdeconnect:iconTint="?colorOnSurfaceVariant"
|
||||
kdeconnect:showAsAction="ifRoom" />
|
||||
</menu>
|
||||
|
@@ -11,7 +11,6 @@
|
||||
<color name="toolbar_color">@android:color/system_neutral1_900</color>
|
||||
<color name="card_stroke_color">@android:color/system_neutral2_800</color>
|
||||
<color name="activity_background">@android:color/system_neutral1_900</color>
|
||||
<item name="lightMode" type="bool">false</item>
|
||||
|
||||
<!-- This is for dark theme. In dark theme both selected and unselected text in the
|
||||
navigation bar should be white. This is different from the light theme as both states have
|
||||
|
@@ -11,7 +11,6 @@
|
||||
<color name="toolbar_color">@android:color/black</color>
|
||||
<color name="card_stroke_color">#8C8C8C</color>
|
||||
<color name="activity_background">@android:color/black</color>
|
||||
<item name="lightMode" type="bool">false</item>
|
||||
|
||||
<!-- This is for dark theme. In dark theme both selected and unselected text in the
|
||||
navigation bar should be white. This is different from the light theme as both states have
|
||||
|
@@ -11,6 +11,5 @@
|
||||
<color name="toolbar_color">@android:color/system_neutral1_50</color>
|
||||
<color name="card_stroke_color">@android:color/system_neutral2_100</color>
|
||||
<color name="activity_background">@android:color/system_neutral1_50</color>
|
||||
<item name="lightMode" type="bool">true</item>
|
||||
</resources>
|
||||
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
<style name="KdeConnectTheme.NoActionBar" parent="KdeConnectThemeBase.NoActionBar">
|
||||
<item name="android:statusBarColor">@android:color/transparent</item>
|
||||
<item name="android:windowLightStatusBar">@bool/lightMode</item>
|
||||
<item name="android:windowLightStatusBar">?attr/isLightTheme</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<style name="KdeConnectThemeBase.V27" parent="KdeConnectThemeBase">
|
||||
<item name="android:navigationBarColor">@color/activity_background</item>
|
||||
<item name="android:navigationBarColor">@android:color/transparent</item>
|
||||
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
|
||||
<item name="android:windowLightNavigationBar">?attr/isLightTheme</item>
|
||||
</style>
|
||||
|
@@ -11,5 +11,4 @@
|
||||
<color name="toolbar_color">@android:color/white</color>
|
||||
<color name="card_stroke_color">#C8C8C8</color>
|
||||
<color name="activity_background">@android:color/white</color>
|
||||
<item name="lightMode" type="bool">true</item>
|
||||
</resources>
|
@@ -488,6 +488,7 @@
|
||||
<string name="click_here_to_type">Tap here to type</string>
|
||||
<string name="clear_compose">Clear</string>
|
||||
<string name="send_compose">Send</string>
|
||||
<string name="compose_send_title">Compose send</string>
|
||||
<string name="open_compose_send">Compose text</string>
|
||||
|
||||
<string name="about_kde_about"><![CDATA[
|
||||
|
@@ -2,25 +2,24 @@
|
||||
<!-- NoActionBar because we use a Toolbar widget as ActionBar -->
|
||||
<style name="KdeConnectThemeBase" parent="Theme.Material3.DayNight.NoActionBar">
|
||||
<!-- The main color attributes -->
|
||||
<!-- The three colors used by system widgets, according to https://chris.banes.me/2014/10/17/appcompat-v21/ -->
|
||||
<item name="colorPrimary">@color/primary</item>
|
||||
<item name="colorPrimaryDark">@color/primaryDark</item>
|
||||
<item name="colorSecondary">@color/primary</item>
|
||||
<item name="colorOnSecondary">@color/on_secondary</item>
|
||||
<item name="colorAccent">@color/accent</item>
|
||||
<item name="colorHighContrast">@color/on_high_contrast</item>
|
||||
<item name="android:windowBackground">@color/activity_background</item>
|
||||
<item name="android:colorBackground">@color/activity_background</item>
|
||||
<!-- TODO: The 2 items below change too much (eg snackbar text is now black, should be white) -->
|
||||
<item name="android:textColorPrimary">@color/text_color_primary</item>
|
||||
<item name="android:textColor">@color/text_color</item>
|
||||
|
||||
<!--For android below 23 api-->
|
||||
<item name="android:statusBarColor">@android:color/black</item>
|
||||
|
||||
<!-- Drawable definitions and overrides -->
|
||||
<item name="divider">?colorHighContrast</item>
|
||||
|
||||
<!-- Style overrides -->
|
||||
<item name="actionModeStyle">@style/ActionModeStyle</item>
|
||||
<item name="toolbarStyle">@style/KdeConnectTheme.Toolbar</item>
|
||||
<item name="actionModeStyle">@style/Widget.Material3.ActionMode</item>
|
||||
<item name="toolbarStyle">@style/Widget.Material3.Toolbar</item>
|
||||
|
||||
<!-- Theme overrides -->
|
||||
<item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
|
||||
|
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021 Forrest Hilton <forrestmhilton@gmail.com>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
*/
|
||||
|
||||
|
||||
package org.kde.kdeconnect.Plugins.MousePadPlugin;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.EditText;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import org.kde.kdeconnect.BackgroundService;
|
||||
import org.kde.kdeconnect.NetworkPacket;
|
||||
import org.kde.kdeconnect.UserInterface.ThemeUtil;
|
||||
import org.kde.kdeconnect_tp.R;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
public class ComposeSendActivity extends AppCompatActivity {
|
||||
|
||||
private String deviceId;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.activity_compose_send);
|
||||
|
||||
setSupportActionBar(findViewById(R.id.toolbar));
|
||||
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setDisplayShowHomeEnabled(true);
|
||||
|
||||
Intent intent = getIntent();
|
||||
|
||||
deviceId = intent.getStringExtra("org.kde.kdeconnect.Plugins.MousePadPlugin.deviceId");
|
||||
|
||||
EditText editText = findViewById(R.id.compose);
|
||||
|
||||
editText.requestFocus();
|
||||
// this is almost never used
|
||||
editText.setOnEditorActionListener((v, actionId, event) -> {
|
||||
if (actionId == EditorInfo.IME_ACTION_SEND) {
|
||||
sendComposed();
|
||||
return true;
|
||||
}
|
||||
if (actionId == EditorInfo.IME_ACTION_DONE) {
|
||||
clear();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
public void sendChars(CharSequence chars) {
|
||||
final NetworkPacket np = new NetworkPacket(MousePadPlugin.PACKET_TYPE_MOUSEPAD_REQUEST);
|
||||
np.set("key", chars.toString());
|
||||
sendKeyPressPacket(np);
|
||||
}
|
||||
|
||||
private void sendKeyPressPacket(final NetworkPacket np) {
|
||||
try {
|
||||
Log.d("packed", np.serialize());
|
||||
} catch (Exception e) {
|
||||
Log.e("KDE/ComposeSend", "Exception", e);
|
||||
}
|
||||
|
||||
BackgroundService.RunWithPlugin(this, deviceId, MousePadPlugin.class, plugin -> plugin.sendKeyboardPacket(np));
|
||||
}
|
||||
|
||||
public void sendComposed() {
|
||||
EditText editText = findViewById(R.id.compose);
|
||||
|
||||
String editTextStr = editText.getText().toString();
|
||||
sendChars(editTextStr);
|
||||
clear();
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
EditText editText = findViewById(R.id.compose);
|
||||
editText.setText("");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.menu_compose_send, menu);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
int id = item.getItemId();
|
||||
if (id == R.id.menu_clear_compose) {
|
||||
clear();
|
||||
return true;
|
||||
} else if (id == R.id.menu_send_compose) {
|
||||
sendComposed();
|
||||
return true;
|
||||
} else {
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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.MousePadPlugin
|
||||
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.foundation.layout.Box
|
||||
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
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.google.accompanist.themeadapter.material3.Mdc3Theme
|
||||
import org.kde.kdeconnect.BackgroundService
|
||||
import org.kde.kdeconnect.NetworkPacket
|
||||
import org.kde.kdeconnect.UserInterface.compose.KdeTextButton
|
||||
import org.kde.kdeconnect.UserInterface.compose.KdeTextField
|
||||
import org.kde.kdeconnect.UserInterface.compose.KdeTopAppBar
|
||||
import org.kde.kdeconnect_tp.R
|
||||
|
||||
private const val INPUT_CACHE_KEY = "compose_send_input_cache"
|
||||
|
||||
class ComposeSendActivity : AppCompatActivity() {
|
||||
private var deviceId: String? = null
|
||||
private val userInput = mutableStateOf(String())
|
||||
private val prefs by lazy { PreferenceManager.getDefaultSharedPreferences(this) }
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
prefs.getString(INPUT_CACHE_KEY, null)?.let { userInput.value = it }
|
||||
|
||||
setContent { ComposeSendScreen() }
|
||||
|
||||
deviceId = intent.getStringExtra("org.kde.kdeconnect.Plugins.MousePadPlugin.deviceId")
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
with(prefs.edit()) {
|
||||
if (userInput.value.isNotBlank()) putString(INPUT_CACHE_KEY, userInput.value) else remove(INPUT_CACHE_KEY)
|
||||
apply()
|
||||
}
|
||||
}
|
||||
|
||||
private fun sendChars(chars: String) {
|
||||
val np = NetworkPacket(MousePadPlugin.PACKET_TYPE_MOUSEPAD_REQUEST)
|
||||
np["key"] = chars
|
||||
sendKeyPressPacket(np)
|
||||
}
|
||||
|
||||
private fun sendKeyPressPacket(np: NetworkPacket) {
|
||||
try {
|
||||
Log.d("packed", np.serialize())
|
||||
} catch (e: Exception) {
|
||||
Log.e("KDE/ComposeSend", "Exception", e)
|
||||
}
|
||||
BackgroundService.RunWithPlugin(
|
||||
this, deviceId, MousePadPlugin::class.java
|
||||
) { plugin: MousePadPlugin -> plugin.sendKeyboardPacket(np) }
|
||||
}
|
||||
|
||||
private fun sendComposed() {
|
||||
sendChars(userInput.value)
|
||||
clearComposeInput()
|
||||
}
|
||||
|
||||
private fun clearComposeInput() {
|
||||
userInput.value = String()
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
private fun ComposeSendScreen() {
|
||||
Mdc3Theme {
|
||||
Scaffold(
|
||||
topBar = {
|
||||
KdeTopAppBar(
|
||||
title = stringResource(R.string.compose_send_title),
|
||||
navIcon = Icons.Default.ArrowBack,
|
||||
navIconOnClick = { onBackPressedDispatcher.onBackPressed() },
|
||||
actions = {
|
||||
KdeTextButton(
|
||||
modifier = Modifier.padding(horizontal = 8.dp),
|
||||
onClick = { clearComposeInput() },
|
||||
text = stringResource(R.string.clear_compose),
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
) { scaffoldPadding ->
|
||||
Box(modifier = Modifier.padding(scaffoldPadding).fillMaxSize()) {
|
||||
KdeTextField(
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.padding(bottom = 80.dp)
|
||||
.align(Alignment.BottomStart)
|
||||
.fillMaxWidth(),
|
||||
input = userInput,
|
||||
label = stringResource(R.string.click_here_to_type),
|
||||
)
|
||||
KdeTextButton(
|
||||
onClick = { sendComposed() },
|
||||
modifier = Modifier.padding(all = 16.dp).align(Alignment.BottomEnd),
|
||||
enabled = userInput.value.isNotEmpty(),
|
||||
text = stringResource(R.string.send_compose),
|
||||
iconLeft = Icons.Default.Send,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -8,6 +8,10 @@ package org.kde.kdeconnect.Plugins.MousePadPlugin;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.hardware.Sensor;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorManager;
|
||||
import android.os.Bundle;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.HapticFeedbackConstants;
|
||||
@@ -15,17 +19,11 @@ import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.hardware.SensorManager;
|
||||
import android.hardware.SensorEventListener;
|
||||
import android.hardware.SensorEvent;
|
||||
import android.hardware.Sensor;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.content.ContextCompat;
|
||||
|
||||
import androidx.preference.PreferenceManager;
|
||||
import org.kde.kdeconnect.BackgroundService;
|
||||
import org.kde.kdeconnect.UserInterface.PluginSettingsActivity;
|
||||
@@ -455,7 +453,6 @@ public class MousePadActivity
|
||||
BackgroundService.RunWithPlugin(this, deviceId, MousePadPlugin.class, plugin -> plugin.sendScroll(0, y));
|
||||
}
|
||||
|
||||
//TODO: Does not work on KitKat with or without requestFocus()
|
||||
private void showKeyboard() {
|
||||
InputMethodManager imm = ContextCompat.getSystemService(this, InputMethodManager.class);
|
||||
keyListenerView.requestFocus();
|
||||
|
42
src/org/kde/kdeconnect/UserInterface/compose/Buttons.kt
Normal file
42
src/org/kde/kdeconnect/UserInterface/compose/Buttons.kt
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.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.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun KdeTextButton(
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier,
|
||||
text: String,
|
||||
enabled: Boolean = true,
|
||||
contentPadding: PaddingValues = PaddingValues(16.dp),
|
||||
iconLeft: ImageVector? = null,
|
||||
) {
|
||||
TextButton(
|
||||
onClick = onClick,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
contentPadding = contentPadding,
|
||||
content = {
|
||||
iconLeft?.let {
|
||||
Icon(imageVector = it, contentDescription = null)
|
||||
Spacer(Modifier.width(16.dp))
|
||||
}
|
||||
Text(text = text)
|
||||
}
|
||||
)
|
||||
}
|
41
src/org/kde/kdeconnect/UserInterface/compose/TextFields.kt
Normal file
41
src/org/kde/kdeconnect/UserInterface/compose/TextFields.kt
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.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.Composable
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.Modifier
|
||||
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 }
|
||||
OutlinedTextField(
|
||||
modifier = modifier,
|
||||
value = value,
|
||||
onValueChange = { userInput -> value = userInput },
|
||||
label = { Text(label) },
|
||||
)
|
||||
}
|
||||
|
||||
@SuppressLint("UnrememberedMutableState")
|
||||
@Preview
|
||||
@Composable
|
||||
fun Preview() {
|
||||
KdeTextField(
|
||||
input = mutableStateOf("John Doe"),
|
||||
label = stringResource(R.string.click_here_to_type),
|
||||
)
|
||||
}
|
33
src/org/kde/kdeconnect/UserInterface/compose/TopAppBars.kt
Normal file
33
src/org/kde/kdeconnect/UserInterface/compose/TopAppBars.kt
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.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.runtime.Composable
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@Composable
|
||||
fun KdeTopAppBar(
|
||||
title: String,
|
||||
navIcon: ImageVector,
|
||||
navIconOnClick: () -> Unit,
|
||||
actions: @Composable (RowScope.() -> Unit) = {},
|
||||
) {
|
||||
TopAppBar(
|
||||
navigationIcon = {
|
||||
IconButton(onClick = navIconOnClick, content = { Icon(navIcon, null) })
|
||||
},
|
||||
title = { Text(title) },
|
||||
actions = actions
|
||||
)
|
||||
}
|
Reference in New Issue
Block a user