2
0
mirror of https://github.com/KDE/kdeconnect-android synced 2025-08-22 01:51:47 +00:00

Homegenize devices look in device lists

This commit is contained in:
Albert Vaca Cintora 2025-05-26 12:03:20 +02:00
parent 17010e533f
commit 5bc41367ed
No known key found for this signature in database
13 changed files with 184 additions and 204 deletions

View File

@ -23,7 +23,7 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
android:dividerHeight="12dp"
android:orientation="vertical"
android:clipToPadding="false"
tools:listitem="@layout/list_card_entry"
tools:listitem="@layout/list_item_device_entry"
tools:context=".MainActivity" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

View File

@ -1,51 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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
-->
<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="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
style="@style/KdeConnectCardStyle.Filled"
app:contentPadding="@dimen/view_default_padding"
tools:layout_width="240dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:baselineAligned="false"
android:gravity="center_vertical"
android:layout_marginTop="8dp"
android:minHeight="?android:attr/listPreferredItemHeight"
android:orientation="vertical">
<ImageView
android:id="@+id/list_item_entry_icon"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:src="@drawable/ic_device_laptop_32dp"
android:layout_marginBottom="12dp"
android:importantForAccessibility="no"
app:tint="?attr/colorOnSurface" />
<TextView
android:id="@+id/list_item_entry_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:ellipsize="end"
android:lines="2"
android:text=""
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="?attr/colorOnSurface"
tools:maxLength="30"
tools:text="@tools:sample/lorem/random" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>

View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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
-->
<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="match_parent"
android:layout_height="wrap_content"
android:layout_margin="4dp"
style="@style/KdeConnectCardStyle.Filled"
app:contentPadding="@dimen/view_default_padding">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:baselineAligned="false"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeight"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/list_item_entry_icon"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_marginStart="12dp"
android:src="@drawable/ic_device_laptop_32dp"
android:importantForAccessibility="no"
app:tint="?attr/colorControlNormal"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/list_item_entry_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dip"
android:text=""
android:textAppearance="?android:attr/textAppearanceMedium"
tools:text="A very long device name that might wrap into multiple lines"/>
<TextView
android:id="@+id/list_item_entry_summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dip"
android:singleLine="true"
android:text=""
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#CC2222"
android:visibility="gone"
tools:text="Other (optional) info"
tools:visibility="gone"/>
</LinearLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>

View File

@ -1,67 +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
-->
<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="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:baselineAligned="false"
android:gravity="center_vertical"
android:minHeight="?android:attr/listPreferredItemHeight"
android:orientation="horizontal"
android:paddingLeft="16dp"
android:paddingRight="16dp">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/list_item_entry_icon"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:layout_marginStart="12dp"
android:src="@drawable/ic_device_laptop_32dp"
android:importantForAccessibility="no"
app:tint="?attr/colorControlNormal"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/list_item_entry_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dip"
android:ellipsize="marquee"
android:fadingEdge="horizontal"
android:singleLine="true"
android:text=""
android:textAppearance="?android:attr/textAppearanceMedium"
tools:maxLength="20"
tools:text="@tools:sample/lorem/random"/>
<TextView
android:id="@+id/list_item_entry_summary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dip"
android:singleLine="true"
android:text=""
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="#CC2222"
android:visibility="gone"
tools:text="Other (optional) info"
tools:visibility="visible"/>
</LinearLayout>
</LinearLayout>

View File

@ -7,11 +7,20 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
-->
<LinearLayout 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="vertical"
android:padding="20dp">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dip"
android:text="@string/pairing_title"
android:textAppearance="?android:attr/textAppearanceLarge" />
<ListView
android:id="@+id/run_commands_device_list"
android:layout_width="match_parent"
@ -20,13 +29,12 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
android:addStatesFromChildren="true"
android:orientation="vertical"
android:divider="@null"
android:dividerHeight="0dp" />
android:dividerHeight="12dp" />
<TextView
android:id="@+id/no_devices"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="10dip"
android:text="@string/device_list_empty"
android:textAppearance="?android:attr/textAppearanceSmall"

View File

@ -265,7 +265,6 @@ SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted
<string name="mpris_notification_settings_summary">Allow controlling your media players without opening KDE Connect</string>
<string name="mpris_notification_key" translatable="false">mpris_notification_enabled</string>
<string name="share_to">Share to…</string>
<string name="unreachable_device">%s (Unreachable)</string>
<string name="unreachable_device_dynamic_shortcut">%s (✕)</string>
<string name="unreachable_device_url_share_text">URLs shared to an unreachable device will be delivered to it once it becomes reachable.\n\n</string>
<string name="protocol_version">Protocol version:</string>

View File

@ -21,7 +21,7 @@ import org.kde.kdeconnect.Helpers.SafeTextChecker;
import org.kde.kdeconnect.Helpers.WindowHelper;
import org.kde.kdeconnect.KdeConnect;
import org.kde.kdeconnect.NetworkPacket;
import org.kde.kdeconnect.UserInterface.List.EntryItemWithIcon;
import org.kde.kdeconnect.UserInterface.List.DeviceItem;
import org.kde.kdeconnect.UserInterface.List.ListAdapter;
import org.kde.kdeconnect.UserInterface.List.SectionItem;
import org.kde.kdeconnect.base.BaseActivity;
@ -166,7 +166,7 @@ public class SendKeystrokesToHostActivity extends BaseActivity<ActivitySendkeyst
for (Device d : devices) {
if (d.isReachable() && d.isPaired()) {
devicesList.add(d);
items.add(new EntryItemWithIcon(d.getName(), d.getIcon()));
items.add(new DeviceItem(d, null));
section.isEmpty = false;
}
}

View File

@ -21,6 +21,8 @@ import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.edit
import org.kde.kdeconnect.Device
import org.kde.kdeconnect.KdeConnect
import org.kde.kdeconnect.UserInterface.List.DeviceItem
import org.kde.kdeconnect.UserInterface.List.ListAdapter
import org.kde.kdeconnect_tp.R
import org.kde.kdeconnect_tp.databinding.WidgetRemoteCommandPluginDialogBinding
import java.util.stream.Collectors
@ -47,15 +49,8 @@ class RunCommandWidgetConfigActivity : AppCompatActivity() {
val pairedDevices = KdeConnect.getInstance().devices.values.stream().filter(Device::isPaired).collect(Collectors.toList())
binding.runCommandsDeviceList.adapter = object : ArrayAdapter<Device>(this, 0, pairedDevices) {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val view : View = convertView ?: layoutInflater.inflate(R.layout.list_item_with_icon_entry, parent, false)
val device = pairedDevices[position]
view.findViewById<TextView>(R.id.list_item_entry_title).text = device.name
view.findViewById<ImageView>(R.id.list_item_entry_icon).setImageDrawable(device.icon)
return view
}
}
val list = ListAdapter(this, pairedDevices.map { DeviceItem(it, null) })
binding.runCommandsDeviceList.adapter = list
binding.runCommandsDeviceList.setOnItemClickListener { _, _, position, _ ->
val deviceId = pairedDevices[position].deviceId
saveWidgetDeviceIdPref(this, appWidgetId, deviceId)

View File

@ -23,9 +23,10 @@ import org.kde.kdeconnect.BackgroundService;
import org.kde.kdeconnect.Device;
import org.kde.kdeconnect.Helpers.WindowHelper;
import org.kde.kdeconnect.KdeConnect;
import org.kde.kdeconnect.UserInterface.List.EntryItemWithIcon;
import org.kde.kdeconnect.UserInterface.List.DeviceItem;
import org.kde.kdeconnect.UserInterface.List.ListAdapter;
import org.kde.kdeconnect.UserInterface.List.SectionItem;
import org.kde.kdeconnect.UserInterface.List.UnreachableDeviceItem;
import org.kde.kdeconnect.base.BaseActivity;
import org.kde.kdeconnect_tp.R;
import org.kde.kdeconnect_tp.databinding.ActivityShareBinding;
@ -109,11 +110,11 @@ public class ShareActivity extends BaseActivity<ActivityShareBinding> {
// Show the paired devices only if they are unreachable and the shared intent has a URL
if (d.isPaired() && (intentHasUrl || d.isReachable())) {
devicesList.add(d);
String deviceName = d.getName();
if (!d.isReachable()) {
deviceName = getString(R.string.unreachable_device, deviceName);
items.add(new UnreachableDeviceItem(d, null));
} else {
items.add(new DeviceItem(d, null));
}
items.add(new EntryItemWithIcon(deviceName, d.getIcon()));
section.isEmpty = false;
}
}

View File

@ -0,0 +1,52 @@
/*
* 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 androidx.annotation.Nullable;
import org.kde.kdeconnect.Device;
import org.kde.kdeconnect_tp.databinding.ListItemDeviceEntryBinding;
public class DeviceItem implements ListAdapter.Item {
public interface Callback {
void pairingClicked(Device d);
}
private final @Nullable Callback callback;
protected final @NonNull Device device;
protected ListItemDeviceEntryBinding binding;
public DeviceItem(@NonNull Device device, @Nullable Callback callback) {
this.device = device;
this.callback = callback;
}
public @NonNull Device getDevice() {
return this.device;
}
@NonNull
@Override
public View inflateView(@NonNull LayoutInflater layoutInflater) {
binding = ListItemDeviceEntryBinding.inflate(layoutInflater);
binding.listItemEntryIcon.setImageDrawable(device.getIcon());
binding.listItemEntryTitle.setText(device.getName());
if (callback != null) {
binding.getRoot().setOnClickListener(v1 -> callback.pairingClicked(device));
}
return binding.getRoot();
}
}

View File

@ -1,30 +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.graphics.drawable.Drawable
import android.view.LayoutInflater
import android.view.View
import org.kde.kdeconnect_tp.databinding.ListCardEntryBinding
open class EntryItemWithIcon : ListAdapter.Item {
protected val title: String
protected val icon: Drawable
constructor(title: String, icon: Drawable) {
this.title = title
this.icon = icon
}
override fun inflateView(layoutInflater: LayoutInflater): View {
val binding = ListCardEntryBinding.inflate(layoutInflater)
binding.listItemEntryTitle.text = title
binding.listItemEntryIcon.setImageDrawable(icon)
return binding.root
}
}

View File

@ -13,54 +13,24 @@ import androidx.annotation.NonNull;
import org.kde.kdeconnect.Device;
import org.kde.kdeconnect_tp.R;
import org.kde.kdeconnect_tp.databinding.ListItemWithIconEntryBinding;
public class PairingDeviceItem implements ListAdapter.Item {
public interface Callback {
void pairingClicked(Device d);
}
private final Callback callback;
private final Device device;
public class PairingDeviceItem extends DeviceItem {
public PairingDeviceItem(Device device, Callback callback) {
this.device = device;
this.callback = callback;
}
public Device getDevice() {
return this.device;
super(device, callback);
}
@NonNull
@Override
public View inflateView(@NonNull LayoutInflater layoutInflater) {
final ListItemWithIconEntryBinding binding = ListItemWithIconEntryBinding.inflate(layoutInflater);
binding.listItemEntryIcon.setImageDrawable(device.getIcon());
// binding.listItemEntryTitle.setText(device.getName() + " " + device.getConnectivityType());
binding.listItemEntryTitle.setText(device.getName());
if (device.compareProtocolVersion() != 0) {
if (device.compareProtocolVersion() > 0) {
binding.listItemEntrySummary.setText(R.string.protocol_version_newer);
binding.listItemEntrySummary.setVisibility(View.VISIBLE);
} else {
//FIXME: Uncoment when we decide old versions are old enough to notify the user.
binding.listItemEntrySummary.setVisibility(View.GONE);
/*
summaryView.setText(R.string.protocol_version_older);
summaryView.setVisibility(View.VISIBLE);
*/
}
View ret = super.inflateView(layoutInflater);
if (device.compareProtocolVersion() > 0) {
binding.listItemEntrySummary.setText(R.string.protocol_version_newer);
binding.listItemEntrySummary.setVisibility(View.VISIBLE);
} else {
binding.listItemEntrySummary.setVisibility(View.GONE);
}
binding.getRoot().setOnClickListener(v1 -> callback.pairingClicked(device));
return binding.getRoot();
return ret;
}
}

View File

@ -0,0 +1,34 @@
/*
* 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.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import androidx.annotation.NonNull;
import org.kde.kdeconnect.Device;
import org.kde.kdeconnect_tp.R;
public class UnreachableDeviceItem extends DeviceItem {
public UnreachableDeviceItem(Device device, Callback callback) {
super(device, callback);
}
@NonNull
@Override
public View inflateView(@NonNull LayoutInflater layoutInflater) {
View ret = super.inflateView(layoutInflater);
binding.listItemEntryTitle.setText(device.getName());
binding.listItemEntrySummary.setText(R.string.runcommand_notreachable);
binding.listItemEntrySummary.setVisibility(View.VISIBLE);
return ret;
}
}