mirror of
https://github.com/KDE/kdeconnect-android
synced 2025-08-21 17:37:39 +00:00
Homegenize devices look in device lists
This commit is contained in:
parent
17010e533f
commit
5bc41367ed
@ -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>
|
||||
|
@ -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>
|
69
res/layout/list_item_device_entry.xml
Normal file
69
res/layout/list_item_device_entry.xml
Normal 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>
|
@ -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>
|
@ -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"
|
||||
|
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
52
src/org/kde/kdeconnect/UserInterface/List/DeviceItem.java
Normal file
52
src/org/kde/kdeconnect/UserInterface/List/DeviceItem.java
Normal 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();
|
||||
}
|
||||
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user