Skip to content
This repository has been archived by the owner on Jun 9, 2023. It is now read-only.

Large image previews #87

Merged
merged 8 commits into from
Jan 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [Unreleased]
### Added
- Large image previews ([#87](https://github.com/Tunous/Dawn/pull/87))

### Changed
- Renamed application to "Dawn" ([#74](https://github.com/Tunous/Dawn/pull/74))

Expand Down
23 changes: 17 additions & 6 deletions app/src/main/java/me/saket/dank/di/UserPreferencesModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import me.saket.dank.ui.preferences.NetworkStrategy;
import me.saket.dank.ui.preferences.TypefaceResource;
import me.saket.dank.ui.subreddit.SubmissionSwipeAction;
import me.saket.dank.ui.subreddit.uimodels.SubredditSubmissionImageStyle;
import me.saket.dank.utils.DeviceInfo;
import me.saket.dank.utils.RxPreferencesEnumListTypeAdapter;
import me.saket.dank.utils.RxPreferencesEnumTypeAdapter;
Expand Down Expand Up @@ -105,12 +106,6 @@ Observable<Object> provideUserPrefChanges(@Named("user_prefs") SharedPreferences

// ======== LOOK & FEEL ======== //

@Provides
@Named("show_submission_thumbnails")
Preference<Boolean> showSubmissionThumbnailsPref(@Named("user_prefs") RxSharedPreferences rxPrefs) {
return rxPrefs.getBoolean("show_submission_thumbnails", true);
}

@Provides
@Named("show_submission_thumbnails_on_left")
Preference<Boolean> showSubmissionThumbnailsOnLeftPref(@Named("user_prefs") RxSharedPreferences rxPrefs) {
Expand All @@ -128,6 +123,22 @@ Preference<Boolean> showColoredCommentsTreePref(@Named("user_prefs") RxSharedPre
return rxPrefs.getBoolean("show_colored_comments_tree", false);
}

@Provides
RxPreferencesEnumTypeAdapter<SubredditSubmissionImageStyle> subredditSubmissionImageStyleEnumTypeAdapter() {
return new RxPreferencesEnumTypeAdapter<>(SubredditSubmissionImageStyle.class);
}

@Provides
@Named("subreddit_submission_image_style")
Preference<SubredditSubmissionImageStyle> subredditSubmissionImageStylePref(
@Named("user_prefs") RxSharedPreferences rxPrefs,
RxPreferencesEnumTypeAdapter<SubredditSubmissionImageStyle> enumAdapter
) {
Boolean thumbnailsEnabledUsingOldPreference = rxPrefs.getBoolean("show_submission_thumbnails", true).get();
SubredditSubmissionImageStyle defaultStyle = thumbnailsEnabledUsingOldPreference ? SubredditSubmissionImageStyle.THUMBNAIL : SubredditSubmissionImageStyle.NONE;
return rxPrefs.getObject("subreddit_submission_image_style", defaultStyle, enumAdapter);
}

// ======== DATA USAGE ======== //

@Provides
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,18 @@ import me.saket.dank.R
import me.saket.dank.ui.preferences.MultiOptionPreferencePopup
import me.saket.dank.ui.preferences.TypefaceResource
import me.saket.dank.ui.subreddit.SubmissionSwipeAction
import me.saket.dank.ui.subreddit.uimodels.SubredditSubmissionImageStyle
import javax.inject.Inject
import javax.inject.Named

class LookAndFeelPreferencesConstructor @Inject constructor(
private val typefacePref: Preference<TypefaceResource>,
@Named("show_submission_thumbnails") private val showSubmissionThumbnails: Preference<Boolean>,
@Named("comment_count_in_submission_list_byline") private val showCommentCountInByline: Preference<Boolean>,
@Named("show_submission_thumbnails_on_left") private val showSubmissionThumbnailsOnLeft: Preference<Boolean>,
@Named("show_colored_comments_tree") private val showColoredCommentsTree: Preference<Boolean>,
@Named("submission_start_swipe_actions") private val submissionStartSwipeActions: Preference<List<SubmissionSwipeAction>>,
@Named("submission_end_swipe_actions") private val submissionEndSwipeActions: Preference<List<SubmissionSwipeAction>>
@Named("submission_end_swipe_actions") private val submissionEndSwipeActions: Preference<List<SubmissionSwipeAction>>,
@Named("subreddit_submission_image_style") private val subredditSubmissionImageStyle: Preference<SubredditSubmissionImageStyle>
) : UserPreferencesConstructor.ChildConstructor {

override fun construct(c: Context): List<UserPreferencesScreenUiModel> {
Expand Down Expand Up @@ -64,28 +65,30 @@ class LookAndFeelPreferencesConstructor @Inject constructor(

uiModels.add(UserPreferenceSectionHeader.UiModel.create(c.getString(R.string.userprefs_group_subreddit)))

uiModels.add(
UserPreferenceSwitch.UiModel(
c.getString(R.string.userprefs_submission_thumbnails),
if (showSubmissionThumbnails.get())
c.getString(R.string.userprefs_submission_thumbnail_summary_on)
else
c.getString(R.string.userprefs_submission_thumbnail_summary_off),
showSubmissionThumbnails.get(),
showSubmissionThumbnails
)
)
uiModels.add(UserPreferenceButton.UiModel.create(
c.getString(R.string.userprefs_submission_image_style),
c.getString(subredditSubmissionImageStyle.get().userVisibleName)
) { clickHandler, event ->
val builder = MultiOptionPreferencePopup.builder(subredditSubmissionImageStyle)
builder.addOption(SubredditSubmissionImageStyle.NONE, R.string.image_style_disabled, R.drawable.ic_block_20dp)
builder.addOption(SubredditSubmissionImageStyle.THUMBNAIL, R.string.image_style_thumbnail, R.drawable.ic_image_style_thumbnail_20dp)
builder.addOption(SubredditSubmissionImageStyle.LARGE, R.string.image_style_large, R.drawable.ic_image_style_large_20dp)
clickHandler.show(builder, event.itemViewHolder())
})

uiModels.add(
UserPreferenceSwitch.UiModel(
c.getString(R.string.userprefs_show_submission_thumbnails_on_left),
if (subredditSubmissionImageStyle.get() == SubredditSubmissionImageStyle.THUMBNAIL)
c.getString(R.string.userprefs_show_submission_thumbnails_on_left)
else
c.getString(R.string.userprefs_show_submission_type_indicator_on_left),
if (showSubmissionThumbnailsOnLeft.get())
c.getString(R.string.userprefs_show_submission_thumbnails_on_left_summary_on)
else
c.getString(R.string.userprefs_show_submission_thumbnails_on_left_summary_off),
showSubmissionThumbnailsOnLeft.get(),
showSubmissionThumbnailsOnLeft,
showSubmissionThumbnails.get()
subredditSubmissionImageStyle.get() != SubredditSubmissionImageStyle.NONE
)
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ object SubmissionItemDiffer : DiffUtil.ItemCallback<SubmissionRowUiModel>() {
if (oldSubmission.byline() != newSubmission.byline()) {
partialChanges.add(SubredditSubmission.PartialChange.BYLINE)
}
if (oldSubmission.thumbnail() != newSubmission.thumbnail()) {
if (oldSubmission.thumbnail() != newSubmission.thumbnail() || oldSubmission.imageStyle() != newSubmission.imageStyle()) {
partialChanges.add(SubredditSubmission.PartialChange.THUMBNAIL)
}
if (oldSubmission.isSaved != newSubmission.isSaved) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
import me.saket.dank.ui.subreddit.events.SubredditSubmissionThumbnailClickEvent;
import me.saket.dank.utils.Optional;
import me.saket.dank.utils.Pair;
import me.saket.dank.utils.glide.GlideCircularTransformation;
import me.saket.dank.widgets.swipe.SwipeActions;
import me.saket.dank.widgets.swipe.SwipeableLayout;
import me.saket.dank.widgets.swipe.ViewHolderWithSwipeActions;
Expand Down Expand Up @@ -76,6 +75,8 @@ public Type type() {

public abstract boolean displayThumbnailOnLeftSide();

public abstract SubredditSubmissionImageStyle imageStyle();

public abstract SwipeActions swipeActions();

public static Builder builder() {
Expand Down Expand Up @@ -110,6 +111,8 @@ public Builder byline(CharSequence byline, Integer commentsCount) {

public abstract Builder displayThumbnailOnLeftSide(boolean displayThumbnailOnLeftSide);

public abstract Builder imageStyle(SubredditSubmissionImageStyle imageStyle);

public abstract Builder swipeActions(SwipeActions swipeActions);

public abstract UiModel build();
Expand Down Expand Up @@ -154,6 +157,7 @@ public abstract static class Builder {

class ViewHolder extends RecyclerView.ViewHolder implements ViewHolderWithSwipeActions {
private final ImageView thumbnailView;
private final ImageView imageView;
private final TextView titleView;
private final TextView bylineView;
private final ConstraintLayout contentContainerConstraintLayout;
Expand All @@ -164,6 +168,7 @@ class ViewHolder extends RecyclerView.ViewHolder implements ViewHolderWithSwipeA
protected ViewHolder(View itemView) {
super(itemView);
thumbnailView = itemView.findViewById(R.id.submission_item_icon);
imageView = itemView.findViewById(R.id.submission_item_image);
titleView = itemView.findViewById(R.id.submission_item_title);
bylineView = itemView.findViewById(R.id.submission_item_byline);

Expand All @@ -188,6 +193,7 @@ public void render() {
bylineView.setText(uiModel.byline());

Glide.with(thumbnailView).clear(thumbnailView);
Glide.with(imageView).clear(imageView);
setThumbnail(uiModel.thumbnail());

if (uiModel.backgroundDrawableRes().isPresent()) {
Expand Down Expand Up @@ -240,7 +246,9 @@ private void setConstraints(boolean displayThumbnailsOnLeftSide) {
}

private void setThumbnail(Optional<UiModel.Thumbnail> optionalThumbnail) {
thumbnailView.setVisibility(uiModel.thumbnail().isPresent() ? View.VISIBLE : View.GONE);
int visibility = uiModel.thumbnail().isPresent() ? View.VISIBLE : View.GONE;
thumbnailView.setVisibility(visibility);
imageView.setVisibility(visibility);

optionalThumbnail.ifPresent(thumb -> {
thumbnailView.setBackgroundResource(thumb.backgroundRes().orElse(0));
Expand All @@ -254,13 +262,32 @@ private void setThumbnail(Optional<UiModel.Thumbnail> optionalThumbnail) {
}

if (thumb.staticRes().isPresent()) {
imageView.setVisibility(View.GONE);
thumbnailView.setImageResource(thumb.staticRes().get());

} else {
Glide.with(itemView)
.load(thumb.remoteUrl().get())
.apply(RequestOptions.bitmapTransform(GlideCircularTransformation.INSTANCE))
.transition(DrawableTransitionOptions.withCrossFade())
.into(thumbnailView);
switch (uiModel.imageStyle()) {
case NONE:
imageView.setVisibility(View.GONE);
thumbnailView.setVisibility(View.GONE);
break;
case THUMBNAIL:
imageView.setVisibility(View.GONE);
Glide.with(itemView)
.load(thumb.remoteUrl().get())
.apply(RequestOptions.circleCropTransform())
.transition(DrawableTransitionOptions.withCrossFade())
.into(thumbnailView);
break;
case LARGE:
thumbnailView.setVisibility(View.GONE);
Glide.with(itemView)
.load(thumb.remoteUrl().get())
.apply(RequestOptions.centerCropTransform())
.transition(DrawableTransitionOptions.withCrossFade())
.into(imageView);
break;
}
}
});
}
Expand All @@ -287,13 +314,15 @@ public ViewHolder onCreateViewHolder(LayoutInflater inflater, ViewGroup parent)
holder.itemView.setOnClickListener(o ->
submissionClicks.accept(SubredditSubmissionClickEvent.create(holder.uiModel.submission(), holder.itemView, holder.getItemId()))
);
holder.thumbnailView.setOnClickListener(o -> {
View.OnClickListener imageClickListener = o -> {
if (holder.uiModel.isThumbnailClickable()) {
thumbnailClicks.accept(SubredditSubmissionThumbnailClickEvent.create(holder.uiModel.submission(), holder.itemView, holder.thumbnailView));
} else {
holder.itemView.performClick();
}
});
};
holder.imageView.setOnClickListener(imageClickListener);
holder.thumbnailView.setOnClickListener(imageClickListener);

SwipeableLayout swipeableLayout = holder.getSwipeableLayout();
swipeableLayout.setSwipeActionIconProvider((imageView, oldAction, newAction) ->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package me.saket.dank.ui.subreddit.uimodels

import androidx.annotation.StringRes
import me.saket.dank.R

enum class SubredditSubmissionImageStyle {
NONE,
THUMBNAIL,
LARGE;

val userVisibleName: Int
@StringRes get() {
return when (this) {
NONE -> R.string.image_style_disabled
THUMBNAIL -> R.string.image_style_thumbnail
LARGE -> R.string.image_style_large
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ public class SubredditUiConstructor {
private final Lazy<SubmissionGesturesWalkthrough> gesturesWalkthrough;
private final Preference<Boolean> showCommentCountInByline;
private final Preference<Boolean> showNsfwContent;
private final Preference<Boolean> showThumbnailsPref;
private final Preference<Boolean> showSubmissionThumbnailsOnLeft;
private final Preference<SubredditSubmissionImageStyle> subredditSubmissionImageStyle;
private final ErrorResolver errorResolver;
private final Lazy<BookmarksRepository> bookmarksRepository;
private final Lazy<SubmissionSwipeActionsRepository> swipeActionsRepository;
Expand All @@ -70,8 +70,8 @@ public SubredditUiConstructor(
Lazy<SubmissionGesturesWalkthrough> gesturesWalkthrough,
@Named("comment_count_in_submission_list_byline") Preference<Boolean> showCommentCountInByline,
@Named("show_nsfw_content") Preference<Boolean> showNsfwContent,
@Named("show_submission_thumbnails") Preference<Boolean> showThumbnailsPref,
@Named("show_submission_thumbnails_on_left") Preference<Boolean> showSubmissionThumbnailsOnLeft,
@Named("subreddit_submission_image_style") Preference<SubredditSubmissionImageStyle> subredditSubmissionImageStyle,
Lazy<SubmissionSwipeActionsRepository> swipeActionsRepository
) {
this.votingManager = votingManager;
Expand All @@ -80,8 +80,8 @@ public SubredditUiConstructor(
this.gesturesWalkthrough = gesturesWalkthrough;
this.showCommentCountInByline = showCommentCountInByline;
this.showNsfwContent = showNsfwContent;
this.showThumbnailsPref = showThumbnailsPref;
this.showSubmissionThumbnailsOnLeft = showSubmissionThumbnailsOnLeft;
this.subredditSubmissionImageStyle = subredditSubmissionImageStyle;
this.swipeActionsRepository = swipeActionsRepository;
}

Expand All @@ -93,11 +93,11 @@ public Observable<SubredditScreenUiModel> stream(
Observable<CachedSubmissionFolder> submissionFolderStream)
{
Observable<?> userPrefChanges = Observable
.merge(
.merge(Arrays.asList(
showCommentCountInByline.asObservable(),
showNsfwContent.asObservable(),
showThumbnailsPref.asObservable(),
showSubmissionThumbnailsOnLeft.asObservable()
showSubmissionThumbnailsOnLeft.asObservable(),
subredditSubmissionImageStyle.asObservable())
)
.skip(1); // Skip initial values.

Expand Down Expand Up @@ -300,7 +300,7 @@ public SubredditSubmission.UiModel submissionUiModel(
SubmissionThumbnailTypeMinusNsfw thumbnailType = SubmissionThumbnailTypeMinusNsfw.Companion.parse(submission);
Optional<SubredditSubmission.UiModel.Thumbnail> thumbnail;

if (!showThumbnailsPref.get()) {
if (subredditSubmissionImageStyle.get().equals(SubredditSubmissionImageStyle.NONE)) {
thumbnail = Optional.empty();

} else if (thumbnailType == SubmissionThumbnailTypeMinusNsfw.NONE) {
Expand Down Expand Up @@ -387,6 +387,7 @@ public SubredditSubmission.UiModel submissionUiModel(
.thumbnail(thumbnail)
.isThumbnailClickable(isThumbnailClickable)
.displayThumbnailOnLeftSide(showSubmissionThumbnailsOnLeft.get())
.imageStyle(subredditSubmissionImageStyle.get())
.title(titleBuilder.build(), Pair.create(submissionScore, voteDirection))
.byline(bylineBuilder.build(), postedAndPendingCommentCount)
.backgroundDrawableRes(rowBackgroundResource)
Expand All @@ -406,7 +407,8 @@ private SubredditSubmission.UiModel.Thumbnail.Builder thumbnailForStaticImage(Co

private SubredditSubmission.UiModel.Thumbnail thumbnailForRemoteImage(Context c, SubmissionPreview preview) {
ImageWithMultipleVariants redditThumbnails = ImageWithMultipleVariants.Companion.of(preview);
String optimizedThumbnailUrl = redditThumbnails.findNearestFor(c.getResources().getDimensionPixelSize(R.dimen.subreddit_submission_thumbnail));
int preferredWidth = getPreferredWidthForThumbnail(c);
String optimizedThumbnailUrl = redditThumbnails.findNearestFor(preferredWidth);

return SubredditSubmission.UiModel.Thumbnail.builder()
.staticRes(Optional.empty())
Expand All @@ -417,4 +419,11 @@ private SubredditSubmission.UiModel.Thumbnail thumbnailForRemoteImage(Context c,
.backgroundRes(Optional.empty())
.build();
}

private int getPreferredWidthForThumbnail(Context c) {
if (subredditSubmissionImageStyle.get().equals(SubredditSubmissionImageStyle.LARGE)) {
return c.getResources().getDisplayMetrics().widthPixels;
}
return c.getResources().getDimensionPixelSize(R.dimen.subreddit_submission_thumbnail);
}
}
9 changes: 9 additions & 0 deletions app/src/main/res/drawable/ic_image_style_large_20dp.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFF"
android:pathData="M2,21h19v-3H2v3zM20,8H3c-0.55,0 -1,0.45 -1,1v6c0,0.55 0.45,1 1,1h17c0.55,0 1,-0.45 1,-1V9c0,-0.55 -0.45,-1 -1,-1zM2,3v3h19V3H2z"/>
</vector>
9 changes: 9 additions & 0 deletions app/src/main/res/drawable/ic_image_style_thumbnail_20dp.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFF"
android:pathData="M4,14h4v-4L4,10v4zM4,19h4v-4L4,15v4zM4,9h4L8,5L4,5v4zM9,14h12v-4L9,10v4zM9,19h12v-4L9,15v4zM9,5v4h12L21,5L9,5z"/>
</vector>
12 changes: 12 additions & 0 deletions app/src/main/res/drawable/touchindicator_submission_image.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/color_accent">

<item android:id="@android:id/mask">
<shape android:shape="rectangle">
<!-- The color of this mask has an effect on the highlight color.
Yet to understand why. -->
<solid android:color="@color/white_opacity_50" />
</shape>
</item>
</ripple>
Loading