2
0
mirror of https://github.com/KDE/kdeconnect-android synced 2025-08-30 05:37:43 +00:00

Main activity responsive layout

This commit is contained in:
Dmitry Yudin 2023-04-13 17:54:21 +02:00 committed by Albert Vaca Cintora
parent e2dbc39e3a
commit 8aeefded7c
19 changed files with 299 additions and 253 deletions

View File

@ -0,0 +1,30 @@
<LinearLayout 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"
android:fitsSystemWindows="true">
<com.google.android.material.navigation.NavigationView
android:id="@+id/navigation_drawer"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/nav_header" />
<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">
<include layout="@layout/toolbar" android:id="@+id/toolbar_layout" />
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>

View File

@ -1,44 +1,51 @@
<LinearLayout
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="@integer/activity_device_orientation"
tools:context="org.kde.kdeconnect.UserInterface.DeviceFragment">
android:layout_height="match_parent">
<!-- Layout shown when device is reachable but not yet paired -->
<include
android:id="@+id/pair_request"
layout="@layout/view_pair_request"
tools:visibility="gone"/>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<!-- Layout shown when we can't pair with device or device is not reachable -->
<include
android:id="@+id/pair_error"
layout="@layout/view_pair_error"
tools:visibility="gone"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
tools:context="org.kde.kdeconnect.UserInterface.DeviceFragment">
<!-- Layouts shown when device is paired and reachable -->
<GridView
android:id="@+id/plugins_list"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="@integer/plugins_list_weight"
android:numColumns="@integer/plugins_columns"
android:horizontalSpacing="8dp"
android:verticalSpacing="8dp"
android:layout_margin="@dimen/activity_vertical_margin"
tools:listitem="@layout/list_plugin_entry"
tools:layout_height="300dp" />
<!-- Layout shown when device is reachable but not yet paired -->
<include
android:id="@+id/pair_request"
layout="@layout/view_pair_request"
tools:visibility="gone"/>
<ListView
android:id="@+id/buttons_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="@integer/buttons_list_weight"
android:divider="@null"
android:dividerHeight="0dp"
tools:context=".DeviceActivity"
tools:listitem="@layout/list_item_with_icon_entry"
tools:layout_height="300dp" />
</LinearLayout>
<!-- Layout shown when we can't pair with device or device is not reachable -->
<include
android:id="@+id/pair_error"
layout="@layout/view_pair_error"
tools:visibility="gone"/>
<!-- Layouts shown when device is paired and reachable -->
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/plugins_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="12dp"
android:nestedScrollingEnabled="false"
tools:listitem="@layout/list_plugin_entry"
tools:layout_height="300dp" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/permissions_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nestedScrollingEnabled="false"
tools:context=".DeviceActivity"
tools:listitem="@layout/list_item_plugin_header"
tools:layout_height="300dp" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</FrameLayout>

View File

@ -1,32 +1,37 @@
<androidx.drawerlayout.widget.DrawerLayout 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: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 -->
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:id="@+id/coordinatorLayout"
android:layout_height="match_parent"
<FrameLayout 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"
tools:context="org.kde.kdeconnect.UserInterface.MainActivity">
android:layout_height="match_parent">
<include layout="@layout/toolbar" android:id="@+id/toolbar_layout" />
<FrameLayout
android:id="@+id/container"
<androidx.drawerlayout.widget.DrawerLayout
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
android:fitsSystemWindows="true"> <!-- fitSystemWindows to make the drawer slide below the Lollipop transparent status bar -->
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<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">
<com.google.android.material.navigation.NavigationView
android:id="@+id/navigation_drawer"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/nav_header" />
<include layout="@layout/toolbar" android:id="@+id/toolbar_layout"/>
</androidx.drawerlayout.widget.DrawerLayout>
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<com.google.android.material.navigation.NavigationView
android:id="@+id/navigation_drawer"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/nav_header"/>
</androidx.drawerlayout.widget.DrawerLayout>
</FrameLayout>

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="16dp"
android:paddingTop="28dp"
android:paddingRight="16dp"
android:paddingBottom="8dp" />
android:layout_height="wrap_content"
android:background="?selectableItemBackground"
android:padding="@dimen/view_default_padding"
tools:background="@android:color/darker_gray"
tools:text="@tools:sample/lorem"/>

View File

@ -2,10 +2,11 @@
<com.google.android.material.card.MaterialCardView 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="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
style="@style/KdeConnectCardStyle.Filled"
app:contentPadding="12dp"
app:contentPadding="@dimen/view_default_padding"
tools:layout_width="240dp">
<LinearLayout
@ -17,7 +18,7 @@
android:minHeight="?android:attr/listPreferredItemHeight"
android:orientation="vertical">
<androidx.appcompat.widget.AppCompatImageView
<ImageView
android:id="@+id/list_item_entry_icon"
android:layout_width="wrap_content"
android:layout_height="match_parent"

View File

@ -33,17 +33,14 @@
android:drawablePadding="5dp"
android:layout_marginBottom="8dip"
android:visibility="gone"
android:text=""
android:textAppearance="?android:attr/textAppearanceMedium"
app:drawableStartCompat="@drawable/ic_key" />
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/pair_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/button_round"
android:text="@string/request_pairing"
android:textColor="@android:color/white" />
android:text="@string/request_pairing" />
<LinearLayout
@ -51,27 +48,27 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:visibility="gone">
android:visibility="gone"
android:paddingVertical="4dp"
tools:visibility="visible">
<Button
<com.google.android.material.button.MaterialButton
android:id="@+id/accept_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="4dip"
android:layout_weight="1"
android:background="@drawable/button_round"
android:text="@string/pairing_accept"
android:textColor="@android:color/white" />
android:text="@string/pairing_accept" />
<Button
<android.widget.Space
android:layout_width="8dp"
android:layout_height="8dp" />
<com.google.android.material.button.MaterialButton
android:id="@+id/reject_button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="4dip"
android:layout_weight="1"
android:background="@drawable/button_round"
android:text="@string/pairing_reject"
android:textColor="@android:color/white" />
android:text="@string/pairing_reject" />
</LinearLayout>
</LinearLayout>

View File

@ -1,11 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="activity_device_orientation">@integer/orientation_horizontal</integer>
<integer name="plugins_list_weight">4</integer>
<integer name="buttons_list_weight">6</integer>
<integer name="mpris_now_playing_orientation">@integer/orientation_horizontal</integer>
<integer name="mpris_now_playing_album_weight">1</integer>
<integer name="mpris_now_playing_controls_weight">1</integer>

View File

@ -10,9 +10,6 @@
<item name="layout_wrap_content" type="dimen">-2</item>
<!--used in activity_device-->
<integer name="activity_device_orientation">@integer/orientation_vertical</integer>
<integer name="plugins_list_weight">@null</integer>
<integer name="buttons_list_weight">@null</integer>
<integer name="plugins_columns">2</integer>
<!--used in mpris_now_playing-->

View File

@ -2,6 +2,7 @@
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen name="activity_horizontal_margin">16dp</dimen>
<dimen name="activity_vertical_margin">16dp</dimen>
<dimen name="view_default_padding">16dp</dimen>
<dimen name="key_height">48dip</dimen>
<dimen name="fab_margin">16dp</dimen>
<dimen name="fab_elevation">6dp</dimen>

View File

@ -162,7 +162,7 @@ public class RemoteKeyboardService
}
} else { // != 1 instance of plugin -> show main activity view
Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("forceOverview", true);
intent.putExtra(MainActivity.FLAG_FORCE_OVERVIEW, true);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
if (instances.size() < 1)

View File

@ -32,13 +32,11 @@ internal class SystemVolumeProvider private constructor(plugin: SystemVolumePlug
@JvmStatic
fun fromPlugin(systemVolumePlugin: SystemVolumePlugin): SystemVolumeProvider {
if (currentProvider == null) {
currentProvider = SystemVolumeProvider(systemVolumePlugin)
}
val currentProvider = currentProvider ?: SystemVolumeProvider(systemVolumePlugin)
currentProvider!!.update(systemVolumePlugin)
currentProvider.update(systemVolumePlugin)
return currentProvider!!
return currentProvider
}
private fun scale(value: Int, maxValue: Int, maxScaled: Int): Int {

View File

@ -37,12 +37,10 @@ class AboutData(var name: String, var icon: Int, var versionName: String, var bu
parcel.writeString(sourceCodeURL)
parcel.writeString(donateURL)
if (authorsFooterText == null) {
parcel.writeByte(0x00)
} else {
authorsFooterText?.let {
parcel.writeByte(0x01)
parcel.writeInt(authorsFooterText!!)
}
parcel.writeInt(it)
} ?: parcel.writeByte(0x00)
}
override fun describeContents(): Int = 0

View File

@ -6,7 +6,6 @@
package org.kde.kdeconnect.UserInterface
import android.content.Intent
import android.content.res.Configuration
import android.os.Bundle
import android.util.Log
import android.view.KeyEvent
@ -14,10 +13,10 @@ import android.view.LayoutInflater
import android.view.Menu
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.annotation.StringRes
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import org.kde.kdeconnect.BackgroundService
import org.kde.kdeconnect.Device
@ -26,10 +25,8 @@ import org.kde.kdeconnect.Device.PluginsChangedListener
import org.kde.kdeconnect.Helpers.SecurityHelpers.SslHelper
import org.kde.kdeconnect.Plugins.BatteryPlugin.BatteryPlugin
import org.kde.kdeconnect.Plugins.Plugin
import org.kde.kdeconnect.UserInterface.List.FailedPluginListItem
import org.kde.kdeconnect.UserInterface.List.ListAdapter
import org.kde.kdeconnect.UserInterface.List.PluginAdapter
import org.kde.kdeconnect.UserInterface.List.PluginItem
import org.kde.kdeconnect.UserInterface.List.PluginListHeaderItem
import org.kde.kdeconnect_tp.R
import org.kde.kdeconnect_tp.databinding.ActivityDeviceBinding
import org.kde.kdeconnect_tp.databinding.ViewPairErrorBinding
@ -48,8 +45,8 @@ class DeviceFragment : Fragment() {
private val mActivity: MainActivity? by lazy { activity as MainActivity? }
//TODO use LinkedHashMap and delete irrelevant records when plugins changed
private val pluginListItems: ArrayList<ListAdapter.Item> = ArrayList()
private val permissionListItems: ArrayList<ListAdapter.Item> = ArrayList()
private val pluginListItems: ArrayList<PluginItem> = ArrayList()
private val permissionListItems: ArrayList<PluginItem> = ArrayList()
/**
* Top-level ViewBinding for this fragment.
@ -106,11 +103,13 @@ class DeviceFragment : Fragment() {
}
requireBinding().pairButton.setOnClickListener {
requireBinding().pairButton.visibility = View.GONE
requireBinding().pairMessage.text = null
requireBinding().pairVerification.visibility = View.VISIBLE
requireBinding().pairVerification.text = SslHelper.getVerificationKey(SslHelper.certificate, device?.certificate)
requireBinding().pairProgress.visibility = View.VISIBLE
with(requireBinding()) {
pairButton.visibility = View.GONE
pairMessage.text = null
pairVerification.visibility = View.VISIBLE
pairVerification.text = SslHelper.getVerificationKey(SslHelper.certificate, device?.certificate)
pairProgress.visibility = View.VISIBLE
}
device?.requestPairing()
}
requireBinding().acceptButton.setOnClickListener {
@ -141,6 +140,10 @@ class DeviceFragment : Fragment() {
refreshUI()
}
requireDeviceBinding().pluginsList.layoutManager =
GridLayoutManager(requireContext(), resources.getInteger(R.integer.plugins_columns))
requireDeviceBinding().permissionsList.layoutManager = LinearLayoutManager(requireContext())
return deviceBinding.root
}
@ -165,12 +168,11 @@ class DeviceFragment : Fragment() {
//Plugins button list
val plugins: Collection<Plugin> = device.loadedPlugins.values
for (p in plugins) {
if (!p.displayInContextMenu()) {
continue
}
menu.add(p.actionName).setOnMenuItemClickListener {
p.startMainActivity(mActivity)
true
if (p.displayInContextMenu()) {
menu.add(p.actionName).setOnMenuItemClickListener {
p.startMainActivity(mActivity)
true
}
}
}
val intent = Intent(mActivity, PluginSettingsActivity::class.java)
@ -256,45 +258,57 @@ class DeviceFragment : Fragment() {
if (paired && !reachable) {
requireErrorBinding().errorMessageContainer.visibility = View.VISIBLE
requireErrorBinding().notReachableMessage.visibility = View.VISIBLE
requireDeviceBinding().permissionsList.visibility = View.GONE
requireDeviceBinding().pluginsList.visibility = View.GONE
} else {
requireErrorBinding().errorMessageContainer.visibility = View.GONE
requireErrorBinding().notReachableMessage.visibility = View.GONE
requireDeviceBinding().permissionsList.visibility = View.VISIBLE
requireDeviceBinding().pluginsList.visibility = View.VISIBLE
}
try {
if (paired && reachable) {
//Plugins button list
val plugins: Collection<Plugin> = device.loadedPlugins.values
//TODO look for LinkedHashMap mention above
pluginListItems.clear()
permissionListItems.clear()
//Fill enabled plugins ArrayList
for (p in plugins) {
if (!p.hasMainActivity(context) || p.displayInContextMenu()) continue
pluginListItems.add(PluginItem(p) { p.startMainActivity(mActivity) })
if (p.hasMainActivity(context) && !p.displayInContextMenu()) {
pluginListItems.add(
PluginItem(requireContext(), p, { p.startMainActivity(mActivity) })
)
}
}
//Fill permissionListItems with permissions plugins
createPermissionsList(
device.pluginsWithoutPermissions,
R.string.plugins_need_permission
) { plugin: Plugin ->
val dialog = plugin.permissionExplanationDialog
dialog?.show(childFragmentManager, null)
) { p: Plugin ->
p.permissionExplanationDialog?.show(childFragmentManager, null)
}
createPermissionsList(
device.pluginsWithoutOptionalPermissions,
R.string.plugins_need_optional_permission
) { plugin: Plugin ->
val dialog: DialogFragment? = plugin.optionalPermissionExplanationDialog
dialog?.show(childFragmentManager, null)
) { p: Plugin ->
p.optionalPermissionExplanationDialog?.show(childFragmentManager, null)
}
requireDeviceBinding().permissionsList.adapter =
PluginAdapter(permissionListItems, R.layout.list_item_plugin_header)
requireDeviceBinding().pluginsList.adapter =
PluginAdapter(pluginListItems, R.layout.list_plugin_entry)
requireDeviceBinding().permissionsList.adapter?.notifyDataSetChanged()
requireDeviceBinding().pluginsList.adapter?.notifyDataSetChanged()
displayBatteryInfoIfPossible()
}
requireDeviceBinding().pluginsList.adapter = ListAdapter(mActivity, pluginListItems)
//don't do unnecessary work when all permissions granted and remove view for landscape orientation
if (permissionListItems.isEmpty()) {
requireDeviceBinding().buttonsList.visibility = View.GONE
} else {
requireDeviceBinding().buttonsList.adapter = ListAdapter(mActivity, permissionListItems)
requireDeviceBinding().buttonsList.visibility = View.VISIBLE
}
mActivity?.invalidateOptionsMenu()
} catch (e: IllegalStateException) {
//Ignore: The activity was closed while we were trying to update it
@ -320,7 +334,7 @@ class DeviceFragment : Fragment() {
mActivity?.runOnUiThread {
with(requireBinding()) {
pairMessage.text = error
pairVerification.text = ""
pairVerification.text = null
pairVerification.visibility = View.GONE
pairProgress.visibility = View.GONE
pairButton.visibility = View.VISIBLE
@ -346,17 +360,24 @@ class DeviceFragment : Fragment() {
private fun createPermissionsList(
plugins: ConcurrentHashMap<String, Plugin>,
headerText: Int,
action: FailedPluginListItem.Action
@StringRes headerText: Int,
action: (Plugin) -> Unit,
) {
if (plugins.isEmpty()) return
val device = device ?: return
permissionListItems.add(PluginListHeaderItem(headerText))
permissionListItems.add(
PluginItem(
context = requireContext(),
header = requireContext().getString(headerText),
textStyleRes = R.style.TextAppearance_Material3_BodyMedium,
)
)
for (plugin in plugins.values) {
if (!device.isPluginEnabled(plugin.pluginKey)) {
continue
if (device.isPluginEnabled(plugin.pluginKey)) {
permissionListItems.add(
PluginItem(requireContext(), plugin, action, R.style.TextAppearance_Material3_LabelLarge)
)
}
permissionListItems.add(FailedPluginListItem(plugin, action))
}
}
@ -375,12 +396,10 @@ class DeviceFragment : Fragment() {
if (info != null) {
@StringRes
val resId: Int = if (info.isCharging) {
R.string.battery_status_charging_format
} else if (BatteryPlugin.isLowBattery(info)) {
R.string.battery_status_low_format
} else {
R.string.battery_status_format
val resId = when {
info.isCharging -> R.string.battery_status_charging_format
BatteryPlugin.isLowBattery(info) -> R.string.battery_status_low_format
else -> R.string.battery_status_format
}
mActivity?.supportActionBar?.subtitle = mActivity?.getString(resId, info.currentCharge)

View File

@ -1,19 +0,0 @@
/*
* SPDX-FileCopyrightText: 2018 Nicolas Fella <nicolas.fella@gmx.de>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
package org.kde.kdeconnect.UserInterface.List;
import org.kde.kdeconnect.Plugins.Plugin;
public class FailedPluginListItem extends SmallEntryItem {
public interface Action {
void action(Plugin plugin);
}
public FailedPluginListItem(Plugin plugin, Action action) {
super(plugin.getDisplayName(), (view) -> action.action(plugin));
}
}

View File

@ -0,0 +1,47 @@
package org.kde.kdeconnect.UserInterface.List
import android.annotation.TargetApi
import android.os.Build
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import org.kde.kdeconnect_tp.R
/**
* Adapter for showing enabled plugins and permission requests
* can be used with following layouts:
* list_plugin_entry - card view with text and icon
* list_item_plugin_header - plain TextView
* Any other TextView layout
*/
class PluginAdapter(
private val pluginList: ArrayList<PluginItem>,
private val layoutRes: Int,
) : RecyclerView.Adapter<PluginAdapter.PluginViewHolder>() {
override fun onCreateViewHolder(viewGroup: ViewGroup, type: Int) =
PluginViewHolder(LayoutInflater.from(viewGroup.context).inflate(layoutRes, viewGroup, false))
override fun getItemCount() = pluginList.size
@TargetApi(Build.VERSION_CODES.M)
override fun onBindViewHolder(holder: PluginViewHolder, position: Int) {
pluginList[position].let { plugin ->
holder.pluginTitle.text = plugin.header
holder.pluginIcon?.setImageDrawable(plugin.icon)
plugin.textStyleRes?.let { holder.pluginTitle.setTextAppearance(it) }
plugin.action?.let { action -> holder.itemView.setOnClickListener { action.invoke() } }
}
}
class PluginViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val pluginTitle: TextView = view.findViewById(R.id.list_item_entry_title) ?: view as TextView
val pluginIcon: ImageView? = view.findViewById(R.id.list_item_entry_icon)
}
}

View File

@ -1,31 +0,0 @@
/*
* SPDX-FileCopyrightText: 2014 Albert Vaca Cintora <albertvaka@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
package org.kde.kdeconnect.UserInterface.List;
import android.view.LayoutInflater;
import android.view.View;
import androidx.annotation.NonNull;
import org.kde.kdeconnect.Plugins.Plugin;
public class PluginItem extends EntryItemWithIcon {
private final View.OnClickListener clickListener;
public PluginItem(Plugin p, View.OnClickListener clickListener) {
super(p.getActionName(), p.getIcon());
this.clickListener = clickListener;
}
@NonNull
@Override
public View inflateView(@NonNull LayoutInflater layoutInflater) {
final View root = super.inflateView(layoutInflater);
root.setOnClickListener(clickListener);
return root;
}
}

View File

@ -0,0 +1,29 @@
package org.kde.kdeconnect.UserInterface.List
import android.content.Context
import android.graphics.drawable.Drawable
import org.kde.kdeconnect.Plugins.Plugin
class PluginItem(
val context: Context,
val header: String,
val textStyleRes: Int? = null,
) {
var action: (() -> Unit)? = null
var icon: Drawable? = null
constructor(
context: Context,
plugin: Plugin,
action: (Plugin) -> Unit,
textStyleRes: Int? = null,
) : this(
context = context,
header = plugin.displayName,
textStyleRes = textStyleRes,
) {
this.action = { action(plugin) }
this.icon = plugin.icon
}
}

View File

@ -1,33 +0,0 @@
/*
* SPDX-FileCopyrightText: 2014 Albert Vaca Cintora <albertvaka@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
package org.kde.kdeconnect.UserInterface.List;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.NonNull;
import org.kde.kdeconnect_tp.databinding.ListItemPluginHeaderBinding;
public class PluginListHeaderItem implements ListAdapter.Item {
private final int text;
public PluginListHeaderItem(int text) {
this.text = text;
}
@NonNull
@Override
public View inflateView(@NonNull LayoutInflater layoutInflater) {
TextView textView = ListItemPluginHeaderBinding.inflate(layoutInflater).getRoot();
textView.setText(text);
textView.setOnClickListener(null);
textView.setOnLongClickListener(null);
return textView;
}
}

View File

@ -63,6 +63,7 @@ public class MainActivity extends AppCompatActivity implements SharedPreferences
public static final String PAIRING_PENDING = "pending";
public static final String EXTRA_DEVICE_ID = "deviceId";
public static final String FLAG_FORCE_OVERVIEW = "forceOverview";
private NavigationView mNavigationView;
private DrawerLayout mDrawerLayout;
@ -95,22 +96,24 @@ public class MainActivity extends AppCompatActivity implements SharedPreferences
ActionBar actionBar = getSupportActionBar();
ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(this, /* host Activity */
mDrawerLayout, /* DrawerLayout object */
R.string.open, /* "open drawer" description */
R.string.close /* "close drawer" description */
);
if (mDrawerLayout != null) {
ActionBarDrawerToggle mDrawerToggle = new ActionBarDrawerToggle(this, /* host Activity */
mDrawerLayout, /* DrawerLayout object */
R.string.open, /* "open drawer" description */
R.string.close /* "close drawer" description */
);
mDrawerLayout.addDrawerListener(mDrawerToggle);
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
mDrawerLayout.addDrawerListener(mDrawerToggle);
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
mDrawerToggle.setDrawerIndicatorEnabled(true);
mDrawerToggle.syncState();
}
mDrawerToggle.setDrawerIndicatorEnabled(true);
mDrawerToggle.syncState();
preferences = getSharedPreferences("stored_menu_selection", Context.MODE_PRIVATE);
// Note: The preference changed listener should be registered before getting the name, because getting
@ -144,14 +147,16 @@ public class MainActivity extends AppCompatActivity implements SharedPreferences
break;
}
mDrawerLayout.closeDrawer(mNavigationView);
if (mDrawerLayout != null) {
mDrawerLayout.closeDrawer(mNavigationView);
}
return true;
});
// Decide which menu entry should be selected at start
String savedDevice;
int savedMenuEntry;
if (getIntent().hasExtra("forceOverview")) {
if (getIntent().hasExtra(FLAG_FORCE_OVERVIEW)) {
Log.i("MainActivity", "Requested to start main overview");
savedDevice = null;
savedMenuEntry = MENU_ENTRY_ADD_DEVICE;
@ -248,7 +253,7 @@ public class MainActivity extends AppCompatActivity implements SharedPreferences
@Override
public void onBackPressed() {
if (mDrawerLayout.isDrawerOpen(mNavigationView)) {
if (mDrawerLayout != null && mDrawerLayout.isDrawerOpen(mNavigationView)) {
mDrawerLayout.closeDrawer(mNavigationView);
} else if (mCurrentMenuEntry == MENU_ENTRY_SETTINGS || mCurrentMenuEntry == MENU_ENTRY_ABOUT) {
mCurrentMenuEntry = MENU_ENTRY_ADD_DEVICE;
@ -261,7 +266,7 @@ public class MainActivity extends AppCompatActivity implements SharedPreferences
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
if (mDrawerLayout != null && item.getItemId() == android.R.id.home) {
mDrawerLayout.openDrawer(mNavigationView);
return true;
} else {