Skip to content

Commit

Permalink
Tap avatar in chat preferences or group management to see full screen.
Browse files Browse the repository at this point in the history
  • Loading branch information
alan-signal authored and greyson-signal committed May 29, 2020
1 parent 0711a22 commit 69adcd1
Show file tree
Hide file tree
Showing 5 changed files with 222 additions and 13 deletions.
7 changes: 6 additions & 1 deletion app/src/main/AndroidManifest.xml
Expand Up @@ -347,12 +347,17 @@
android:windowSoftInputMode="stateHidden"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>

<activity android:name=".MediaPreviewActivity"
<activity android:name=".MediaPreviewActivity"
android:label="@string/AndroidManifest__media_preview"
android:windowSoftInputMode="stateHidden"
android:launchMode="singleTask"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>

<activity android:name=".AvatarPreviewActivity"
android:label="@string/AndroidManifest__media_preview"
android:windowSoftInputMode="stateHidden"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>

<activity android:name=".mediaoverview.MediaOverviewActivity"
android:theme="@style/TextSecure.LightNoActionBar"
android:windowSoftInputMode="stateHidden"
Expand Down
@@ -0,0 +1,152 @@
package org.thoughtcrime.securesms;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityOptionsCompat;

import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.Target;

import org.thoughtcrime.securesms.contacts.avatars.ContactPhoto;
import org.thoughtcrime.securesms.contacts.avatars.FallbackContactPhoto;
import org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto;
import org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientId;

/**
* Activity for displaying avatars full screen.
*/
public final class AvatarPreviewActivity extends PassphraseRequiredActionBarActivity {

private static final String TAG = Log.tag(AvatarPreviewActivity.class);

private static final String RECIPIENT_ID_EXTRA = "recipient_id";

public static @NonNull Intent intentFromRecipientId(@NonNull Context context,
@NonNull RecipientId recipientId)
{
Intent intent = new Intent(context, AvatarPreviewActivity.class);
intent.putExtra(RECIPIENT_ID_EXTRA, recipientId.serialize());
return intent;
}

public static Bundle createTransitionBundle(@NonNull Activity activity, @NonNull View from) {
return ActivityOptionsCompat.makeSceneTransitionAnimation(activity, from, "avatar").toBundle();
}

@Override
protected void onCreate(Bundle savedInstanceState, boolean ready) {
super.onCreate(savedInstanceState, ready);

setTheme(R.style.TextSecure_MediaPreview);
setContentView(R.layout.contact_photo_preview_activity);

Toolbar toolbar = findViewById(R.id.toolbar);
ImageView avatar = findViewById(R.id.avatar);

setSupportActionBar(toolbar);

getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);

showSystemUI();

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

Context context = getApplicationContext();
RecipientId recipientId = RecipientId.from(getIntent().getStringExtra(RECIPIENT_ID_EXTRA));

Recipient.live(recipientId).observe(this, recipient -> {
ContactPhoto contactPhoto = recipient.isLocalNumber() ? new ProfileContactPhoto(recipient, recipient.getProfileAvatar())
: recipient.getContactPhoto();
FallbackContactPhoto fallbackPhoto = recipient.isLocalNumber() ? new ResourceContactPhoto(R.drawable.ic_profile_outline_40, R.drawable.ic_profile_outline_20, R.drawable.ic_person_large)
: recipient.getFallbackContactPhoto();

GlideApp.with(this).load(contactPhoto)
.fallback(fallbackPhoto.asCallCard(this))
.error(fallbackPhoto.asCallCard(this))
.diskCacheStrategy(DiskCacheStrategy.ALL)
.addListener(new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
Log.w(TAG, "Unable to load avatar, or avatar removed, closing");
finish();
return false;
}

@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
return false;
}
})
.into(avatar);

toolbar.setTitle(recipient.toShortString(context));
});

avatar.setOnClickListener(v -> toggleUiVisibility());

showAndHideWithSystemUI(getWindow(), findViewById(R.id.toolbar_layout));
}

private static void showAndHideWithSystemUI(@NonNull Window window, @NonNull View... views) {
window.getDecorView().setOnSystemUiVisibilityChangeListener(visibility -> {
boolean hide = (visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;

for (View view : views) {
view.animate()
.alpha(hide ? 0 : 1)
.start();
}
});
}

private void toggleUiVisibility() {
int systemUiVisibility = getWindow().getDecorView().getSystemUiVisibility();
if ((systemUiVisibility & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0) {
showSystemUI();
} else {
hideSystemUI();
}
}

private void hideSystemUI() {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_IMMERSIVE |
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_FULLSCREEN );
}

private void showSystemUI() {
getWindow().getDecorView().setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN );
}

@Override
public boolean onSupportNavigateUp() {
onBackPressed();
return true;
}
}
Expand Up @@ -5,6 +5,7 @@
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
Expand Down Expand Up @@ -35,7 +36,11 @@
import androidx.preference.PreferenceCategory;
import androidx.recyclerview.widget.RecyclerView;

import com.bumptech.glide.load.DataSource;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.load.engine.GlideException;
import com.bumptech.glide.request.RequestListener;
import com.bumptech.glide.request.target.Target;
import com.google.android.material.appbar.CollapsingToolbarLayout;

import org.thoughtcrime.securesms.color.MaterialColor;
Expand Down Expand Up @@ -69,7 +74,6 @@
import org.thoughtcrime.securesms.recipients.RecipientUtil;
import org.thoughtcrime.securesms.util.CommunicationActions;
import org.thoughtcrime.securesms.util.DynamicDarkToolbarTheme;
import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.FeatureFlags;
import org.thoughtcrime.securesms.util.IdentityUtil;
Expand Down Expand Up @@ -100,8 +104,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
private static final String PREFERENCE_ABOUT = "pref_key_number";
private static final String PREFERENCE_CUSTOM_NOTIFICATIONS = "pref_key_recipient_custom_notifications";

private final DynamicTheme dynamicTheme = new DynamicDarkToolbarTheme();
private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
private final DynamicTheme dynamicTheme = new DynamicDarkToolbarTheme();

private ImageView avatar;
private GlideRequests glideRequests;
Expand All @@ -120,7 +123,6 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
@Override
public void onPreCreate() {
dynamicTheme.onCreate(this);
dynamicLanguage.onCreate(this);
}

@Override
Expand All @@ -135,14 +137,13 @@ public void onCreate(Bundle instanceState, boolean ready) {
setHeader(recipient.get());
recipient.observe(this, this::setHeader);

getSupportLoaderManager().initLoader(0, null, this);
LoaderManager.getInstance(this).initLoader(0, null, this);
}

@Override
public void onResume() {
super.onResume();
dynamicTheme.onResume(this);
dynamicLanguage.onResume(this);
}

@Override
Expand All @@ -165,10 +166,10 @@ public boolean onOptionsItemSelected(MenuItem item) {
}

private void initializeToolbar() {
this.toolbarLayout = ViewUtil.findById(this, R.id.collapsing_toolbar);
this.avatar = ViewUtil.findById(this, R.id.avatar);
this.threadPhotoRailView = ViewUtil.findById(this, R.id.recent_photos);
this.threadPhotoRailLabel = ViewUtil.findById(this, R.id.rail_label);
this.toolbarLayout = findViewById(R.id.collapsing_toolbar);
this.avatar = findViewById(R.id.avatar);
this.threadPhotoRailView = findViewById(R.id.recent_photos);
this.threadPhotoRailLabel = findViewById(R.id.rail_label);

this.toolbarLayout.setExpandedTitleColor(ThemeUtil.getThemedColor(this, R.attr.conversation_title_color));
this.toolbarLayout.setCollapsedTitleTextColor(ThemeUtil.getThemedColor(this, R.attr.conversation_title_color));
Expand All @@ -189,7 +190,7 @@ private void initializeToolbar() {
}
);

Toolbar toolbar = ViewUtil.findById(this, R.id.toolbar);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setLogo(null);
Expand All @@ -215,6 +216,20 @@ private void setHeader(@NonNull Recipient recipient) {
.fallback(fallbackPhoto.asCallCard(this))
.error(fallbackPhoto.asCallCard(this))
.diskCacheStrategy(DiskCacheStrategy.ALL)
.addListener(new RequestListener<Drawable>() {
@Override
public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Drawable> target, boolean isFirstResource) {
avatar.setOnClickListener(null);
return false;
}

@Override
public boolean onResourceReady(Drawable resource, Object model, Target<Drawable> target, DataSource dataSource, boolean isFirstResource) {
avatar.setOnClickListener(v -> startActivity(AvatarPreviewActivity.intentFromRecipientId(RecipientPreferenceActivity.this, recipient.getId()),
AvatarPreviewActivity.createTransitionBundle(RecipientPreferenceActivity.this, avatar)));
return false;
}
})
.into(this.avatar);

if (contactPhoto == null) this.avatar.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
Expand Down
Expand Up @@ -22,6 +22,7 @@
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.ViewModelProviders;

import org.thoughtcrime.securesms.AvatarPreviewActivity;
import org.thoughtcrime.securesms.ContactSelectionListFragment;
import org.thoughtcrime.securesms.MediaPreviewActivity;
import org.thoughtcrime.securesms.MuteDialog;
Expand Down Expand Up @@ -189,7 +190,14 @@ public void onActivityCreated(@Nullable Bundle savedInstanceState) {
viewModel.getTitle().observe(getViewLifecycleOwner(), toolbar::setTitle);
viewModel.getMemberCountSummary().observe(getViewLifecycleOwner(), memberCountUnderAvatar::setText);
viewModel.getFullMemberCountSummary().observe(getViewLifecycleOwner(), memberCountAboveList::setText);
viewModel.getGroupRecipient().observe(getViewLifecycleOwner(), avatar::setRecipient);
viewModel.getGroupRecipient().observe(getViewLifecycleOwner(), groupRecipient -> {
avatar.setRecipient(groupRecipient);
avatar.setOnClickListener(v -> {
FragmentActivity activity = requireActivity();
activity.startActivity(AvatarPreviewActivity.intentFromRecipientId(activity, groupRecipient.getId()),
AvatarPreviewActivity.createTransitionBundle(activity, avatar));
});
});

viewModel.getGroupViewState().observe(getViewLifecycleOwner(), vs -> {
if (vs == null) return;
Expand Down
29 changes: 29 additions & 0 deletions app/src/main/res/layout/contact_photo_preview_activity.xml
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/core_grey_95">

<ImageView
android:id="@+id/avatar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:transitionName="avatar" />

<com.google.android.material.appbar.AppBarLayout
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/media_preview_bar_background"
app:elevation="0dp">

<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@android:color/transparent" />

</com.google.android.material.appbar.AppBarLayout>

</FrameLayout>

0 comments on commit 69adcd1

Please sign in to comment.