package org.thoughtcrime.securesms; import android.app.Activity; import android.content.Intent; import android.media.RingtoneManager; import android.net.Uri; import android.os.Bundle; import android.provider.Settings; import android.text.TextUtils; import android.view.ContextMenu; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.EditText; import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.ActionBar; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.Toolbar; import com.b44t.messenger.DcChat; import com.b44t.messenger.DcContact; import com.b44t.messenger.DcContext; import com.b44t.messenger.DcEvent; import com.b44t.messenger.rpc.Rpc; import com.b44t.messenger.rpc.RpcException; import org.thoughtcrime.securesms.connect.DcEventCenter; import org.thoughtcrime.securesms.connect.DcHelper; import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme; import org.thoughtcrime.securesms.util.Prefs; import org.thoughtcrime.securesms.util.RelayUtil; import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.ViewUtil; import java.io.File; public class ProfileActivity extends PassphraseRequiredActionBarActivity implements DcEventCenter.DcEventDelegate { public static final String CHAT_ID_EXTRA = "chat_id"; public static final String CONTACT_ID_EXTRA = "contact_id"; private static final int REQUEST_CODE_PICK_RINGTONE = 1; private DcContext dcContext; private Rpc rpc; private int chatId; private boolean chatIsMultiUser; private boolean chatIsDeviceTalk; private boolean chatIsMailingList; private boolean chatIsOutBroadcast; private boolean chatIsInBroadcast; private int contactId; private boolean contactIsBot; private Toolbar toolbar; @Override protected void onPreCreate() { dynamicTheme = new DynamicNoActionBarTheme(); super.onPreCreate(); dcContext = DcHelper.getContext(this); rpc = DcHelper.getRpc(this); } @Override protected void onCreate(Bundle bundle, boolean ready) { setContentView(R.layout.profile_activity); initializeResources(); setSupportActionBar(this.toolbar); ActionBar supportActionBar = getSupportActionBar(); if (supportActionBar != null) { String title = getString(R.string.profile); if (chatIsMailingList) { title = getString(R.string.mailing_list); } else if (chatIsOutBroadcast || chatIsInBroadcast) { title = getString(R.string.channel); } else if (chatIsMultiUser) { title = getString(R.string.tab_group); } else if (contactIsBot) { title = getString(R.string.bot); } else if (!chatIsDeviceTalk && !isSelfProfile()) { title = getString(R.string.tab_contact); } supportActionBar.setDisplayHomeAsUpEnabled(true); supportActionBar.setTitle(title); } Bundle args = new Bundle(); args.putInt(ProfileFragment.CHAT_ID_EXTRA, (chatId == 0) ? -1 : chatId); args.putInt(ProfileFragment.CONTACT_ID_EXTRA, (contactId == 0) ? -1 : contactId); initFragment(R.id.fragment_container, new ProfileFragment(), args); DcEventCenter eventCenter = DcHelper.getEventCenter(this); eventCenter.addObserver(DcContext.DC_EVENT_CHAT_MODIFIED, this); eventCenter.addObserver(DcContext.DC_EVENT_CONTACTS_CHANGED, this); } @Override public boolean onCreateOptionsMenu(Menu menu) { if (!isSelfProfile()) { getMenuInflater().inflate(R.menu.profile_common, menu); boolean canReceive = true; if (chatId != 0) { DcChat dcChat = dcContext.getChat(chatId); menu.findItem(R.id.menu_clone).setVisible(chatIsMultiUser && !chatIsInBroadcast && !chatIsOutBroadcast && !chatIsMailingList); if (chatIsDeviceTalk) { menu.findItem(R.id.edit_name).setVisible(false); menu.findItem(R.id.show_encr_info).setVisible(false); menu.findItem(R.id.share).setVisible(false); } else if (chatIsMultiUser) { menu.findItem(R.id.edit_name).setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER); if (chatIsOutBroadcast) { canReceive = false; } else { if (!dcChat.isEncrypted() || !dcChat.canSend() || chatIsMailingList) { menu.findItem(R.id.edit_name).setVisible(false); } } menu.findItem(R.id.share).setVisible(false); } } else { menu.findItem(R.id.menu_clone).setVisible(false); canReceive = false; } if (!canReceive) { menu.findItem(R.id.menu_mute_notifications).setVisible(false); menu.findItem(R.id.menu_sound).setVisible(false); menu.findItem(R.id.menu_vibrate).setVisible(false); } if (isContactProfile()) { menu.findItem(R.id.edit_name).setTitle(R.string.menu_edit_name); } if (!isContactProfile() || chatIsDeviceTalk) { menu.findItem(R.id.block_contact).setVisible(false); } } super.onCreateOptionsMenu(menu); return true; } @Override public boolean onPrepareOptionsMenu(Menu menu) { MenuItem item = menu.findItem(R.id.block_contact); if(item!=null) { item.setTitle(dcContext.getContact(contactId).isBlocked()? R.string.menu_unblock_contact : R.string.menu_block_contact); Util.redMenuItem(menu, R.id.block_contact); } item = menu.findItem(R.id.menu_mute_notifications); if(item!=null) { item.setTitle(dcContext.getChat(chatId).isMuted()? R.string.menu_unmute : R.string.menu_mute); } super.onPrepareOptionsMenu(menu); return true; } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); getMenuInflater().inflate(R.menu.profile_title_context, menu); } @Override public void onDestroy() { DcHelper.getEventCenter(this).removeObservers(this); super.onDestroy(); } @Override public void handleEvent(@NonNull DcEvent event) { } private void initializeResources() { chatId = getIntent().getIntExtra(CHAT_ID_EXTRA, 0); contactId = getIntent().getIntExtra(CONTACT_ID_EXTRA, 0); contactIsBot = false; chatIsMultiUser = false; chatIsDeviceTalk = false; chatIsMailingList= false; chatIsInBroadcast = false; chatIsOutBroadcast = false; if (contactId!=0) { DcContact dcContact = dcContext.getContact(contactId); chatId = dcContext.getChatIdByContactId(contactId); contactIsBot = dcContact.isBot(); } if(chatId!=0) { DcChat dcChat = dcContext.getChat(chatId); chatIsMultiUser = dcChat.isMultiUser(); chatIsDeviceTalk = dcChat.isDeviceTalk(); chatIsMailingList = dcChat.isMailingList(); chatIsInBroadcast = dcChat.isInBroadcast(); chatIsOutBroadcast = dcChat.isOutBroadcast(); if(!chatIsMultiUser) { final int[] members = dcContext.getChatContacts(chatId); contactId = members.length>=1? members[0] : 0; } } this.toolbar = ViewUtil.findById(this, R.id.toolbar); } private boolean isContactProfile() { // contact-profiles are profiles without a chat or with a one-to-one chat return contactId!=0 && (chatId==0 || !chatIsMultiUser); } private boolean isSelfProfile() { return isContactProfile() && contactId==DcContact.DC_CONTACT_ID_SELF; } // handle events // ========================================================================= @Override public boolean onOptionsItemSelected(@NonNull MenuItem item) { super.onOptionsItemSelected(item); int itemId = item.getItemId(); if (itemId == android.R.id.home) { finish(); return true; } else if (itemId == R.id.menu_mute_notifications) { onNotifyOnOff(); } else if (itemId == R.id.menu_sound) { onSoundSettings(); } else if (itemId == R.id.menu_vibrate) { onVibrateSettings(); } else if (itemId == R.id.edit_name) { onEditName(); } else if (itemId == R.id.share) { onShare(); } else if (itemId == R.id.show_encr_info) { onEncrInfo(); } else if (itemId == R.id.block_contact) { onBlockContact(); } else if (itemId == R.id.menu_clone) { onClone(); } return false; } @Override public boolean onContextItemSelected(@NonNull MenuItem item) { super.onContextItemSelected(item); if (item.getItemId() == R.id.copy_addr_to_clipboard) { onCopyAddrToClipboard(); } return false; } private void onNotifyOnOff() { if (dcContext.getChat(chatId).isMuted()) { setMuted(0); } else { MuteDialog.show(this, this::setMuted); } } private void setMuted(final long duration) { if (chatId != 0) { dcContext.setChatMuteDuration(chatId, duration); } } private void onSoundSettings() { Uri current = Prefs.getChatRingtone(this, dcContext.getAccountId(), chatId); Uri defaultUri = Prefs.getNotificationRingtone(this); if (current == null) current = Settings.System.DEFAULT_NOTIFICATION_URI; else if (current.toString().isEmpty()) current = null; Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER); intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true); intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true); intent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, defaultUri); intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION); intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, current); startActivityForResult(intent, REQUEST_CODE_PICK_RINGTONE); } private void onVibrateSettings() { int checkedItem = Prefs.getChatVibrate(this, dcContext.getAccountId(), chatId).getId(); int[] selectedChoice = new int[]{checkedItem}; new AlertDialog.Builder(this) .setTitle(R.string.pref_vibrate) .setSingleChoiceItems(R.array.recipient_vibrate_entries, checkedItem, (dialog, which) -> selectedChoice[0] = which) .setPositiveButton(R.string.ok, (dialog, which) -> Prefs.setChatVibrate(this, dcContext.getAccountId(), chatId, Prefs.VibrateState.fromId(selectedChoice[0]))) .setNegativeButton(R.string.cancel, null) .show(); } public void onEnlargeAvatar() { String profileImagePath; String title; Uri profileImageUri; boolean enlargeAvatar = true; if(chatId!=0) { DcChat dcChat = dcContext.getChat(chatId); profileImagePath = dcChat.getProfileImage(); title = dcChat.getName(); enlargeAvatar = dcChat.isEncrypted() && !dcChat.isSelfTalk() && !dcChat.isDeviceTalk(); } else { DcContact dcContact = dcContext.getContact(contactId); profileImagePath = dcContact.getProfileImage(); title = dcContact.getDisplayName(); } File file = new File(profileImagePath); if (enlargeAvatar && file.exists()) { profileImageUri = Uri.fromFile(file); String type = "image/" + profileImagePath.substring(profileImagePath.lastIndexOf(".") + 1); Intent intent = new Intent(this, MediaPreviewActivity.class); intent.setDataAndType(profileImageUri, type); intent.putExtra(MediaPreviewActivity.ACTIVITY_TITLE_EXTRA, title); intent.putExtra( // show edit-button, if the user is allowed to edit the name/avatar MediaPreviewActivity.EDIT_AVATAR_CHAT_ID, (chatIsMultiUser && !chatIsInBroadcast && !chatIsMailingList) ? chatId : 0 ); startActivity(intent); } else if (chatIsMultiUser){ onEditName(); } } private void onEditName() { if (chatIsMultiUser) { DcChat dcChat = dcContext.getChat(chatId); if (chatIsMailingList || dcChat.canSend()) { Intent intent = new Intent(this, GroupCreateActivity.class); intent.putExtra(GroupCreateActivity.EDIT_GROUP_CHAT_ID, chatId); startActivity(intent); } } else { int accountId = dcContext.getAccountId(); DcContact dcContact = dcContext.getContact(contactId); String authName = dcContact.getAuthName(); if (TextUtils.isEmpty(authName)) { authName = dcContact.getAddr(); } View gl = View.inflate(this, R.layout.single_line_input, null); EditText inputField = gl.findViewById(R.id.input_field); inputField.setText(dcContact.getName()); inputField.setSelection(inputField.getText().length()); inputField.setHint(getString(R.string.edit_name_placeholder, authName)); new AlertDialog.Builder(this) .setTitle(R.string.menu_edit_name) .setMessage(getString(R.string.edit_name_explain, authName)) .setView(gl) .setPositiveButton(android.R.string.ok, (dialog, whichButton) -> { String newName = inputField.getText().toString(); try { rpc.changeContactName(accountId, contactId, newName); } catch (RpcException e) { e.printStackTrace(); } }) .setNegativeButton(android.R.string.cancel, null) .setCancelable(false) .show(); } } private void onShare() { Intent composeIntent = new Intent(); DcContact dcContact = dcContext.getContact(contactId); if (dcContact.isKeyContact()) { RelayUtil.setSharedContactId(composeIntent, contactId); } else { RelayUtil.setSharedText(composeIntent, dcContact.getAddr()); } ConversationListRelayingActivity.start(this, composeIntent); } private void onCopyAddrToClipboard() { DcContact dcContact = dcContext.getContact(contactId); Util.writeTextToClipboard(this, dcContact.getAddr()); Toast.makeText(this, getString(R.string.copied_to_clipboard), Toast.LENGTH_SHORT).show(); } private void onEncrInfo() { String infoStr = isContactProfile() ? dcContext.getContactEncrInfo(contactId) : dcContext.getChatEncrInfo(chatId); new AlertDialog.Builder(this) .setMessage(infoStr) .setPositiveButton(android.R.string.ok, null) .show(); } private void onBlockContact() { DcContact dcContact = dcContext.getContact(contactId); if(dcContact.isBlocked()) { new AlertDialog.Builder(this) .setMessage(R.string.ask_unblock_contact) .setCancelable(true) .setNegativeButton(android.R.string.cancel, null) .setPositiveButton(R.string.menu_unblock_contact, (dialog, which) -> { dcContext.blockContact(contactId, 0); }).show(); } else { AlertDialog dialog = new AlertDialog.Builder(this) .setMessage(R.string.ask_block_contact) .setCancelable(true) .setNegativeButton(android.R.string.cancel, null) .setPositiveButton(R.string.menu_block_contact, (d, which) -> { dcContext.blockContact(contactId, 1); }).show(); Util.redPositiveButton(dialog); } } private void onClone() { Intent intent = new Intent(this, GroupCreateActivity.class); intent.putExtra(GroupCreateActivity.CLONE_CHAT_EXTRA, chatId); startActivity(intent); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode==REQUEST_CODE_PICK_RINGTONE && resultCode== Activity.RESULT_OK && data!=null) { Uri value = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI); Uri defaultValue = Prefs.getNotificationRingtone(this); if (defaultValue.equals(value)) value = null; else if (value == null) value = Uri.EMPTY; Prefs.setChatRingtone(this, dcContext.getAccountId(), chatId, value); } } }