diff --git a/CHANGELOG.md b/CHANGELOG.md index abc858022..cc57f3942 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Unreleased +* Profiles focus on recognizing contacts +* See the number of media directly in the profile, no need to tap around * Clearer app lists by removing redundant "App" subtitle * New button for quick access to the apps sent in current chat * New icon for the in-chat apps button diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml index 2473b9b9c..0573786d7 100644 --- a/src/main/AndroidManifest.xml +++ b/src/main/AndroidManifest.xml @@ -288,6 +288,10 @@ android:theme="@style/TextSecure.LightNoActionBar" android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/> + + tabs = new ArrayList<>(); + private Toolbar toolbar; + private TabLayout tabLayout; + private ViewPager viewPager; + + @Override + protected void onPreCreate() { + dynamicTheme = new DynamicNoActionBarTheme(); + super.onPreCreate(); + dcContext = DcHelper.getContext(this); + } + + @Override + protected void onCreate(Bundle bundle, boolean ready) { + tabs.add(new TabData(R.string.webxdc_apps, DcMsg.DC_MSG_WEBXDC, 0, 0)); + tabs.add(new TabData(R.string.tab_gallery, DcMsg.DC_MSG_IMAGE, DcMsg.DC_MSG_GIF, DcMsg.DC_MSG_VIDEO)); + tabs.add(new TabData(R.string.files, DcMsg.DC_MSG_FILE, 0, 0)); + tabs.add(new TabData(R.string.audio, DcMsg.DC_MSG_AUDIO, DcMsg.DC_MSG_VOICE, 0)); + + setContentView(R.layout.all_media_activity); + + initializeResources(); + + setSupportActionBar(this.toolbar); + ActionBar supportActionBar = getSupportActionBar(); + if (supportActionBar != null) { + supportActionBar.setDisplayHomeAsUpEnabled(true); + supportActionBar.setTitle(isGlobalGallery() ? R.string.menu_all_media : R.string.apps_and_media); + } + + this.tabLayout.setupWithViewPager(viewPager); + this.viewPager.setAdapter(new AllMediaPagerAdapter(getSupportFragmentManager())); + if (getIntent().getBooleanExtra(FORCE_GALLERY, false)) { + this.viewPager.setCurrentItem(1, false); + } + + DcEventCenter eventCenter = DcHelper.getEventCenter(this); + eventCenter.addObserver(DcContext.DC_EVENT_CHAT_MODIFIED, this); + eventCenter.addObserver(DcContext.DC_EVENT_CONTACTS_CHANGED, this); + } + + @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); + + if (contactId!=0) { + chatId = dcContext.getChatIdByContactId(contactId); + } + + if(chatId!=0) { + DcChat dcChat = dcContext.getChat(chatId); + if(!dcChat.isMultiUser()) { + final int[] members = dcContext.getChatContacts(chatId); + contactId = members.length>=1? members[0] : 0; + } + } + + this.viewPager = ViewUtil.findById(this, R.id.pager); + this.toolbar = ViewUtil.findById(this, R.id.toolbar); + this.tabLayout = ViewUtil.findById(this, R.id.tab_layout); + } + + private boolean isGlobalGallery() { + return contactId==0 && chatId==0; + } + + private class AllMediaPagerAdapter extends FragmentStatePagerAdapter { + private Object currentFragment = null; + + AllMediaPagerAdapter(FragmentManager fragmentManager) { + super(fragmentManager); + } + + @Override + public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) { + super.setPrimaryItem(container, position, object); + if (currentFragment != null && currentFragment != object) { + ActionMode action = null; + if (currentFragment instanceof MessageSelectorFragment) { + action = ((MessageSelectorFragment) currentFragment).getActionMode(); + } + if (action != null) { + action.finish(); + } + } + currentFragment = object; + } + + @NonNull + @Override + public Fragment getItem(int position) { + TabData data = tabs.get(position); + Fragment fragment; + Bundle args = new Bundle(); + + if (data.type1 == DcMsg.DC_MSG_IMAGE) { + fragment = new AllMediaGalleryFragment(); + args.putInt(AllMediaGalleryFragment.CHAT_ID_EXTRA, (chatId==0&&!isGlobalGallery())? -1 : chatId); + } else { + fragment = new AllMediaDocumentsFragment(); + args.putInt(AllMediaDocumentsFragment.CHAT_ID_EXTRA, (chatId==0&&!isGlobalGallery())? -1 : chatId); + args.putInt(AllMediaDocumentsFragment.VIEWTYPE1, data.type1); + args.putInt(AllMediaDocumentsFragment.VIEWTYPE2, data.type2); + } + fragment.setArguments(args); + return fragment; + } + + @Override + public int getCount() { + return tabs.size(); + } + + @Override + public CharSequence getPageTitle(int position) { + return getString(tabs.get(position).title); + } + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + super.onOptionsItemSelected(item); + + int itemId = item.getItemId(); + if (itemId == android.R.id.home) { + finish(); + return true; + } + + return false; + } +} diff --git a/src/main/java/org/thoughtcrime/securesms/ProfileDocumentsAdapter.java b/src/main/java/org/thoughtcrime/securesms/AllMediaDocumentsAdapter.java similarity index 96% rename from src/main/java/org/thoughtcrime/securesms/ProfileDocumentsAdapter.java rename to src/main/java/org/thoughtcrime/securesms/AllMediaDocumentsAdapter.java index 424547412..c582c7288 100644 --- a/src/main/java/org/thoughtcrime/securesms/ProfileDocumentsAdapter.java +++ b/src/main/java/org/thoughtcrime/securesms/AllMediaDocumentsAdapter.java @@ -25,7 +25,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.Set; -class ProfileDocumentsAdapter extends StickyHeaderGridAdapter { +class AllMediaDocumentsAdapter extends StickyHeaderGridAdapter { private final Context context; private final ItemClickListener itemClickListener; @@ -57,9 +57,9 @@ class ProfileDocumentsAdapter extends StickyHeaderGridAdapter { } } - ProfileDocumentsAdapter(@NonNull Context context, - BucketedThreadMedia media, - ItemClickListener clickListener) + AllMediaDocumentsAdapter(@NonNull Context context, + BucketedThreadMedia media, + ItemClickListener clickListener) { this.context = context; this.media = media; diff --git a/src/main/java/org/thoughtcrime/securesms/ProfileDocumentsFragment.java b/src/main/java/org/thoughtcrime/securesms/AllMediaDocumentsFragment.java similarity index 84% rename from src/main/java/org/thoughtcrime/securesms/ProfileDocumentsFragment.java rename to src/main/java/org/thoughtcrime/securesms/AllMediaDocumentsFragment.java index 1f2e2688e..32b8acdcd 100644 --- a/src/main/java/org/thoughtcrime/securesms/ProfileDocumentsFragment.java +++ b/src/main/java/org/thoughtcrime/securesms/AllMediaDocumentsFragment.java @@ -33,21 +33,21 @@ import org.thoughtcrime.securesms.util.ViewUtil; import java.util.Set; -public class ProfileDocumentsFragment +public class AllMediaDocumentsFragment extends MessageSelectorFragment implements LoaderManager.LoaderCallbacks, - ProfileDocumentsAdapter.ItemClickListener + AllMediaDocumentsAdapter.ItemClickListener { public static final String CHAT_ID_EXTRA = "chat_id"; - public static final String SHOW_AUDIO_EXTRA = "show_audio"; - public static final String SHOW_WEBXDC_EXTRA = "show_webxdc"; + public static final String VIEWTYPE1 = "viewtype1"; + public static final String VIEWTYPE2 = "viewtype2"; protected TextView noMedia; protected RecyclerView recyclerView; private StickyHeaderGridLayoutManager gridManager; private final ActionModeCallback actionModeCallback = new ActionModeCallback(); - private boolean showAudio; - private boolean showWebxdc; + private int viewtype1; + private int viewtype2; protected int chatId; @@ -57,8 +57,8 @@ public class ProfileDocumentsFragment dcContext = DcHelper.getContext(getContext()); chatId = getArguments().getInt(CHAT_ID_EXTRA, -1); - showAudio = getArguments().getBoolean(SHOW_AUDIO_EXTRA, false); - showWebxdc = getArguments().getBoolean(SHOW_WEBXDC_EXTRA, false); + viewtype1 = getArguments().getInt(VIEWTYPE1, 0); + viewtype2 = getArguments().getInt(VIEWTYPE2, 0); getLoaderManager().initLoader(0, null, this); } @@ -71,7 +71,7 @@ public class ProfileDocumentsFragment this.noMedia = ViewUtil.findById(view, R.id.no_documents); this.gridManager = new StickyHeaderGridLayoutManager(1); - this.recyclerView.setAdapter(new ProfileDocumentsAdapter(getContext(), + this.recyclerView.setAdapter(new AllMediaDocumentsAdapter(getContext(), new BucketedThreadMediaLoader.BucketedThreadMedia(getContext()), this)); this.recyclerView.setLayoutManager(gridManager); @@ -105,32 +105,26 @@ public class ProfileDocumentsFragment @Override public Loader onCreateLoader(int i, Bundle bundle) { - if (showAudio) { - return new BucketedThreadMediaLoader(getContext(), chatId, DcMsg.DC_MSG_AUDIO, DcMsg.DC_MSG_VOICE, 0); - } else if (showWebxdc) { - return new BucketedThreadMediaLoader(getContext(), chatId, DcMsg.DC_MSG_WEBXDC, 0, 0); - } else { - return new BucketedThreadMediaLoader(getContext(), chatId, DcMsg.DC_MSG_FILE, 0, 0); - } + return new BucketedThreadMediaLoader(getContext(), chatId, viewtype1, viewtype2, 0); } @Override public void onLoadFinished(Loader loader, BucketedThreadMediaLoader.BucketedThreadMedia bucketedThreadMedia) { - ((ProfileDocumentsAdapter) recyclerView.getAdapter()).setMedia(bucketedThreadMedia); - ((ProfileDocumentsAdapter) recyclerView.getAdapter()).notifyAllSectionsDataSetChanged(); + ((AllMediaDocumentsAdapter) recyclerView.getAdapter()).setMedia(bucketedThreadMedia); + ((AllMediaDocumentsAdapter) recyclerView.getAdapter()).notifyAllSectionsDataSetChanged(); noMedia.setVisibility(recyclerView.getAdapter().getItemCount() > 0 ? View.GONE : View.VISIBLE); if (chatId == DC_CHAT_NO_CHAT) { - if (showWebxdc) { + if (viewtype1 == DcMsg.DC_MSG_WEBXDC) { noMedia.setText(R.string.all_apps_empty_hint); - } else if (!showAudio){ + } else if (viewtype1 == DcMsg.DC_MSG_FILE){ noMedia.setText(R.string.all_files_empty_hint); } else { noMedia.setText(R.string.tab_all_media_empty_hint); } - } else if (showAudio) { + } else if (viewtype1 == DcMsg.DC_MSG_AUDIO) { noMedia.setText(R.string.tab_audio_empty_hint); - } else if (showWebxdc) { + } else if (viewtype1 == DcMsg.DC_MSG_WEBXDC) { noMedia.setText(R.string.tab_webxdc_empty_hint); } getActivity().invalidateOptionsMenu(); @@ -138,7 +132,7 @@ public class ProfileDocumentsFragment @Override public void onLoaderReset(Loader cursorLoader) { - ((ProfileDocumentsAdapter) recyclerView.getAdapter()).setMedia(new BucketedThreadMediaLoader.BucketedThreadMedia(getContext())); + ((AllMediaDocumentsAdapter) recyclerView.getAdapter()).setMedia(new BucketedThreadMediaLoader.BucketedThreadMedia(getContext())); } @Override @@ -156,7 +150,7 @@ public class ProfileDocumentsFragment } private void handleMediaMultiSelectClick(@NonNull DcMsg mediaRecord) { - ProfileDocumentsAdapter adapter = getListAdapter(); + AllMediaDocumentsAdapter adapter = getListAdapter(); adapter.toggleSelection(mediaRecord); if (adapter.getSelectedMediaCount() == 0) { @@ -188,7 +182,7 @@ public class ProfileDocumentsFragment @Override public void onMediaLongClicked(DcMsg mediaRecord) { if (actionMode == null) { - ((ProfileDocumentsAdapter) recyclerView.getAdapter()).toggleSelection(mediaRecord); + ((AllMediaDocumentsAdapter) recyclerView.getAdapter()).toggleSelection(mediaRecord); actionMode = ((AppCompatActivity) getActivity()).startSupportActionMode(actionModeCallback); } @@ -221,8 +215,8 @@ public class ProfileDocumentsFragment menu.findItem(R.id.menu_add_to_home_screen).setVisible(webxdcApp); } - private ProfileDocumentsAdapter getListAdapter() { - return (ProfileDocumentsAdapter) recyclerView.getAdapter(); + private AllMediaDocumentsAdapter getListAdapter() { + return (AllMediaDocumentsAdapter) recyclerView.getAdapter(); } private class ActionModeCallback implements ActionMode.Callback { diff --git a/src/main/java/org/thoughtcrime/securesms/ProfileGalleryAdapter.java b/src/main/java/org/thoughtcrime/securesms/AllMediaGalleryAdapter.java similarity index 93% rename from src/main/java/org/thoughtcrime/securesms/ProfileGalleryAdapter.java rename to src/main/java/org/thoughtcrime/securesms/AllMediaGalleryAdapter.java index 1efa30457..85d940625 100644 --- a/src/main/java/org/thoughtcrime/securesms/ProfileGalleryAdapter.java +++ b/src/main/java/org/thoughtcrime/securesms/AllMediaGalleryAdapter.java @@ -21,7 +21,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.Set; -class ProfileGalleryAdapter extends StickyHeaderGridAdapter { +class AllMediaGalleryAdapter extends StickyHeaderGridAdapter { private final Context context; private final GlideRequests glideRequests; @@ -50,10 +50,10 @@ class ProfileGalleryAdapter extends StickyHeaderGridAdapter { } } - ProfileGalleryAdapter(@NonNull Context context, - @NonNull GlideRequests glideRequests, - BucketedThreadMedia media, - ItemClickListener clickListener) + AllMediaGalleryAdapter(@NonNull Context context, + @NonNull GlideRequests glideRequests, + BucketedThreadMedia media, + ItemClickListener clickListener) { this.context = context; this.glideRequests = glideRequests; diff --git a/src/main/java/org/thoughtcrime/securesms/ProfileGalleryFragment.java b/src/main/java/org/thoughtcrime/securesms/AllMediaGalleryFragment.java similarity index 92% rename from src/main/java/org/thoughtcrime/securesms/ProfileGalleryFragment.java rename to src/main/java/org/thoughtcrime/securesms/AllMediaGalleryFragment.java index 97ad4471e..a3c742027 100644 --- a/src/main/java/org/thoughtcrime/securesms/ProfileGalleryFragment.java +++ b/src/main/java/org/thoughtcrime/securesms/AllMediaGalleryFragment.java @@ -35,10 +35,10 @@ import org.thoughtcrime.securesms.util.ViewUtil; import java.util.Set; -public class ProfileGalleryFragment +public class AllMediaGalleryFragment extends MessageSelectorFragment implements LoaderManager.LoaderCallbacks, - ProfileGalleryAdapter.ItemClickListener + AllMediaGalleryAdapter.ItemClickListener { public static final String CHAT_ID_EXTRA = "chat_id"; @@ -67,7 +67,7 @@ public class ProfileGalleryFragment this.noMedia = ViewUtil.findById(view, R.id.no_images); this.gridManager = new StickyHeaderGridLayoutManager(getCols()); - this.recyclerView.setAdapter(new ProfileGalleryAdapter(getContext(), + this.recyclerView.setAdapter(new AllMediaGalleryAdapter(getContext(), GlideApp.with(this), new BucketedThreadMediaLoader.BucketedThreadMedia(getContext()), this)); @@ -112,8 +112,8 @@ public class ProfileGalleryFragment @Override public void onLoadFinished(Loader loader, BucketedThreadMediaLoader.BucketedThreadMedia bucketedThreadMedia) { - ((ProfileGalleryAdapter) recyclerView.getAdapter()).setMedia(bucketedThreadMedia); - ((ProfileGalleryAdapter) recyclerView.getAdapter()).notifyAllSectionsDataSetChanged(); + ((AllMediaGalleryAdapter) recyclerView.getAdapter()).setMedia(bucketedThreadMedia); + ((AllMediaGalleryAdapter) recyclerView.getAdapter()).notifyAllSectionsDataSetChanged(); noMedia.setVisibility(recyclerView.getAdapter().getItemCount() > 0 ? View.GONE : View.VISIBLE); if (chatId == DC_CHAT_NO_CHAT) { @@ -124,7 +124,7 @@ public class ProfileGalleryFragment @Override public void onLoaderReset(Loader cursorLoader) { - ((ProfileGalleryAdapter) recyclerView.getAdapter()).setMedia(new BucketedThreadMediaLoader.BucketedThreadMedia(getContext())); + ((AllMediaGalleryAdapter) recyclerView.getAdapter()).setMedia(new BucketedThreadMediaLoader.BucketedThreadMedia(getContext())); } @Override @@ -142,7 +142,7 @@ public class ProfileGalleryFragment } private void handleMediaMultiSelectClick(@NonNull DcMsg mediaRecord) { - ProfileGalleryAdapter adapter = getListAdapter(); + AllMediaGalleryAdapter adapter = getListAdapter(); adapter.toggleSelection(mediaRecord); if (adapter.getSelectedMediaCount() == 0) { @@ -175,7 +175,7 @@ public class ProfileGalleryFragment @Override public void onMediaLongClicked(DcMsg mediaRecord) { if (actionMode == null) { - ((ProfileGalleryAdapter) recyclerView.getAdapter()).toggleSelection(mediaRecord); + ((AllMediaGalleryAdapter) recyclerView.getAdapter()).toggleSelection(mediaRecord); recyclerView.getAdapter().notifyDataSetChanged(); actionMode = ((AppCompatActivity) getActivity()).startSupportActionMode(actionModeCallback); @@ -206,8 +206,8 @@ public class ProfileGalleryFragment menu.findItem(R.id.menu_resend).setVisible(canResend); } - private ProfileGalleryAdapter getListAdapter() { - return (ProfileGalleryAdapter) recyclerView.getAdapter(); + private AllMediaGalleryAdapter getListAdapter() { + return (AllMediaGalleryAdapter) recyclerView.getAdapter(); } private class ActionModeCallback implements ActionMode.Callback { diff --git a/src/main/java/org/thoughtcrime/securesms/ConversationActivity.java b/src/main/java/org/thoughtcrime/securesms/ConversationActivity.java index 4544064de..ecea1e968 100644 --- a/src/main/java/org/thoughtcrime/securesms/ConversationActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/ConversationActivity.java @@ -529,8 +529,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity } else if (itemId == R.id.menu_show_map) { WebxdcActivity.openMaps(this, chatId); return true; - } else if (itemId == R.id.menu_show_apps) { - handleProfile(true); + } else if (itemId == R.id.menu_all_media) { + handleAllMedia(); return true; } else if (itemId == R.id.menu_search_up) { handleMenuSearchNext(false); @@ -612,15 +612,16 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity } } - private void handleProfile(boolean showApps) { + private void handleProfile() { Intent intent = new Intent(this, ProfileActivity.class); intent.putExtra(ProfileActivity.CHAT_ID_EXTRA, chatId); - intent.putExtra(ProfileActivity.FROM_CHAT, true); - if (showApps) { - intent.putExtra(ProfileActivity.FORCE_TAB_EXTRA, ProfileActivity.TAB_WEBXDC); - } startActivity(intent); - overridePendingTransition(0, 0); + } + + private void handleAllMedia() { + Intent intent = new Intent(this, AllMediaActivity.class); + intent.putExtra(AllMediaActivity.CHAT_ID_EXTRA, chatId); + startActivity(intent); } private void handleLeaveGroup() { @@ -872,7 +873,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity buttonToggle.getBackground().invalidateSelf(); }); - titleView.setOnClickListener(v -> handleProfile(false)); + titleView.setOnClickListener(v -> handleProfile()); titleView.setOnBackClickedListener(view -> handleReturnToConversationList()); composeText.setOnKeyListener(composeKeyPressedListener); diff --git a/src/main/java/org/thoughtcrime/securesms/ConversationListActivity.java b/src/main/java/org/thoughtcrime/securesms/ConversationListActivity.java index b588406cf..300cb62de 100644 --- a/src/main/java/org/thoughtcrime/securesms/ConversationListActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/ConversationListActivity.java @@ -449,7 +449,7 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit onBackPressed(); return true; } else if (itemId == R.id.menu_all_media) { - startActivity(new Intent(this, ProfileActivity.class)); + startActivity(new Intent(this, AllMediaActivity.class)); return true; } diff --git a/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java b/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java index b603d2eff..bcb848cae 100644 --- a/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/MediaPreviewActivity.java @@ -262,16 +262,16 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity finish(); } else if(conversationRecipient.getAddress().isDcChat()) { - Intent intent = new Intent(this, ProfileActivity.class); - intent.putExtra(ProfileActivity.CHAT_ID_EXTRA, conversationRecipient.getAddress().getDcChatId()); - intent.putExtra(ProfileActivity.FORCE_TAB_EXTRA, ProfileActivity.TAB_GALLERY); + Intent intent = new Intent(this, AllMediaActivity.class); + intent.putExtra(AllMediaActivity.CHAT_ID_EXTRA, conversationRecipient.getAddress().getDcChatId()); + intent.putExtra(AllMediaActivity.FORCE_GALLERY, true); startActivity(intent); finish(); } else if(conversationRecipient.getAddress().isDcContact()) { - Intent intent = new Intent(this, ProfileActivity.class); - intent.putExtra(ProfileActivity.CONTACT_ID_EXTRA, conversationRecipient.getAddress().getDcContactId()); - intent.putExtra(ProfileActivity.FORCE_TAB_EXTRA, ProfileActivity.TAB_GALLERY); + Intent intent = new Intent(this, AllMediaActivity.class); + intent.putExtra(AllMediaActivity.CONTACT_ID_EXTRA, conversationRecipient.getAddress().getDcContactId()); + intent.putExtra(AllMediaActivity.FORCE_GALLERY, true); startActivity(intent); finish(); } diff --git a/src/main/java/org/thoughtcrime/securesms/ProfileActivity.java b/src/main/java/org/thoughtcrime/securesms/ProfileActivity.java index 1ac092903..506e49e42 100644 --- a/src/main/java/org/thoughtcrime/securesms/ProfileActivity.java +++ b/src/main/java/org/thoughtcrime/securesms/ProfileActivity.java @@ -11,19 +11,13 @@ import android.view.ContextMenu; import android.view.Menu; import android.view.MenuItem; import android.view.View; -import android.view.ViewGroup; 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.view.ActionMode; import androidx.appcompat.widget.Toolbar; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentStatePagerAdapter; -import androidx.viewpager.widget.ViewPager; import com.b44t.messenger.DcChat; import com.b44t.messenger.DcContact; @@ -31,11 +25,9 @@ import com.b44t.messenger.DcContext; import com.b44t.messenger.DcEvent; import com.b44t.messenger.rpc.Rpc; import com.b44t.messenger.rpc.RpcException; -import com.google.android.material.tabs.TabLayout; import org.thoughtcrime.securesms.connect.DcEventCenter; import org.thoughtcrime.securesms.connect.DcHelper; -import org.thoughtcrime.securesms.mms.GlideApp; import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme; import org.thoughtcrime.securesms.util.Prefs; import org.thoughtcrime.securesms.util.RelayUtil; @@ -43,7 +35,6 @@ import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.ViewUtil; import java.io.File; -import java.util.ArrayList; public class ProfileActivity extends PassphraseRequiredActionBarActivity implements DcEventCenter.DcEventDelegate @@ -51,16 +42,6 @@ public class ProfileActivity extends PassphraseRequiredActionBarActivity public static final String CHAT_ID_EXTRA = "chat_id"; public static final String CONTACT_ID_EXTRA = "contact_id"; - public static final String FORCE_TAB_EXTRA = "force_tab"; - public static final String FROM_CHAT = "from_chat"; - - public static final int TAB_SETTINGS = 10; - public static final int TAB_GALLERY = 20; - public static final int TAB_AUDIO = 25; - public static final int TAB_DOCS = 30; - public static final int TAB_WEBXDC = 35; - public static final int TAB_LINKS = 40; - public static final int TAB_MAP = 50; private static final int REQUEST_CODE_PICK_RINGTONE = 1; @@ -72,13 +53,8 @@ public class ProfileActivity extends PassphraseRequiredActionBarActivity private boolean chatIsMailingList; private boolean chatIsBroadcast; private int contactId; - private boolean fromChat; - - private final ArrayList tabs = new ArrayList<>(); - private Toolbar toolbar; - private ConversationTitleView titleView; - private TabLayout tabLayout; - private ViewPager viewPager; + private boolean contactIsBot; + private Toolbar toolbar; @Override protected void onPreCreate() { @@ -97,38 +73,27 @@ public class ProfileActivity extends PassphraseRequiredActionBarActivity setSupportActionBar(this.toolbar); ActionBar supportActionBar = getSupportActionBar(); if (supportActionBar != null) { - if (isGlobalProfile()) { - supportActionBar.setDisplayHomeAsUpEnabled(true); - supportActionBar.setHomeActionContentDescription(getString(R.string.back)); - } else { - supportActionBar.setDisplayHomeAsUpEnabled(false); - supportActionBar.setCustomView(R.layout.conversation_title_view); - supportActionBar.setDisplayShowCustomEnabled(true); - supportActionBar.setDisplayShowTitleEnabled(false); - Toolbar parent = (Toolbar) supportActionBar.getCustomView().getParent(); - parent.setPadding(0,0,0,0); - parent.setContentInsetsAbsolute(0,0); - - titleView = (ConversationTitleView) supportActionBar.getCustomView(); - titleView.setOnBackClickedListener(view -> onBackPressed()); - titleView.setOnClickListener(view -> onEnlargeAvatar()); - if (isContactProfile() && !isSelfProfile() && !chatIsDeviceTalk) { - titleView.registerForContextMenu(this); - } + String title = getString(R.string.profile); + if (chatIsMailingList) { + title = getString(R.string.mailing_list); + } else if (chatIsBroadcast) { + title = getString(R.string.broadcast_list); + } 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); } - updateToolbar(); - - this.tabLayout.setupWithViewPager(viewPager); - this.viewPager.setAdapter(new ProfilePagerAdapter(getSupportFragmentManager())); - int forceTab = getIntent().getIntExtra(FORCE_TAB_EXTRA, -1); - if (forceTab != -1) { - int forceIndex = tabs.indexOf(forceTab); - if (forceIndex != -1) { - this.viewPager.setCurrentItem(forceIndex); - } - } + 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); @@ -137,7 +102,7 @@ public class ProfileActivity extends PassphraseRequiredActionBarActivity @Override public boolean onCreateOptionsMenu(Menu menu) { - if (!isSelfProfile() && !isGlobalProfile()) { + if (!isSelfProfile()) { getMenuInflater().inflate(R.menu.profile_common, menu); boolean canReceive = true; @@ -149,6 +114,7 @@ public class ProfileActivity extends PassphraseRequiredActionBarActivity 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 (chatIsBroadcast) { canReceive = false; } else { @@ -207,21 +173,6 @@ public class ProfileActivity extends PassphraseRequiredActionBarActivity getMenuInflater().inflate(R.menu.profile_title_context, menu); } - boolean backPressed = false; - @Override - public void onBackPressed() { - backPressed = true; - super.onBackPressed(); - } - - @Override - protected void onPause() { - super.onPause(); - if (backPressed && fromChat) { - overridePendingTransition(0, 0); - } - } - @Override public void onDestroy() { DcHelper.getEventCenter(this).removeObservers(this); @@ -230,22 +181,24 @@ public class ProfileActivity extends PassphraseRequiredActionBarActivity @Override public void handleEvent(@NonNull DcEvent event) { - updateToolbar(); } 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; chatIsBroadcast = false; - fromChat = getIntent().getBooleanExtra(FROM_CHAT, false); if (contactId!=0) { + DcContact dcContact = dcContext.getContact(contactId); chatId = dcContext.getChatIdByContactId(contactId); + contactIsBot = dcContact.isBot(); } - else if(chatId!=0) { + + if(chatId!=0) { DcChat dcChat = dcContext.getChat(chatId); chatIsMultiUser = dcChat.isMultiUser(); chatIsDeviceTalk = dcChat.isDeviceTalk(); @@ -257,38 +210,7 @@ public class ProfileActivity extends PassphraseRequiredActionBarActivity } } - if(!isGlobalProfile() && !isSelfProfile() && !chatIsMailingList) { - tabs.add(TAB_SETTINGS); - } - tabs.add(TAB_GALLERY); - tabs.add(TAB_AUDIO); - tabs.add(TAB_DOCS); - tabs.add(TAB_WEBXDC); - //tabs.add(TAB_LINKS); - //if(Prefs.isLocationStreamingEnabled(this)) { - // tabs.add(TAB_MAP); - //} - - this.viewPager = ViewUtil.findById(this, R.id.pager); this.toolbar = ViewUtil.findById(this, R.id.toolbar); - this.tabLayout = ViewUtil.findById(this, R.id.tab_layout); - } - - private void updateToolbar() { - if (isGlobalProfile()){ - getSupportActionBar().setTitle(R.string.menu_all_media); - } - else if (chatId > 0) { - DcChat dcChat = dcContext.getChat(chatId); - titleView.setTitle(GlideApp.with(this), dcChat, true); - } - else if (isContactProfile()){ - titleView.setTitle(GlideApp.with(this), dcContext.getContact(contactId)); - } - } - - private boolean isGlobalProfile() { - return contactId==0 && chatId==0; } private boolean isContactProfile() { @@ -300,124 +222,6 @@ public class ProfileActivity extends PassphraseRequiredActionBarActivity return isContactProfile() && contactId==DcContact.DC_CONTACT_ID_SELF; } - private class ProfilePagerAdapter extends FragmentStatePagerAdapter { - private Object currentFragment = null; - - ProfilePagerAdapter(FragmentManager fragmentManager) { - super(fragmentManager); - } - - @Override - public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) { - super.setPrimaryItem(container, position, object); - if (currentFragment != null && currentFragment != object) { - ActionMode action = null; - if (currentFragment instanceof MessageSelectorFragment) { - action = ((MessageSelectorFragment) currentFragment).getActionMode(); - } else if (currentFragment instanceof ProfileSettingsFragment) { - action = ((ProfileSettingsFragment) currentFragment).getActionMode(); - } - if (action != null) { - action.finish(); - } - } - currentFragment = object; - } - - @NonNull - @Override - public Fragment getItem(int position) { - int tabId = tabs.get(position); - Fragment fragment; - Bundle args = new Bundle(); - - switch(tabId) { - case TAB_SETTINGS: - fragment = new ProfileSettingsFragment(); - args.putInt(ProfileSettingsFragment.CHAT_ID_EXTRA, (chatId==0&&!isGlobalProfile())? -1 : chatId); - args.putInt(ProfileSettingsFragment.CONTACT_ID_EXTRA, (contactId==0&&!isGlobalProfile())? -1 : contactId); - break; - - case TAB_GALLERY: - fragment = new ProfileGalleryFragment(); - args.putInt(ProfileGalleryFragment.CHAT_ID_EXTRA, (chatId==0&&!isGlobalProfile())? -1 : chatId); - break; - - case TAB_AUDIO: - fragment = new ProfileDocumentsFragment(); - args.putInt(ProfileDocumentsFragment.CHAT_ID_EXTRA, (chatId==0&&!isGlobalProfile())? -1 : chatId); - args.putBoolean(ProfileDocumentsFragment.SHOW_AUDIO_EXTRA, true); - break; - - case TAB_WEBXDC: - fragment = new ProfileDocumentsFragment(); - args.putInt(ProfileDocumentsFragment.CHAT_ID_EXTRA, (chatId==0&&!isGlobalProfile())? -1 : chatId); - args.putBoolean(ProfileDocumentsFragment.SHOW_WEBXDC_EXTRA, true); - break; - - default: - fragment = new ProfileDocumentsFragment(); - args.putInt(ProfileGalleryFragment.CHAT_ID_EXTRA, (chatId==0&&!isGlobalProfile())? -1 : chatId); - break; - } - - fragment.setArguments(args); - return fragment; - } - - @Override - public int getCount() { - return tabs.size(); - } - - @Override - public CharSequence getPageTitle(int position) { - int tabId = tabs.get(position); - switch(tabId) { - case TAB_SETTINGS: - if (chatIsDeviceTalk) { - return getString(R.string.profile); - } else if(isContactProfile()) { - if (dcContext.getContact(contactId).isBot()) { - return getString(R.string.bot); - } else { - return getString(R.string.tab_contact); - } - } - else if (chatIsBroadcast) { - return getString(R.string.broadcast_list); - } - else if (chatIsMailingList) { - return getString(R.string.mailing_list); - } else { - return getString(R.string.tab_group); - } - - case TAB_GALLERY: - return getString(R.string.tab_gallery); - - case TAB_AUDIO: - return getString(R.string.audio); - - case TAB_DOCS: - return getString(R.string.files); - - case TAB_WEBXDC: - return getString(R.string.webxdc_apps); - - case TAB_LINKS: - return getString(R.string.tab_links); - - case TAB_MAP: - return getString(R.string.tab_map); - - default: - throw new AssertionError(); - } - } - } - - // handle events // ========================================================================= @@ -427,7 +231,6 @@ public class ProfileActivity extends PassphraseRequiredActionBarActivity int itemId = item.getItemId(); if (itemId == android.R.id.home) { - backPressed = true; finish(); return true; } else if (itemId == R.id.menu_mute_notifications) { @@ -505,7 +308,7 @@ public class ProfileActivity extends PassphraseRequiredActionBarActivity .show(); } - private void onEnlargeAvatar() { + public void onEnlargeAvatar() { String profileImagePath; String title; Uri profileImageUri; @@ -530,7 +333,7 @@ public class ProfileActivity extends PassphraseRequiredActionBarActivity intent.putExtra(MediaPreviewActivity.ACTIVITY_TITLE_EXTRA, title); intent.putExtra(MediaPreviewActivity.EDIT_AVATAR_CHAT_ID, chatIsMultiUser ? chatId : 0); // shows edit-button, might be 0 for a contact-profile startActivity(intent); - } else { + } else if (chatIsMultiUser){ onEditName(); } } diff --git a/src/main/java/org/thoughtcrime/securesms/ProfileAdapter.java b/src/main/java/org/thoughtcrime/securesms/ProfileAdapter.java new file mode 100644 index 000000000..1f6850bd1 --- /dev/null +++ b/src/main/java/org/thoughtcrime/securesms/ProfileAdapter.java @@ -0,0 +1,372 @@ +package org.thoughtcrime.securesms; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.RecyclerView; + +import com.b44t.messenger.DcChat; +import com.b44t.messenger.DcChatlist; +import com.b44t.messenger.DcContact; +import com.b44t.messenger.DcContext; +import com.b44t.messenger.DcLot; +import com.b44t.messenger.DcMsg; + +import org.thoughtcrime.securesms.connect.DcHelper; +import org.thoughtcrime.securesms.contacts.ContactSelectionListItem; +import org.thoughtcrime.securesms.mms.GlideRequests; +import org.thoughtcrime.securesms.util.DateUtils; +import org.thoughtcrime.securesms.util.Util; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +public class ProfileAdapter extends RecyclerView.Adapter +{ + public static final int ITEM_AVATAR = 10; + public static final int ITEM_DIVIDER = 20; + public static final int ITEM_SIGNATURE = 25; + public static final int ITEM_ALL_MEDIA_BUTTON = 30; + public static final int ITEM_SEND_MESSAGE_BUTTON = 35; + public static final int ITEM_LAST_SEEN = 40; + public static final int ITEM_INTRODUCED_BY = 45; + public static final int ITEM_ADDRESS = 50; + public static final int ITEM_HEADER = 53; + public static final int ITEM_MEMBERS = 55; + public static final int ITEM_SHARED_CHATS = 60; + + private final @NonNull Context context; + private final @NonNull DcContext dcContext; + private @Nullable DcChat dcChat; + private @Nullable DcContact dcContact; + + private final @NonNull ArrayList itemData = new ArrayList<>(); + private DcChatlist itemDataSharedChats; + private String itemDataStatusText; + private boolean isBroadcast; + private int memberCount; + private final Set selectedMembers; + + private final LayoutInflater layoutInflater; + private final ItemClickListener clickListener; + private final GlideRequests glideRequests; + + static class ItemData { + final int viewType; + final int contactId; + final int chatlistIndex; + final String label; + final int icon; + + ItemData(int viewType, String label, int icon) { + this(viewType, 0, 0, label, icon); + } + + ItemData(int viewType, int contactId, int chatlistIndex) { + this(viewType, contactId, chatlistIndex, null, 0); + } + + private ItemData(int viewType, int contactId, int chatlistIndex, @Nullable String label, int icon) { + this.viewType = viewType; + this.contactId = contactId; + this.chatlistIndex = chatlistIndex; + this.label = label; + this.icon = icon; + } + }; + + public ProfileAdapter(@NonNull Context context, + @NonNull GlideRequests glideRequests, + @Nullable ItemClickListener clickListener) + { + super(); + this.context = context; + this.glideRequests = glideRequests; + this.clickListener = clickListener; + this.dcContext = DcHelper.getContext(context); + this.layoutInflater = LayoutInflater.from(context); + this.selectedMembers= new HashSet<>(); + } + + @Override + public int getItemCount() { + return itemData.size(); + } + + @Override + public int getItemViewType(int i) { + return itemData.get(i).viewType; + } + + public static class ViewHolder extends RecyclerView.ViewHolder { + public ViewHolder(View itemView) { + super(itemView); + } + } + + @NonNull + @Override + public ProfileAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + if (viewType == ITEM_HEADER) { + final View item = LayoutInflater.from(context).inflate(R.layout.contact_selection_list_divider, parent, false); + return new ViewHolder(item); + } else if (viewType == ITEM_DIVIDER) { + final View item = LayoutInflater.from(context).inflate(R.layout.profile_divider, parent, false); + return new ViewHolder(item); + } else if (viewType == ITEM_MEMBERS) { + final ContactSelectionListItem item = (ContactSelectionListItem)layoutInflater.inflate(R.layout.contact_selection_list_item, parent, false); + return new ViewHolder(item); + } else if (viewType == ITEM_SHARED_CHATS) { + final ConversationListItem item = (ConversationListItem)layoutInflater.inflate(R.layout.conversation_list_item_view, parent, false); + item.hideItemDivider(); + return new ViewHolder(item); + } else if (viewType == ITEM_SIGNATURE) { + final ProfileStatusItem item = (ProfileStatusItem)layoutInflater.inflate(R.layout.profile_status_item, parent, false); + return new ViewHolder(item); + } else if (viewType == ITEM_AVATAR) { + final ProfileAvatarItem item = (ProfileAvatarItem)layoutInflater.inflate(R.layout.profile_avatar_item, parent, false); + return new ViewHolder(item); + } else if (viewType == ITEM_ALL_MEDIA_BUTTON || viewType == ITEM_SEND_MESSAGE_BUTTON) { + final ProfileTextItem item = (ProfileTextItem)layoutInflater.inflate(R.layout.profile_text_item_button, parent, false); + return new ViewHolder(item); + } else if (viewType == ITEM_LAST_SEEN || viewType == ITEM_INTRODUCED_BY || viewType == ITEM_ADDRESS) { + final ProfileTextItem item = (ProfileTextItem)layoutInflater.inflate(R.layout.profile_text_item_small, parent, false); + return new ViewHolder(item); + } else { + final ProfileTextItem item = (ProfileTextItem)layoutInflater.inflate(R.layout.profile_text_item, parent, false); + return new ViewHolder(item); + } + } + + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) { + ViewHolder holder = (ViewHolder) viewHolder; + ItemData data = itemData.get(i); + if (holder.itemView instanceof ContactSelectionListItem) { + ContactSelectionListItem contactItem = (ContactSelectionListItem) holder.itemView; + + int contactId = data.contactId; + DcContact dcContact = null; + String label = null; + String name; + String addr = null; + + if (contactId == DcContact.DC_CONTACT_ID_ADD_MEMBER) { + if (isBroadcast) { + name = context.getString(R.string.add_recipients); + } else { + name = context.getString(R.string.group_add_members); + } + } + else if (contactId == DcContact.DC_CONTACT_ID_QR_INVITE) { + name = context.getString(R.string.qrshow_title); + } + else { + dcContact = dcContext.getContact(contactId); + name = dcContact.getDisplayName(); + addr = dcContact.getAddr(); + } + + contactItem.unbind(glideRequests); + contactItem.set(glideRequests, contactId, dcContact, name, addr, label, false, true); + contactItem.setSelected(selectedMembers.contains(contactId)); + contactItem.setOnClickListener(view -> clickListener.onMemberClicked(contactId)); + contactItem.setOnLongClickListener(view -> {clickListener.onMemberLongClicked(contactId); return true;}); + } + else if (holder.itemView instanceof ConversationListItem) { + ConversationListItem conversationListItem = (ConversationListItem) holder.itemView; + int chatlistIndex = data.chatlistIndex; + + int chatId = itemDataSharedChats.getChatId(chatlistIndex); + DcChat chat = dcContext.getChat(chatId); + DcLot summary = itemDataSharedChats.getSummary(chatlistIndex, chat); + + conversationListItem.bind(DcHelper.getThreadRecord(context, summary, chat), + itemDataSharedChats.getMsgId(chatlistIndex), summary, glideRequests, + Collections.emptySet(), false); + conversationListItem.setOnClickListener(view -> clickListener.onSharedChatClicked(chatId)); + } + else if(holder.itemView instanceof ProfileStatusItem) { + ProfileStatusItem item = (ProfileStatusItem) holder.itemView; + item.setOnLongClickListener(view -> {clickListener.onStatusLongClicked(); return true;}); + item.set(data.label); + } + else if(holder.itemView instanceof ProfileAvatarItem) { + ProfileAvatarItem item = (ProfileAvatarItem) holder.itemView; + item.setAvatarClickListener(view -> clickListener.onAvatarClicked()); + item.set(glideRequests, dcChat, dcContact, memberCount); + } + else if(holder.itemView instanceof ProfileTextItem) { + ProfileTextItem item = (ProfileTextItem) holder.itemView; + item.setOnClickListener(view -> clickListener.onSettingsClicked(data.viewType)); + item.set(data.label, data.icon); + if (data.viewType == ITEM_LAST_SEEN || data.viewType == ITEM_ADDRESS) { + int padding = (int)((float)context.getResources().getDimensionPixelSize(R.dimen.contact_list_normal_padding) * 1.2); + item.setPadding(item.getPaddingLeft(), item.getPaddingTop(), item.getPaddingRight(), padding); + } else if (data.viewType == ITEM_INTRODUCED_BY) { + int padding = context.getResources().getDimensionPixelSize(R.dimen.contact_list_normal_padding); + item.setPadding(item.getPaddingLeft(), padding, item.getPaddingRight(), item.getPaddingBottom()); + } else if (data.viewType == ITEM_ALL_MEDIA_BUTTON && dcChat != null) { + Util.runOnAnyBackgroundThread(() -> { + String c = getAllMediaCountString(dcChat.getId()); + Util.runOnMain(() -> { + item.setValue(c); + }); + }); + } + } else if (data.viewType == ITEM_HEADER) { + TextView textView = holder.itemView.findViewById(R.id.label); + textView.setText(data.label); + } + } + + public interface ItemClickListener { + void onSettingsClicked(int settingsId); + void onStatusLongClicked(); + void onSharedChatClicked(int chatId); + void onMemberClicked(int contactId); + void onMemberLongClicked(int contactId); + void onAvatarClicked(); + } + + public void toggleMemberSelection(int contactId) { + if (!selectedMembers.remove(contactId)) { + selectedMembers.add(contactId); + } + notifyDataSetChanged(); + } + + @NonNull + public Collection getSelectedMembers() { + return new HashSet<>(selectedMembers); + } + + public int getSelectedMembersCount() { + return selectedMembers.size(); + } + + @NonNull + public String getStatusText() { + return itemDataStatusText; + } + + public void clearSelection() { + selectedMembers.clear(); + notifyDataSetChanged(); + } + + public void changeData(@Nullable int[] memberList, @Nullable DcContact dcContact, @Nullable DcChatlist sharedChats, @Nullable DcChat dcChat) { + this.dcChat = dcChat; + this.dcContact = dcContact; + itemData.clear(); + itemDataSharedChats = sharedChats; + itemDataStatusText = ""; + isBroadcast = dcChat != null && dcChat.isBroadcast(); + boolean isMailingList = dcChat != null && dcChat.isMailingList(); + boolean isGroup = dcChat != null && dcChat.getType() == DcChat.DC_CHAT_TYPE_GROUP; + boolean isSelfTalk = dcChat != null && dcChat.isSelfTalk(); + boolean isDeviceTalk = dcChat != null && dcChat.isDeviceTalk(); + memberCount = memberList!=null ? memberList.length : 0; + + itemData.add(new ItemData(ITEM_AVATAR, null, 0)); + + if (isSelfTalk || dcContact != null && !dcContact.getStatus().isEmpty()) { + itemDataStatusText = isSelfTalk ? context.getString(R.string.saved_messages_explain) : dcContact.getStatus(); + itemData.add(new ItemData(ITEM_SIGNATURE, itemDataStatusText, 0)); + } else { + itemData.add(new ItemData(ITEM_DIVIDER, null, 0)); + } + + itemData.add(new ItemData(ITEM_ALL_MEDIA_BUTTON, context.getString(R.string.apps_and_media), R.drawable.ic_apps_24)); + + if (dcContact != null && !isDeviceTalk && !isSelfTalk) { + itemData.add(new ItemData(ITEM_SEND_MESSAGE_BUTTON, context.getString(R.string.send_message), R.drawable.ic_send_sms_white_24dp)); + } + + if (dcContact != null && !isDeviceTalk && !isSelfTalk) { + long lastSeenTimestamp = dcContact.getLastSeen(); + String lastSeenTxt; + if (lastSeenTimestamp == 0) { + lastSeenTxt = context.getString(R.string.last_seen_unknown); + } + else { + lastSeenTxt = context.getString(R.string.last_seen_at, DateUtils.getExtendedTimeSpanString(context, lastSeenTimestamp)); + } + itemData.add(new ItemData(ITEM_LAST_SEEN, lastSeenTxt, 0)); + } + + if (memberList!=null) { + itemData.add(new ItemData(ITEM_DIVIDER, null, 0)); + if (dcChat != null) { + if (!isMailingList && dcChat.canSend() && dcChat.isEncrypted()) { + itemData.add(new ItemData(ITEM_MEMBERS, DcContact.DC_CONTACT_ID_ADD_MEMBER, 0)); + if (!isBroadcast) { + itemData.add(new ItemData(ITEM_MEMBERS, DcContact.DC_CONTACT_ID_QR_INVITE, 0)); + } + } + } + for (int value : memberList) { + itemData.add(new ItemData(ITEM_MEMBERS, value, 0)); + } + } + + if (sharedChats != null && !isDeviceTalk) { + itemData.add(new ItemData(ITEM_HEADER, context.getString(R.string.profile_shared_chats), 0)); + for (int i = 0; i < sharedChats.getCnt(); i++) { + itemData.add(new ItemData(ITEM_SHARED_CHATS, 0, i)); + } + } + + if (dcContact != null && !isDeviceTalk && !isSelfTalk) { + int verifierId = dcContact.getVerifierId(); + if (verifierId != 0) { + String introducedBy; + if (verifierId == DcContact.DC_CONTACT_ID_SELF) { + introducedBy = context.getString(R.string.verified_by_you); + } else { + introducedBy = context.getString(R.string.verified_by, dcContext.getContact(verifierId).getDisplayName()); + } + itemData.add(new ItemData(ITEM_INTRODUCED_BY, introducedBy, 0)); + } + + if (dcContact != null) { + itemData.add(new ItemData(ITEM_ADDRESS, dcContact.getAddr(), 0)); + } else if (isMailingList) { + itemData.add(new ItemData(ITEM_ADDRESS, dcChat.getMailinglistAddr(), 0)); + } + } + + notifyDataSetChanged(); + } + + public int ALL_MEDIA_COUNT_MAX = 500; + public int getAllMediaCount(int chatId) { + int c = dcContext.getChatMedia(chatId, DcMsg.DC_MSG_IMAGE, DcMsg.DC_MSG_GIF, DcMsg.DC_MSG_VIDEO).length; + if (c < ALL_MEDIA_COUNT_MAX) { + c += dcContext.getChatMedia(chatId, DcMsg.DC_MSG_AUDIO, DcMsg.DC_MSG_VOICE, 0).length; + } + if (c < ALL_MEDIA_COUNT_MAX) { + c += dcContext.getChatMedia(chatId, DcMsg.DC_MSG_FILE, DcMsg.DC_MSG_WEBXDC, 0).length; + } + return c; + } + + public String getAllMediaCountString(int chatId) { + final int c = getAllMediaCount(chatId); + if (c == 0) { + return context.getString(R.string.none); + } else if (c >= ALL_MEDIA_COUNT_MAX) { + return ALL_MEDIA_COUNT_MAX + "+"; + } else { + return c + ""; + } + } +} diff --git a/src/main/java/org/thoughtcrime/securesms/ProfileAvatarItem.java b/src/main/java/org/thoughtcrime/securesms/ProfileAvatarItem.java new file mode 100644 index 000000000..301c25fdd --- /dev/null +++ b/src/main/java/org/thoughtcrime/securesms/ProfileAvatarItem.java @@ -0,0 +1,112 @@ +package org.thoughtcrime.securesms; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.b44t.messenger.DcChat; +import com.b44t.messenger.DcContact; + +import org.thoughtcrime.securesms.components.AvatarView; +import org.thoughtcrime.securesms.mms.GlideRequests; +import org.thoughtcrime.securesms.recipients.Recipient; +import org.thoughtcrime.securesms.recipients.RecipientModifiedListener; +import org.thoughtcrime.securesms.util.Util; +import org.thoughtcrime.securesms.util.ViewUtil; + +public class ProfileAvatarItem extends LinearLayout implements RecipientModifiedListener { + + private AvatarView avatarView; + private TextView nameView; + private TextView subtitleView; + + private Recipient recipient; + private GlideRequests glideRequests; + + public ProfileAvatarItem(Context context) { + super(context); + } + + public ProfileAvatarItem(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + avatarView = findViewById(R.id.avatar); + nameView = findViewById(R.id.name); + subtitleView = findViewById(R.id.subtitle); + + ViewUtil.setTextViewGravityStart(nameView, getContext()); + } + + public void set(@NonNull GlideRequests glideRequests, @Nullable DcChat dcChat, @Nullable DcContact dcContact, int memberCount) { + this.glideRequests = glideRequests; + + String name = ""; + boolean greenCheckmark = false; + String subtitle = null; + if (dcChat != null) { + recipient = new Recipient(getContext(), dcChat); + name = dcChat.getName(); + greenCheckmark = dcChat.isProtected(); + + if (dcChat.isMailingList()) { + subtitle = getContext().getString(R.string.contacts_headline); + } else if (dcChat.isBroadcast()) { + subtitle = getContext().getResources().getQuantityString(R.plurals.n_recipients, memberCount, memberCount); + } else if (dcChat.getType() == DcChat.DC_CHAT_TYPE_GROUP) { + subtitle = getContext().getResources().getQuantityString(R.plurals.n_members, memberCount, memberCount); + } + } else if (dcContact != null) { + recipient = new Recipient(getContext(), dcContact); + name = dcContact.getDisplayName(); + greenCheckmark = dcContact.isVerified(); + } + + recipient.addListener(this); + avatarView.setAvatar(glideRequests, recipient, false); + avatarView.setSeenRecently(dcContact != null && dcContact.wasSeenRecently()); + + nameView.setText(name); + nameView.setCompoundDrawablesWithIntrinsicBounds(0,0, greenCheckmark ? R.drawable.ic_verified : 0, 0); + + if (subtitle != null) { + subtitleView.setVisibility(View.VISIBLE); + subtitleView.setText(subtitle); + } else { + subtitleView.setVisibility(View.GONE); + } + } + + public void setAvatarClickListener(OnClickListener listener) { + avatarView.setAvatarClickListener(listener); + } + + public void unbind(GlideRequests glideRequests) { + if (recipient != null) { + recipient.removeListener(this); + recipient = null; + } + + avatarView.clear(glideRequests); + } + + @Override + public void onModified(final Recipient recipient) { + if (this.recipient == recipient) { + Util.runOnMain(() -> { + avatarView.setAvatar(glideRequests, recipient, false); + DcContact contact = recipient.getDcContact(); + avatarView.setSeenRecently(contact != null && contact.wasSeenRecently()); + nameView.setText(recipient.toShortString()); + }); + } + } +} diff --git a/src/main/java/org/thoughtcrime/securesms/ProfileSettingsFragment.java b/src/main/java/org/thoughtcrime/securesms/ProfileFragment.java similarity index 91% rename from src/main/java/org/thoughtcrime/securesms/ProfileSettingsFragment.java rename to src/main/java/org/thoughtcrime/securesms/ProfileFragment.java index b5e77e79e..3c9c0d855 100644 --- a/src/main/java/org/thoughtcrime/securesms/ProfileSettingsFragment.java +++ b/src/main/java/org/thoughtcrime/securesms/ProfileFragment.java @@ -31,7 +31,6 @@ import org.thoughtcrime.securesms.connect.DcEventCenter; import org.thoughtcrime.securesms.connect.DcHelper; import org.thoughtcrime.securesms.mms.GlideApp; import org.thoughtcrime.securesms.qr.QrShowActivity; -import org.thoughtcrime.securesms.util.StickyHeaderDecoration; import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.ViewUtil; @@ -39,16 +38,15 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -public class ProfileSettingsFragment extends Fragment - implements ProfileSettingsAdapter.ItemClickListener, DcEventCenter.DcEventDelegate { +public class ProfileFragment extends Fragment + implements ProfileAdapter.ItemClickListener, 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_CONTACT = 2; - private StickyHeaderDecoration listDecoration; - private ProfileSettingsAdapter adapter; + private ProfileAdapter adapter; private ActionMode actionMode; private final ActionModeCallback actionModeCallback = new ActionModeCallback(); @@ -57,10 +55,6 @@ public class ProfileSettingsFragment extends Fragment protected int chatId; private int contactId; - protected ActionMode getActionMode() { - return actionMode; - } - @Override public void onCreate(Bundle bundle) { super.onCreate(bundle); @@ -72,14 +66,12 @@ public class ProfileSettingsFragment extends Fragment @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.profile_settings_fragment, container, false); - adapter = new ProfileSettingsAdapter(requireContext(), GlideApp.with(this), this); + View view = inflater.inflate(R.layout.profile_fragment, container, false); + adapter = new ProfileAdapter(requireContext(), GlideApp.with(this), this); RecyclerView list = ViewUtil.findById(view, R.id.recycler_view); list.setAdapter(adapter); list.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false)); - listDecoration = new StickyHeaderDecoration(adapter, false, true); - list.addItemDecoration(listDecoration); update(); @@ -97,12 +89,6 @@ public class ProfileSettingsFragment extends Fragment super.onDestroyView(); } - @Override - public void onConfigurationChanged(@NonNull Configuration newConfig) { - super.onConfigurationChanged(newConfig); - listDecoration.onConfigurationChanged(newConfig); - } - @Override public void handleEvent(@NonNull DcEvent event) { update(); @@ -121,12 +107,11 @@ public class ProfileSettingsFragment extends Fragment if(dcChat!=null && dcChat.isMultiUser()) { memberList = dcContext.getChatContacts(chatId); } - else if(contactId>0) { + else if(contactId>0 && contactId!=DcContact.DC_CONTACT_ID_SELF) { sharedChats = dcContext.getChatlist(0, null, contactId); } adapter.changeData(memberList, dcContact, sharedChats, dcChat); - listDecoration.invalidateLayouts(); } @@ -136,10 +121,17 @@ public class ProfileSettingsFragment extends Fragment @Override public void onSettingsClicked(int settingsId) { switch(settingsId) { - case ProfileSettingsAdapter.INFO_SEND_MESSAGE_BUTTON: + case ProfileAdapter.ITEM_ALL_MEDIA_BUTTON: + if (chatId > 0) { + Intent intent = new Intent(getActivity(), AllMediaActivity.class); + intent.putExtra(AllMediaActivity.CHAT_ID_EXTRA, chatId); + startActivity(intent); + } + break; + case ProfileAdapter.ITEM_SEND_MESSAGE_BUTTON: onSendMessage(); break; - case ProfileSettingsAdapter.INFO_VERIFIED: + case ProfileAdapter.ITEM_INTRODUCED_BY: onVerifiedByClicked(); break; } @@ -202,6 +194,12 @@ public class ProfileSettingsFragment extends Fragment } } + @Override + public void onAvatarClicked() { + ProfileActivity activity = (ProfileActivity)getActivity(); + activity.onEnlargeAvatar(); + } + public void onAddMember() { DcChat dcChat = dcContext.getChat(chatId); Intent intent = new Intent(getContext(), ContactMultiSelectionActivity.class); diff --git a/src/main/java/org/thoughtcrime/securesms/ProfileSettingsAdapter.java b/src/main/java/org/thoughtcrime/securesms/ProfileSettingsAdapter.java deleted file mode 100644 index 90827157b..000000000 --- a/src/main/java/org/thoughtcrime/securesms/ProfileSettingsAdapter.java +++ /dev/null @@ -1,352 +0,0 @@ -package org.thoughtcrime.securesms; - -import android.content.Context; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.recyclerview.widget.RecyclerView; - -import com.b44t.messenger.DcChat; -import com.b44t.messenger.DcChatlist; -import com.b44t.messenger.DcContact; -import com.b44t.messenger.DcContext; -import com.b44t.messenger.DcLot; - -import org.thoughtcrime.securesms.connect.DcHelper; -import org.thoughtcrime.securesms.contacts.ContactSelectionListItem; -import org.thoughtcrime.securesms.mms.GlideRequests; -import org.thoughtcrime.securesms.util.DateUtils; -import org.thoughtcrime.securesms.util.StickyHeaderDecoration.StickyHeaderAdapter; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - -public class ProfileSettingsAdapter extends RecyclerView.Adapter - implements StickyHeaderAdapter -{ - public static final int INFO_VERIFIED = 118; - public static final int INFO_LAST_SEEN = 119; - public static final int INFO_SEND_MESSAGE_BUTTON = 120; - - private final @NonNull Context context; - private final @NonNull DcContext dcContext; - - private final @NonNull ArrayList itemData = new ArrayList<>(); - private int itemDataMemberCount; - private DcChatlist itemDataSharedChats; - private String itemDataStatusText; - private boolean isMailingList; - private boolean isBroadcast; - private final Set selectedMembers; - - private final LayoutInflater layoutInflater; - private final ItemClickListener clickListener; - private final GlideRequests glideRequests; - - static class ItemData { - static final int CATEGORY_INFO = 1; - static final int CATEGORY_SIGNATURE = 2; - static final int CATEGORY_MEMBERS = 3; - static final int CATEGORY_SHARED_CHATS = 4; - final int type; - final int contactId; - final int chatlistIndex; - final int settingsId; - final String label; - final int labelColor; - final int iconLeft; - - ItemData(int type, int settingsId, String label, int labelColor, int iconLeft) { - this(type, 0, 0, settingsId, label, labelColor, iconLeft); - } - - ItemData(int type, int contactId, int chatlistIndex) { - this(type, contactId, chatlistIndex, 0, null, 0, 0); - } - - ItemData(int type, int contactId, int chatlistIndex, int settingsId, @Nullable String label, int labelColor, int iconLeft) { - this.type = type; - this.contactId = contactId; - this.chatlistIndex = chatlistIndex; - this.settingsId = settingsId; - this.label = label; - this.labelColor = labelColor; - this.iconLeft = iconLeft; - } - }; - - public ProfileSettingsAdapter(@NonNull Context context, - @NonNull GlideRequests glideRequests, - @Nullable ItemClickListener clickListener) - { - super(); - this.context = context; - this.glideRequests = glideRequests; - this.clickListener = clickListener; - this.dcContext = DcHelper.getContext(context); - this.layoutInflater = LayoutInflater.from(context); - this.selectedMembers= new HashSet<>(); - } - - @Override - public int getItemCount() { - return itemData.size(); - } - - public static class ViewHolder extends RecyclerView.ViewHolder { - public ViewHolder(View itemView) { - super(itemView); - } - } - - static class HeaderViewHolder extends RecyclerView.ViewHolder { - final TextView textView; - HeaderViewHolder(View itemView) { - super(itemView); - textView = itemView.findViewById(R.id.label); - } - } - - @NonNull - @Override - public ProfileSettingsAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - if (viewType == ItemData.CATEGORY_MEMBERS) { - final ContactSelectionListItem item = (ContactSelectionListItem)layoutInflater.inflate(R.layout.contact_selection_list_item, parent, false); - item.setNoHeaderPadding(); - return new ViewHolder(item); - } - else if (viewType == ItemData.CATEGORY_SHARED_CHATS) { - final ConversationListItem item = (ConversationListItem)layoutInflater.inflate(R.layout.conversation_list_item_view, parent, false); - item.hideItemDivider(); - return new ViewHolder(item); - } - else if (viewType == ItemData.CATEGORY_SIGNATURE) { - final ProfileStatusItem item = (ProfileStatusItem)layoutInflater.inflate(R.layout.profile_status_item, parent, false); - return new ViewHolder(item); - } - else { - final ProfileSettingsItem item = (ProfileSettingsItem)layoutInflater.inflate(R.layout.profile_settings_item, parent, false); - return new ViewHolder(item); - } - } - - @Override - public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) { - ViewHolder holder = (ViewHolder) viewHolder; - if (holder.itemView instanceof ContactSelectionListItem) { - ContactSelectionListItem contactItem = (ContactSelectionListItem) holder.itemView; - - int contactId = itemData.get(i).contactId; - DcContact dcContact = null; - String label = null; - String name; - String addr = null; - - if (contactId == DcContact.DC_CONTACT_ID_ADD_MEMBER) { - if (isBroadcast) { - name = context.getString(R.string.add_recipients); - } else { - name = context.getString(R.string.group_add_members); - } - } - else if (contactId == DcContact.DC_CONTACT_ID_QR_INVITE) { - name = context.getString(R.string.qrshow_title); - } - else { - dcContact = dcContext.getContact(contactId); - name = dcContact.getDisplayName(); - addr = dcContact.getAddr(); - } - - contactItem.unbind(glideRequests); - contactItem.set(glideRequests, contactId, dcContact, name, addr, label, false, true); - contactItem.setSelected(selectedMembers.contains(contactId)); - contactItem.setOnClickListener(view -> clickListener.onMemberClicked(contactId)); - contactItem.setOnLongClickListener(view -> {clickListener.onMemberLongClicked(contactId); return true;}); - } - else if (holder.itemView instanceof ConversationListItem) { - ConversationListItem conversationListItem = (ConversationListItem) holder.itemView; - int chatlistIndex = itemData.get(i).chatlistIndex; - - int chatId = itemDataSharedChats.getChatId(chatlistIndex); - DcChat chat = dcContext.getChat(chatId); - DcLot summary = itemDataSharedChats.getSummary(chatlistIndex, chat); - - conversationListItem.bind(DcHelper.getThreadRecord(context, summary, chat), - itemDataSharedChats.getMsgId(chatlistIndex), summary, glideRequests, - Collections.emptySet(), false); - conversationListItem.setOnClickListener(view -> clickListener.onSharedChatClicked(chatId)); - } - else if(holder.itemView instanceof ProfileStatusItem) { - ProfileStatusItem item = (ProfileStatusItem) holder.itemView; - item.setOnLongClickListener(view -> {clickListener.onStatusLongClicked(); return true;}); - item.set(itemData.get(i).label); - } - else if(holder.itemView instanceof ProfileSettingsItem) { - int settingsId = itemData.get(i).settingsId; - ProfileSettingsItem profileSettingsItem = (ProfileSettingsItem) holder.itemView; - profileSettingsItem.setOnClickListener(view -> clickListener.onSettingsClicked(settingsId)); - profileSettingsItem.set(itemData.get(i).label, itemData.get(i).labelColor, itemData.get(i).iconLeft); - } - } - - @Override - public int getItemViewType(int i) { - return itemData.get(i).type; - } - - public interface ItemClickListener { - void onSettingsClicked(int settingsId); - void onStatusLongClicked(); - void onSharedChatClicked(int chatId); - void onMemberClicked(int contactId); - void onMemberLongClicked(int contactId); - } - - @Override - public long getHeaderId(int position) { - return getItemViewType(position); - } - - @Override - public HeaderViewHolder onCreateHeaderViewHolder(ViewGroup parent) { - return new HeaderViewHolder(LayoutInflater.from(context).inflate(R.layout.contact_selection_list_divider, parent, false)); - } - - @Override - public void onBindHeaderViewHolder(HeaderViewHolder viewHolder, int position) { - String txt = ""; - switch(getItemViewType(position)) { - case ItemData.CATEGORY_MEMBERS: - if (isMailingList) { - txt = context.getString(R.string.contacts_headline); - } else if (isBroadcast) { - txt = context.getResources().getQuantityString(R.plurals.n_recipients, (int) itemDataMemberCount, (int) itemDataMemberCount); - } else { - txt = context.getResources().getQuantityString(R.plurals.n_members, (int) itemDataMemberCount, (int) itemDataMemberCount); - } - break; - case ItemData.CATEGORY_SHARED_CHATS: - txt = context.getString(R.string.profile_shared_chats); - break; - case ItemData.CATEGORY_INFO: - txt = context.getString(R.string.info); - break; - case ItemData.CATEGORY_SIGNATURE: - txt = context.getString(R.string.pref_default_status_label); - break; - default: - txt = context.getString(R.string.menu_settings); - break; - } - viewHolder.textView.setText(txt); - } - - public void toggleMemberSelection(int contactId) { - if (!selectedMembers.remove(contactId)) { - selectedMembers.add(contactId); - } - notifyDataSetChanged(); - } - - @NonNull - public Collection getSelectedMembers() { - return new HashSet<>(selectedMembers); - } - - public int getSelectedMembersCount() { - return selectedMembers.size(); - } - - @NonNull - public String getStatusText() { - return itemDataStatusText; - } - - public void clearSelection() { - selectedMembers.clear(); - notifyDataSetChanged(); - } - - public void changeData(@Nullable int[] memberList, @Nullable DcContact dcContact, @Nullable DcChatlist sharedChats, @Nullable DcChat dcChat) { - itemData.clear(); - itemDataMemberCount = 0; - itemDataSharedChats = null; - itemDataStatusText = ""; - isMailingList = false; - isBroadcast = false; - - if (memberList!=null) { - itemDataMemberCount = memberList.length; - if (dcChat != null) { - if (dcChat.isBroadcast()) { - isBroadcast = true; - } - - if (dcChat.isMailingList()) { - isMailingList = true; - } else if (dcChat.canSend() && dcChat.isEncrypted()) { - itemData.add(new ItemData(ItemData.CATEGORY_MEMBERS, DcContact.DC_CONTACT_ID_ADD_MEMBER, 0)); - if (!isBroadcast) { - itemData.add(new ItemData(ItemData.CATEGORY_MEMBERS, DcContact.DC_CONTACT_ID_QR_INVITE, 0)); - } - } - } - - for (int value : memberList) { - itemData.add(new ItemData(ItemData.CATEGORY_MEMBERS, value, 0)); - } - } - else if (sharedChats!=null && dcContact!=null) { - boolean chatIsDeviceTalk = dcChat != null && dcChat.isDeviceTalk(); - - if (!chatIsDeviceTalk) { - int verifierId = dcContact.getVerifierId(); - if (verifierId != 0) { - String verifiedInfo; - if (verifierId == DcContact.DC_CONTACT_ID_SELF) { - verifiedInfo = context.getString(R.string.verified_by_you); - } else { - verifiedInfo = context.getString(R.string.verified_by, dcContext.getContact(verifierId).getDisplayName()); - } - itemData.add(new ItemData(ItemData.CATEGORY_INFO, INFO_VERIFIED, verifiedInfo, 0, R.drawable.ic_verified)); - } - - long lastSeenTimestamp = dcContact.getLastSeen(); - String lastSeenTxt; - if (lastSeenTimestamp == 0) { - lastSeenTxt = context.getString(R.string.last_seen_unknown); - } - else { - lastSeenTxt = context.getString(R.string.last_seen_at, DateUtils.getExtendedTimeSpanString(context, lastSeenTimestamp)); - } - itemData.add(new ItemData(ItemData.CATEGORY_INFO, INFO_LAST_SEEN, lastSeenTxt, 0, 0)); - - - itemData.add(new ItemData(ItemData.CATEGORY_INFO, INFO_SEND_MESSAGE_BUTTON, context.getString(R.string.send_message), R.color.delta_accent, 0)); - } - - itemDataStatusText = dcContact.getStatus(); - if (!itemDataStatusText.isEmpty()) { - itemData.add(new ItemData(ItemData.CATEGORY_SIGNATURE, 0, itemDataStatusText, 0, 0)); - } - - itemDataSharedChats = sharedChats; - if (!chatIsDeviceTalk) { - int sharedChatsCnt = sharedChats.getCnt(); - for (int i = 0; i < sharedChatsCnt; i++) { - itemData.add(new ItemData(ItemData.CATEGORY_SHARED_CHATS, 0, i)); - } - } - } - - notifyDataSetChanged(); - } -} diff --git a/src/main/java/org/thoughtcrime/securesms/ProfileSettingsItem.java b/src/main/java/org/thoughtcrime/securesms/ProfileSettingsItem.java deleted file mode 100644 index 8b113c29d..000000000 --- a/src/main/java/org/thoughtcrime/securesms/ProfileSettingsItem.java +++ /dev/null @@ -1,41 +0,0 @@ -package org.thoughtcrime.securesms; - -import android.content.Context; -import android.util.AttributeSet; -import android.widget.LinearLayout; -import android.widget.TextView; - -import androidx.core.content.ContextCompat; - -import org.thoughtcrime.securesms.util.ResUtil; - -public class ProfileSettingsItem extends LinearLayout { - - private TextView labelView; - - public ProfileSettingsItem(Context context) { - super(context); - } - - public ProfileSettingsItem(Context context, AttributeSet attrs) { - super(context, attrs); - } - - @Override - protected void onFinishInflate() { - super.onFinishInflate(); - labelView = findViewById(R.id.label); - } - - public void set(String label, int labelColor, int iconLeft) { - labelView.setText(label==null? "" : label); - labelView.setCompoundDrawablesWithIntrinsicBounds(iconLeft, 0,0,0); - - // we need different color getters as `labelColor` is `R.color.name` while default is `R.attr.name` - if (labelColor != 0) { - labelView.setTextColor(ContextCompat.getColor(getContext(), labelColor)); - } else { - labelView.setTextColor(ResUtil.getColor(getContext(), R.attr.emoji_text_color)); - } - } -} diff --git a/src/main/java/org/thoughtcrime/securesms/ProfileTextItem.java b/src/main/java/org/thoughtcrime/securesms/ProfileTextItem.java new file mode 100644 index 000000000..d75082c04 --- /dev/null +++ b/src/main/java/org/thoughtcrime/securesms/ProfileTextItem.java @@ -0,0 +1,57 @@ +package org.thoughtcrime.securesms; + +import android.content.Context; +import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; +import androidx.core.graphics.drawable.DrawableCompat; + +import org.thoughtcrime.securesms.util.ResUtil; + +public class ProfileTextItem extends LinearLayout { + + private TextView labelView; + private @Nullable TextView valueView; + + public ProfileTextItem(Context context) { + super(context); + } + + public ProfileTextItem(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + labelView = findViewById(R.id.label); + valueView = findViewById(R.id.value); + } + + public void set(String label, int icon) { + labelView.setText(label); + + if (icon != 0) { + Drawable orgDrawable = ContextCompat.getDrawable(getContext(), icon); + if (orgDrawable != null) { + Drawable drawable = orgDrawable.mutate(); // avoid global state modification and showing eg. app-icon tinted also elsewhere + drawable = DrawableCompat.wrap(drawable); + DrawableCompat.setTint(drawable, getResources().getColor(R.color.delta_accent)); + labelView.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null); + } + } + } + + public void setValue(String value) { + if (valueView != null) { + valueView.setText(value); + valueView.setVisibility(View.VISIBLE); + } + } +} diff --git a/src/main/java/org/thoughtcrime/securesms/contacts/ContactSelectionListItem.java b/src/main/java/org/thoughtcrime/securesms/contacts/ContactSelectionListItem.java index 83959ecad..943ee3901 100644 --- a/src/main/java/org/thoughtcrime/securesms/contacts/ContactSelectionListItem.java +++ b/src/main/java/org/thoughtcrime/securesms/contacts/ContactSelectionListItem.java @@ -163,9 +163,4 @@ public class ContactSelectionListItem extends LinearLayout implements RecipientM }); } } - - public void setNoHeaderPadding() { - int paddinglr = getContext().getResources().getDimensionPixelSize(R.dimen.contact_list_normal_padding); - setPadding(paddinglr, 0, paddinglr, 0); - } } diff --git a/src/main/res/layout/all_media_activity.xml b/src/main/res/layout/all_media_activity.xml new file mode 100644 index 000000000..d2c2e1a7a --- /dev/null +++ b/src/main/res/layout/all_media_activity.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + diff --git a/src/main/res/layout/avatar_view.xml b/src/main/res/layout/avatar_view.xml index f175f8c8b..cb28e84dc 100644 --- a/src/main/res/layout/avatar_view.xml +++ b/src/main/res/layout/avatar_view.xml @@ -25,6 +25,8 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="@+id/top_guideline" app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintWidth_max="34dp" + app:layout_constraintHeight_max="34dp" android:src="@drawable/ic_circle_status_online" android:contentDescription="@null" diff --git a/src/main/res/layout/contact_selection_list_item.xml b/src/main/res/layout/contact_selection_list_item.xml index 0d2f5243f..2b01e070c 100644 --- a/src/main/res/layout/contact_selection_list_item.xml +++ b/src/main/res/layout/contact_selection_list_item.xml @@ -8,8 +8,8 @@ android:gravity="center_vertical" android:focusable="true" android:background="?attr/conversation_list_item_background" - android:paddingLeft="24dp" - android:paddingRight="24dp"> + android:paddingLeft="16dp" + android:paddingRight="16dp"> - - - - diff --git a/src/main/res/layout/profile_avatar_item.xml b/src/main/res/layout/profile_avatar_item.xml new file mode 100644 index 000000000..ab7ed97bb --- /dev/null +++ b/src/main/res/layout/profile_avatar_item.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + diff --git a/src/main/res/layout/profile_divider.xml b/src/main/res/layout/profile_divider.xml new file mode 100644 index 000000000..a1458c441 --- /dev/null +++ b/src/main/res/layout/profile_divider.xml @@ -0,0 +1,14 @@ + + + + + + diff --git a/src/main/res/layout/profile_settings_fragment.xml b/src/main/res/layout/profile_fragment.xml similarity index 100% rename from src/main/res/layout/profile_settings_fragment.xml rename to src/main/res/layout/profile_fragment.xml diff --git a/src/main/res/layout/profile_settings_item.xml b/src/main/res/layout/profile_settings_item.xml deleted file mode 100644 index 1a57eec3a..000000000 --- a/src/main/res/layout/profile_settings_item.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/main/res/layout/profile_status_item.xml b/src/main/res/layout/profile_status_item.xml index fbeace308..0dc5e6158 100644 --- a/src/main/res/layout/profile_status_item.xml +++ b/src/main/res/layout/profile_status_item.xml @@ -4,15 +4,18 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:focusable="true" - android:padding="16dp"> + android:paddingTop="8dp" + android:paddingBottom="8dp"> + android:textColorLink="?attr/emoji_text_color" + android:background="?attr/contact_list_divider"/> diff --git a/src/main/res/layout/profile_text_item.xml b/src/main/res/layout/profile_text_item.xml new file mode 100644 index 000000000..bd7e2b9f2 --- /dev/null +++ b/src/main/res/layout/profile_text_item.xml @@ -0,0 +1,19 @@ + + + + + + diff --git a/src/main/res/layout/profile_text_item_button.xml b/src/main/res/layout/profile_text_item_button.xml new file mode 100644 index 000000000..027cf5180 --- /dev/null +++ b/src/main/res/layout/profile_text_item_button.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + diff --git a/src/main/res/layout/profile_text_item_small.xml b/src/main/res/layout/profile_text_item_small.xml new file mode 100644 index 000000000..5db68843f --- /dev/null +++ b/src/main/res/layout/profile_text_item_small.xml @@ -0,0 +1,22 @@ + + + + + + diff --git a/src/main/res/menu/conversation.xml b/src/main/res/menu/conversation.xml index d21b28434..2cbf9a2c9 100644 --- a/src/main/res/menu/conversation.xml +++ b/src/main/res/menu/conversation.xml @@ -25,10 +25,10 @@ android:visible="false" app:showAsAction="always"/> - + app:showAsAction="always" /> diff --git a/src/main/res/menu/profile_common.xml b/src/main/res/menu/profile_common.xml index 2ae4969d3..7ec7330a6 100644 --- a/src/main/res/menu/profile_common.xml +++ b/src/main/res/menu/profile_common.xml @@ -8,7 +8,8 @@ + android:icon="@drawable/ic_create_white_24dp" + app:showAsAction="always"/>