Detailed changes
@@ -472,17 +472,17 @@ public class MucOptions {
return subset;
}
- public static List<User> sub(List<User> users, int max) {
- ArrayList<User> subset = new ArrayList<>();
- HashSet<Jid> jids = new HashSet<>();
- for (User user : users) {
- jids.add(user.getAccount().getJid().asBareJid());
- if (user.getRealJid() == null
- || (user.getRealJid().getLocal() != null && jids.add(user.getRealJid()))) {
+ public static List<User> sub(final List<User> users, final int max) {
+ final var subset = new ArrayList<User>();
+ final var addresses = new HashSet<Jid>();
+ for (final var user : users) {
+ addresses.add(user.getAccount().getJid().asBareJid());
+ final var address = user.getRealJid();
+ if (address == null || (address.getLocal() != null && addresses.add(address))) {
subset.add(user);
}
if (subset.size() >= max) {
- break;
+ return subset;
}
}
return subset;
@@ -641,8 +641,12 @@ public class ConferenceDetailsActivity extends XmppActivity
}
}
});
- this.mUserPreviewAdapter.submitList(
- MucOptions.sub(users, GridManager.getCurrentColumnCount(binding.users)));
+ this.binding.users.post(
+ () -> {
+ final var list =
+ MucOptions.sub(users, GridManager.getCurrentColumnCount(binding.users));
+ this.mUserPreviewAdapter.submitList(list);
+ });
this.binding.invite.setVisibility(mucOptions.canInvite() ? View.VISIBLE : View.GONE);
this.binding.showUsers.setVisibility(users.size() > 0 ? View.VISIBLE : View.GONE);
this.binding.showUsers.setText(
@@ -14,9 +14,11 @@ import android.preference.PreferenceManager;
import android.provider.ContactsContract.CommonDataKinds;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Intents;
+import android.provider.Settings;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.RelativeSizeSpan;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
@@ -145,16 +147,14 @@ public class ContactDetailsActivity extends OmemoActivity
private void checkContactPermissionAndShowAddDialog() {
if (hasContactsPermission()) {
showAddToPhoneBookDialog();
- } else if (QuickConversationsService.isContactListIntegration(this)
- && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ } else if (QuickConversationsService.isContactListIntegration(this)) {
requestPermissions(
new String[] {Manifest.permission.READ_CONTACTS}, REQUEST_SYNC_CONTACTS);
}
}
private boolean hasContactsPermission() {
- if (QuickConversationsService.isContactListIntegration(this)
- && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ if (QuickConversationsService.isContactListIntegration(this)) {
return checkSelfPermission(Manifest.permission.READ_CONTACTS)
== PackageManager.PERMISSION_GRANTED;
} else {
@@ -175,7 +175,7 @@ public class ContactDetailsActivity extends OmemoActivity
value = jid.toString();
}
final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(this);
- builder.setTitle(getString(R.string.action_add_phone_book));
+ builder.setTitle(getString(R.string.save_to_contact));
builder.setMessage(getString(R.string.add_phone_book_text, value));
builder.setNegativeButton(getString(R.string.cancel), null);
builder.setPositiveButton(
@@ -295,14 +295,35 @@ public class ContactDetailsActivity extends OmemoActivity
int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
// TODO check for Camera / Scan permission
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
- if (grantResults.length > 0)
+ if (grantResults.length == 0) {
+ return;
+ }
+ if (requestCode == REQUEST_SYNC_CONTACTS && xmppConnectionServiceBound) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
- if (requestCode == REQUEST_SYNC_CONTACTS && xmppConnectionServiceBound) {
- showAddToPhoneBookDialog();
- xmppConnectionService.loadPhoneContacts();
- xmppConnectionService.startContactObserver();
- }
+ showAddToPhoneBookDialog();
+ xmppConnectionService.loadPhoneContacts();
+ xmppConnectionService.startContactObserver();
+ } else {
+ showRedirectToAppSettings();
}
+ }
+ }
+
+ private void showRedirectToAppSettings() {
+ final var dialogBuilder = new MaterialAlertDialogBuilder(this);
+ dialogBuilder.setTitle(R.string.save_to_contact);
+ dialogBuilder.setMessage(
+ getString(R.string.no_contacts_permission, getString(R.string.app_name)));
+ dialogBuilder.setPositiveButton(
+ R.string.continue_btn,
+ (d, w) -> {
+ Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
+ Uri uri = Uri.fromParts("package", getPackageName(), null);
+ intent.setData(uri);
+ startActivity(intent);
+ });
+ dialogBuilder.setNegativeButton(R.string.cancel, null);
+ dialogBuilder.create().show();
}
@Override
@@ -481,29 +502,41 @@ public class ContactDetailsActivity extends OmemoActivity
}
if (contact.isBlocked() && !this.showDynamicTags) {
- binding.detailsLastseen.setVisibility(View.VISIBLE);
- binding.detailsLastseen.setText(R.string.contact_blocked);
+ binding.detailsLastSeen.setVisibility(View.VISIBLE);
+ binding.detailsLastSeen.setText(R.string.contact_blocked);
} else {
if (showLastSeen
&& contact.getLastseen() > 0
&& contact.getPresences().allOrNonSupport(Namespace.IDLE)) {
- binding.detailsLastseen.setVisibility(View.VISIBLE);
- binding.detailsLastseen.setText(
+ binding.detailsLastSeen.setVisibility(View.VISIBLE);
+ binding.detailsLastSeen.setText(
UIHelper.lastseen(
getApplicationContext(),
contact.isActive(),
contact.getLastseen()));
} else {
- binding.detailsLastseen.setVisibility(View.GONE);
+ binding.detailsLastSeen.setVisibility(View.GONE);
}
}
- binding.detailsContactjid.setText(IrregularUnicodeDetector.style(this, contact.getJid()));
+ binding.detailsContactXmppAddress.setText(
+ IrregularUnicodeDetector.style(this, contact.getJid()));
final String account = contact.getAccount().getJid().asBareJid().toString();
binding.detailsAccount.setText(getString(R.string.using_account, account));
AvatarWorkerTask.loadAvatar(
contact, binding.detailsContactBadge, R.dimen.avatar_on_details_screen_size);
binding.detailsContactBadge.setOnClickListener(this::onBadgeClick);
+ if (QuickConversationsService.isContactListIntegration(this)) {
+ if (contact.getSystemAccount() == null) {
+ binding.addAddressBook.setText(R.string.save_to_contact);
+ } else {
+ binding.addAddressBook.setText(R.string.show_in_contacts);
+ }
+ binding.addAddressBook.setVisibility(View.VISIBLE);
+ binding.addAddressBook.setOnClickListener(this::onAddToAddressBookClick);
+ } else {
+ binding.addAddressBook.setVisibility(View.GONE);
+ }
binding.detailsContactKeys.removeAllViews();
boolean hasKeys = false;
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="960"
+ android:viewportHeight="960"
+ android:tint="?attr/colorControlNormal">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M160,920L160,840L800,840L800,920L160,920ZM160,120L160,40L800,40L800,120L160,120ZM480,520Q530,520 565,485Q600,450 600,400Q600,350 565,315Q530,280 480,280Q430,280 395,315Q360,350 360,400Q360,450 395,485Q430,520 480,520ZM160,800Q127,800 103.5,776.5Q80,753 80,720L80,240Q80,207 103.5,183.5Q127,160 160,160L800,160Q833,160 856.5,183.5Q880,207 880,240L880,720Q880,753 856.5,776.5Q833,800 800,800L160,800ZM230,720L730,720Q685,664 621,632Q557,600 480,600Q403,600 339,632Q275,664 230,720Z"/>
+</vector>
@@ -46,76 +46,109 @@
<com.makeramen.roundedimageview.RoundedImageView
android:id="@+id/details_contact_badge"
- android:layout_width="@dimen/avatar_on_details_screen_size"
- android:layout_height="@dimen/avatar_on_details_screen_size"
+ android:layout_width="@dimen/publish_avatar_size"
+ android:layout_height="@dimen/publish_avatar_size"
android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"
android:scaleType="centerCrop"
app:riv_corner_radius="8dp" />
+ <TextView
+ android:id="@+id/details_contact_xmpp_address"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/details_contact_badge"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="16sp"
+ android:gravity="center_horizontal"
+ android:minWidth="288dp"
+ android:text="@string/account_settings_example_jabber_id"
+ android:textAppearance="?textAppearanceTitleLarge" />
+
+
+
<LinearLayout
- android:id="@+id/details_jidbox"
+ android:id="@+id/button_box"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginLeft="16dp"
- android:layout_toRightOf="@+id/details_contact_badge"
- android:orientation="vertical">
+ android:layout_below="@+id/details_contact_xmpp_address"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="16dp"
+ android:orientation="horizontal">
- <TextView
- android:id="@+id/details_contactjid"
+ <Button
+ android:id="@+id/add_contact_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:text="@string/account_settings_example_jabber_id"
- android:textAppearance="?textAppearanceTitleMedium" />
+ android:layout_marginHorizontal="8dp"
+ android:text="@string/add_contact" />
- <androidx.constraintlayout.widget.ConstraintLayout
- android:id="@+id/tags"
+ <Button
+ android:id="@+id/add_address_book"
+ style="@style/Widget.Material3.Button.TonalButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="8sp">
-
- <androidx.constraintlayout.helper.widget.Flow
- android:id="@+id/flow_widget"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- app:flow_horizontalBias="0"
- app:flow_horizontalGap="8sp"
- app:flow_horizontalStyle="packed"
- app:flow_verticalGap="4sp"
- app:flow_wrapMode="chain"
- app:layout_constraintEnd_toEndOf="parent"
- app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toTopOf="parent" />
- </androidx.constraintlayout.widget.ConstraintLayout>
+ android:layout_marginHorizontal="8dp"
+ android:text="@string/save_to_contact"
+ app:icon="@drawable/ic_contacts_24dp" />
+ </LinearLayout>
- <TextView
- android:id="@+id/details_lastseen"
- android:layout_width="wrap_content"
+
+ <androidx.constraintlayout.widget.ConstraintLayout
+ android:id="@+id/tags"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/button_box"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="16sp"
+ android:visibility="gone">
+
+ <androidx.constraintlayout.helper.widget.Flow
+ android:id="@+id/flow_widget"
+ android:layout_width="0dp"
android:layout_height="wrap_content"
- android:layout_marginTop="4dp"
- android:textAppearance="?textAppearanceTitleSmall"
- tools:text="@string/just_now" />
+ app:flow_horizontalBias="0"
+ app:flow_horizontalGap="8sp"
+ app:flow_horizontalStyle="packed"
+ app:flow_verticalGap="4sp"
+ app:flow_wrapMode="chain"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+ </androidx.constraintlayout.widget.ConstraintLayout>
+
+
+ <TextView
+ android:id="@+id/details_last_seen"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/tags"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="8sp"
+ android:textAppearance="?textAppearanceTitleSmall"
+ tools:text="@string/just_now" />
+
+ <LinearLayout
+ android:id="@+id/status_message_subscription_box"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_below="@+id/details_last_seen"
+ android:layout_alignStart="@+id/details_contact_xmpp_address"
+ android:layout_marginTop="8sp"
+ android:orientation="vertical">
<TextView
android:id="@+id/status_message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
+ android:layout_marginBottom="8sp"
android:textAppearance="?textAppearanceBodyMedium"
tools:text="Hey there! Iām using Conversations" />
- <Button
- android:id="@+id/add_contact_button"
- style="@style/Widget.Material3.Button.ElevatedButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
- android:text="@string/add_contact" />
-
<CheckBox
android:id="@+id/details_send_presence"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_marginTop="8dp"
android:text="@string/send_presence_updates" />
<CheckBox
@@ -129,9 +162,10 @@
android:id="@+id/details_account"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_below="@+id/details_jidbox"
+ android:layout_below="@+id/status_message_subscription_box"
android:layout_alignParentEnd="true"
- android:layout_marginTop="32dp"
+ android:layout_alignParentBottom="true"
+ android:layout_marginTop="16sp"
android:text="@string/using_account"
android:textAppearance="?textAppearanceLabelMedium" />
</RelativeLayout>
@@ -9,7 +9,6 @@
<string name="channel_details">Channel details</string>
<string name="action_add_account">Add account</string>
<string name="action_edit_contact">Edit name</string>
- <string name="action_add_phone_book">Add to address book</string>
<string name="action_delete_contact">Delete from roster</string>
<string name="action_block_contact">Block contact</string>
<string name="action_unblock_contact">Unblock contact</string>
@@ -521,6 +520,7 @@
<string name="shared_text_with_x">Text shared with %s</string>
<string name="no_storage_permission">Grant %1$s access to external storage</string>
<string name="no_camera_permission">Grant %1$s access to the camera</string>
+ <string name="no_contacts_permission">%1$s needs access to your contacts</string>
<string name="quicksy_wants_your_consent">Quicksy asks for your consent to use your data</string>
<string name="sync_with_contacts">Contact list integration</string>
<string name="sync_with_contacts_long">%1$s processes your contact list locally, on your device, to show you the names and profile pictures for matching contacts on XMPP.\n\nNo contact list data ever leaves your device!</string>
@@ -1119,4 +1119,6 @@
<string name="account_status_service_outage_scheduled">Planned Downtime</string>
<string name="account_status_service_outage_known">Service Down (Known Issue)</string>
<string name="sos_scheduled_return">The service is scheduled to return at %s</string>
+ <string name="save_to_contact">Save to Contacts</string>
+ <string name="show_in_contacts">Show in Contacts</string>
</resources>