From 23d84dfa66733637d291a380438a5bbf76e0e721 Mon Sep 17 00:00:00 2001 From: Ivan Kupalov Date: Thu, 10 May 2018 21:13:25 +0300 Subject: [PATCH] Show image descriptions in gallery (#630) * Add circleci * Commit to maybe fix ci * Suppress false positives in lint * Disable linting for tests in ci * Add image descriptions to gallery * Fix test * [CI] Attempt to fix OOM error * [CI] Attempt to fix OOM error, 2 * Add option to open status from media * fix theme issue * increase linespacing on media description --- .circleci/config.yml | 3 + .../tusky/ViewMediaActivity.java | 93 ++++++++++----- .../tusky/ViewThreadActivity.java | 21 +++- .../tusky/adapter/StatusBaseViewHolder.java | 106 ++++++------------ .../adapter/StatusDetailedViewHolder.java | 2 +- .../keylesspalace/tusky/entity/Attachment.kt | 5 +- .../com/keylesspalace/tusky/entity/Status.kt | 2 +- .../tusky/fragment/AccountMediaFragment.kt | 32 +++--- .../tusky/fragment/NotificationsFragment.java | 7 +- .../tusky/fragment/SFragment.java | 18 +-- .../tusky/fragment/SearchFragment.kt | 5 +- .../tusky/fragment/TimelineFragment.java | 7 +- .../tusky/fragment/ViewMediaFragment.java | 105 ++++++++++++----- .../tusky/fragment/ViewThreadFragment.java | 6 +- .../interfaces/StatusActionListener.java | 2 +- .../tusky/pager/ImagePagerAdapter.java | 19 ++-- .../tusky/viewdata/AttachmentViewData.kt | 23 ++++ .../tusky/viewdata/StatusViewData.java | 15 +-- app/src/main/res/layout/activity_account.xml | 2 +- .../main/res/layout/activity_view_media.xml | 4 +- .../main/res/layout/fragment_view_media.xml | 16 ++- app/src/main/res/menu/view_media_toolbar.xml | 4 + app/src/main/res/values-night/styles.xml | 2 +- app/src/main/res/values/attrs.xml | 2 +- app/src/main/res/values/strings.xml | 1 + app/src/main/res/values/styles.xml | 2 +- .../tusky/BottomSheetActivityTest.kt | 2 +- 27 files changed, 313 insertions(+), 193 deletions(-) create mode 100644 app/src/main/java/com/keylesspalace/tusky/viewdata/AttachmentViewData.kt diff --git a/.circleci/config.yml b/.circleci/config.yml index 3ef108b97..0c9a50b31 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,4 +1,7 @@ version: 2 +machine: + environment: + GRADLE_OPTS: '-Dorg.gradle.jvmargs="-Xmx2048m -XX:+HeapDumpOnOutOfMemoryError"' jobs: build: working_directory: ~/code diff --git a/app/src/main/java/com/keylesspalace/tusky/ViewMediaActivity.java b/app/src/main/java/com/keylesspalace/tusky/ViewMediaActivity.java index 1493545bc..60f586904 100644 --- a/app/src/main/java/com/keylesspalace/tusky/ViewMediaActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/ViewMediaActivity.java @@ -39,25 +39,58 @@ import android.support.v4.view.ViewPager; import android.support.v7.app.ActionBar; import android.support.v7.widget.Toolbar; import android.view.Menu; -import android.view.MenuItem; import android.view.View; import android.widget.Toast; +import com.keylesspalace.tusky.entity.Attachment; import com.keylesspalace.tusky.fragment.ViewMediaFragment; import com.keylesspalace.tusky.pager.ImagePagerAdapter; import com.keylesspalace.tusky.view.ImageViewPager; +import com.keylesspalace.tusky.viewdata.AttachmentViewData; import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import kotlin.collections.CollectionsKt; +import kotlin.jvm.functions.Function0; + +public final class ViewMediaActivity extends BaseActivity + implements ViewMediaFragment.PhotoActionsListener { + private static final String ATTACHMENTS_EXTRA = "attachments"; + private static final String INDEX_EXTRA = "index"; + + public static Intent newIntent(Context context, List attachments, + int index) { + final Intent intent = new Intent(context, ViewMediaActivity.class); + intent.putParcelableArrayListExtra(ATTACHMENTS_EXTRA, new ArrayList<>(attachments)); + intent.putExtra(INDEX_EXTRA, index); + return intent; + } -public class ViewMediaActivity extends BaseActivity implements ViewMediaFragment.PhotoActionsListener { private static final int PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 1; private ImageViewPager viewPager; private View anyView; - private String[] imageUrls; + private List attachments; private Toolbar toolbar; private boolean isToolbarVisible = true; + private final List toolbarVisibilityListeners = new ArrayList<>(); + + public interface ToolbarVisibilityListener { + void onToolbarVisiblityChanged(boolean isVisible); + } + + public Function0 addToolbarVisibilityListener(ToolbarVisibilityListener listener) { + this.toolbarVisibilityListeners.add(listener); + listener.onToolbarVisiblityChanged(isToolbarVisible); + return () -> toolbarVisibilityListeners.remove(listener); + } + + public boolean isToolbarVisible() { + return isToolbarVisible; + } @Override protected void onCreate(@Nullable Bundle savedInstanceState) { @@ -73,12 +106,14 @@ public class ViewMediaActivity extends BaseActivity implements ViewMediaFragment // Gather the parameters. Intent intent = getIntent(); - imageUrls = intent.getStringArrayExtra("urls"); - int initialPosition = intent.getIntExtra("urlIndex", 0); + attachments = intent.getParcelableArrayListExtra(ATTACHMENTS_EXTRA); + int initialPosition = intent.getIntExtra(INDEX_EXTRA, 0); + List realAttachs = + CollectionsKt.map(attachments, AttachmentViewData::getAttachment); // Setup the view pager. final ImagePagerAdapter adapter = new ImagePagerAdapter(getSupportFragmentManager(), - imageUrls, initialPosition); + realAttachs, initialPosition); viewPager.setAdapter(adapter); viewPager.setCurrentItem(initialPosition); viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @@ -106,23 +141,18 @@ public class ViewMediaActivity extends BaseActivity implements ViewMediaFragment actionBar.setDisplayShowHomeEnabled(true); actionBar.setTitle(adapter.getPageTitle(initialPosition)); } - toolbar.setNavigationOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - supportFinishAfterTransition(); - } - }); - toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() { - @Override - public boolean onMenuItemClick(MenuItem item) { - int id = item.getItemId(); - switch (id) { - case R.id.action_download: - downloadImage(); - break; - } - return true; + toolbar.setNavigationOnClickListener(v -> supportFinishAfterTransition()); + toolbar.setOnMenuItemClickListener(item -> { + int id = item.getItemId(); + switch (id) { + case R.id.action_download: + downloadImage(); + break; + case R.id.action_open_status: + onOpenStatus(); + break; } + return true; }); View decorView = getWindow().getDecorView(); @@ -161,8 +191,12 @@ public class ViewMediaActivity extends BaseActivity implements ViewMediaFragment @Override public void onPhotoTap() { isToolbarVisible = !isToolbarVisible; + for (ToolbarVisibilityListener listener : toolbarVisibilityListeners) { + listener.onToolbarVisiblityChanged(isToolbarVisible); + } final int visibility = isToolbarVisible ? View.VISIBLE : View.INVISIBLE; int alpha = isToolbarVisible ? 1 : 0; + toolbar.animate().alpha(alpha) .setListener(new AnimatorListenerAdapter() { @Override @@ -184,12 +218,7 @@ public class ViewMediaActivity extends BaseActivity implements ViewMediaFragment downloadImage(); } else { doErrorDialog(R.string.error_media_download_permission, R.string.action_retry, - new View.OnClickListener() { - @Override - public void onClick(View v) { - downloadImage(); - } - }); + v -> downloadImage()); } break; } @@ -214,7 +243,7 @@ public class ViewMediaActivity extends BaseActivity implements ViewMediaFragment new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE); } else { - String url = imageUrls[viewPager.getCurrentItem()]; + String url = attachments.get(viewPager.getCurrentItem()).getAttachment().getUrl(); Uri uri = Uri.parse(url); String filename = new File(url).getName(); @@ -234,4 +263,10 @@ public class ViewMediaActivity extends BaseActivity implements ViewMediaFragment downloadManager.enqueue(request); } } + + private void onOpenStatus() { + final AttachmentViewData attach = attachments.get(viewPager.getCurrentItem()); + startActivity(ViewThreadActivity.startIntent(this, attach.getStatusId(), + attach.getStatusUrl())); + } } diff --git a/app/src/main/java/com/keylesspalace/tusky/ViewThreadActivity.java b/app/src/main/java/com/keylesspalace/tusky/ViewThreadActivity.java index 070872590..1518e6cf2 100644 --- a/app/src/main/java/com/keylesspalace/tusky/ViewThreadActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/ViewThreadActivity.java @@ -15,6 +15,8 @@ package com.keylesspalace.tusky; +import android.content.Context; +import android.content.Intent; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; @@ -24,6 +26,7 @@ import android.support.v7.widget.Toolbar; import android.view.Menu; import android.view.MenuItem; +import com.keylesspalace.tusky.entity.Status; import com.keylesspalace.tusky.fragment.ViewThreadFragment; import com.keylesspalace.tusky.util.LinkHelper; @@ -39,6 +42,20 @@ public class ViewThreadActivity extends BottomSheetActivity implements HasSuppor public static final int REVEAL_BUTTON_REVEAL = 2; public static final int REVEAL_BUTTON_HIDE = 3; + public static Intent startIntent(Context context, String id, String url) { + Intent intent = new Intent(context, ViewThreadActivity.class); + intent.putExtra(ID_EXTRA, id); + intent.putExtra(URL_EXTRA, url); + return intent; + } + + public static Intent startIntentFromStatus(Context context, Status status) { + return startIntent(context, status.getActionableId(), status.getActionableStatus().getUrl()); + } + + private static final String ID_EXTRA = "id"; + private static final String URL_EXTRA = "url"; + private int revealButtonState = REVEAL_BUTTON_HIDDEN; @Inject @@ -60,7 +77,7 @@ public class ViewThreadActivity extends BottomSheetActivity implements HasSuppor actionBar.setDisplayShowHomeEnabled(true); } - String id = getIntent().getStringExtra("id"); + String id = getIntent().getStringExtra(ID_EXTRA); FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction(); fragment = ViewThreadFragment.newInstance(id); fragmentTransaction.replace(R.id.fragment_container, fragment); @@ -98,7 +115,7 @@ public class ViewThreadActivity extends BottomSheetActivity implements HasSuppor return true; } case R.id.action_open_in_web: { - LinkHelper.openLink(getIntent().getStringExtra("url"), this); + LinkHelper.openLink(getIntent().getStringExtra(URL_EXTRA), this); return true; } case R.id.action_reveal: { diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java index c22aadd9c..9b593208c 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusBaseViewHolder.java @@ -30,6 +30,7 @@ import com.keylesspalace.tusky.view.RoundedTransformation; import com.keylesspalace.tusky.viewdata.StatusViewData; import com.mikepenz.iconics.utils.Utils; import com.squareup.picasso.Picasso; + import at.connyduck.sparkbutton.SparkButton; import at.connyduck.sparkbutton.SparkEventListener; @@ -148,7 +149,7 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { } protected void showContent(boolean show) { - if(show) { + if (show) { container.setVisibility(View.VISIBLE); container.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT; } else { @@ -158,7 +159,7 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { } private void setIsReply(boolean isReply) { - if(isReply) { + if (isReply) { replyButton.setImageResource(R.drawable.ic_reply_all_24dp); } else { replyButton.setImageResource(R.drawable.ic_reply_24dp); @@ -199,7 +200,7 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { favouriteButton.setChecked(favourited); } - private void setMediaPreviews(final Attachment[] attachments, boolean sensitive, + private void setMediaPreviews(final List attachments, boolean sensitive, final StatusActionListener listener, boolean showingContent) { final ImageView[] previews = { mediaPreview0, mediaPreview1, mediaPreview2, mediaPreview3 @@ -213,18 +214,13 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { ThemeUtils.getDrawableId(itemView.getContext(), R.attr.media_preview_unloaded_drawable, android.R.color.black); - final int n = Math.min(attachments.length, Status.MAX_MEDIA_ATTACHMENTS); - - final String[] urls = new String[n]; - for (int i = 0; i < n; i++) { - urls[i] = attachments[i].getUrl(); - } + final int n = Math.min(attachments.size(), Status.MAX_MEDIA_ATTACHMENTS); for (int i = 0; i < n; i++) { - String previewUrl = attachments[i].getPreviewUrl(); - String description = attachments[i].getDescription(); + String previewUrl = attachments.get(i).getPreviewUrl(); + String description = attachments.get(i).getDescription(); - if(TextUtils.isEmpty(description)) { + if (TextUtils.isEmpty(description)) { previews[i].setContentDescription(context.getString(R.string.action_view_media)); } else { previews[i].setContentDescription(description); @@ -243,28 +239,19 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { .into(previews[i]); } - final Attachment.Type type = attachments[i].getType(); + final Attachment.Type type = attachments.get(i).getType(); if (type == Attachment.Type.VIDEO | type == Attachment.Type.GIFV) { overlays[i].setVisibility(View.VISIBLE); } else { overlays[i].setVisibility(View.GONE); } - if (urls[i] == null || urls[i].isEmpty()) { - previews[i].setOnClickListener(null); - } else { - final int urlIndex = i; - previews[i].setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - listener.onViewMedia(urls, urlIndex, type, v); - } - }); - } + final int urlIndex = i; + previews[i].setOnClickListener(v -> listener.onViewMedia(getAdapterPosition(), urlIndex, v)); - if(n <= 2) { - previews[0].getLayoutParams().height = getMediaPreviewHeight(context)*2; - previews[1].getLayoutParams().height = getMediaPreviewHeight(context)*2; + if (n <= 2) { + previews[0].getLayoutParams().height = getMediaPreviewHeight(context) * 2; + previews[1].getLayoutParams().height = getMediaPreviewHeight(context) * 2; } else { previews[0].getLayoutParams().height = getMediaPreviewHeight(context); previews[1].getLayoutParams().height = getMediaPreviewHeight(context); @@ -274,7 +261,7 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { } String hiddenContentText; - if(sensitive) { + if (sensitive) { hiddenContentText = context.getString(R.string.status_sensitive_media_template, context.getString(R.string.status_sensitive_media_title), context.getString(R.string.status_sensitive_media_directions)); @@ -289,25 +276,19 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { sensitiveMediaWarning.setVisibility(showingContent ? View.GONE : View.VISIBLE); sensitiveMediaShow.setVisibility(showingContent ? View.VISIBLE : View.GONE); - sensitiveMediaShow.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (getAdapterPosition() != RecyclerView.NO_POSITION) { - listener.onContentHiddenChange(false, getAdapterPosition()); - } - v.setVisibility(View.GONE); - sensitiveMediaWarning.setVisibility(View.VISIBLE); + sensitiveMediaShow.setOnClickListener(v -> { + if (getAdapterPosition() != RecyclerView.NO_POSITION) { + listener.onContentHiddenChange(false, getAdapterPosition()); } + v.setVisibility(View.GONE); + sensitiveMediaWarning.setVisibility(View.VISIBLE); }); - sensitiveMediaWarning.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - if (getAdapterPosition() != RecyclerView.NO_POSITION) { - listener.onContentHiddenChange(true, getAdapterPosition()); - } - v.setVisibility(View.GONE); - sensitiveMediaShow.setVisibility(View.VISIBLE); + sensitiveMediaWarning.setOnClickListener(v -> { + if (getAdapterPosition() != RecyclerView.NO_POSITION) { + listener.onContentHiddenChange(true, getAdapterPosition()); } + v.setVisibility(View.GONE); + sensitiveMediaShow.setVisibility(View.VISIBLE); }); @@ -341,9 +322,9 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { } } - private void setMediaLabel(Attachment[] attachments, boolean sensitive, + private void setMediaLabel(List attachments, boolean sensitive, final StatusActionListener listener) { - if (attachments.length == 0) { + if (attachments.size() == 0) { mediaLabel.setVisibility(View.GONE); return; } @@ -351,7 +332,7 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { // Set the label's text. Context context = itemView.getContext(); - String labelText = getLabelTypeText(context, attachments[0].getType()); + String labelText = getLabelTypeText(context, attachments.get(0).getType()); if (sensitive) { String sensitiveText = context.getString(R.string.status_sensitive_media_title); labelText += String.format(" (%s)", sensitiveText); @@ -359,24 +340,12 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { mediaLabel.setText(labelText); // Set the icon next to the label. - int drawableId = getLabelIcon(attachments[0].getType()); + int drawableId = getLabelIcon(attachments.get(0).getType()); Drawable drawable = AppCompatResources.getDrawable(context, drawableId); ThemeUtils.setDrawableTint(context, drawable, android.R.attr.textColorTertiary); mediaLabel.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null); - // Set the listener for the media view action. - int n = Math.min(attachments.length, Status.MAX_MEDIA_ATTACHMENTS); - final String[] urls = new String[n]; - for (int i = 0; i < n; i++) { - urls[i] = attachments[i].getUrl(); - } - final Attachment.Type type = attachments[0].getType(); - mediaLabel.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - listener.onViewMedia(urls, 0, type, null); - } - }); + mediaLabel.setOnClickListener(v -> listener.onViewMedia(getAdapterPosition(), 0, null)); } private void hideSensitiveMediaWarning() { @@ -483,13 +452,10 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { * if it contains URLSpans without also setting its listener. The surrounding spans will * just eat the clicks instead of deferring to the parent listener, but WILL respond to a * listener directly on the TextView, for whatever reason. */ - View.OnClickListener viewThreadListener = new View.OnClickListener() { - @Override - public void onClick(View v) { - int position = getAdapterPosition(); - if (position != RecyclerView.NO_POSITION) { - listener.onViewThread(position); - } + View.OnClickListener viewThreadListener = v -> { + int position = getAdapterPosition(); + if (position != RecyclerView.NO_POSITION) { + listener.onViewThread(position); } }; content.setOnClickListener(viewThreadListener); @@ -506,12 +472,12 @@ abstract class StatusBaseViewHolder extends RecyclerView.ViewHolder { setAvatar(status.getAvatar(), status.getRebloggedAvatar()); setReblogged(status.isReblogged()); setFavourited(status.isFavourited()); - Attachment[] attachments = status.getAttachments(); + List attachments = status.getAttachments(); boolean sensitive = status.isSensitive(); if (mediaPreviewEnabled) { setMediaPreviews(attachments, sensitive, listener, status.isShowingContent()); - if (attachments.length == 0) { + if (attachments.size() == 0) { hideSensitiveMediaWarning(); // videoIndicator.setVisibility(View.GONE); } diff --git a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusDetailedViewHolder.java b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusDetailedViewHolder.java index 17dcdecb1..88d5b7183 100644 --- a/app/src/main/java/com/keylesspalace/tusky/adapter/StatusDetailedViewHolder.java +++ b/app/src/main/java/com/keylesspalace/tusky/adapter/StatusDetailedViewHolder.java @@ -110,7 +110,7 @@ class StatusDetailedViewHolder extends StatusBaseViewHolder { content.setOnLongClickListener(longClickListener); contentWarningDescription.setOnLongClickListener(longClickListener); - if(status.getAttachments().length == 0 && status.getCard() != null && !TextUtils.isEmpty(status.getCard().getUrl())) { + if(status.getAttachments().size() == 0 && status.getCard() != null && !TextUtils.isEmpty(status.getCard().getUrl())) { final Card card = status.getCard(); cardView.setVisibility(View.VISIBLE); cardTitle.setText(card.getTitle()); diff --git a/app/src/main/java/com/keylesspalace/tusky/entity/Attachment.kt b/app/src/main/java/com/keylesspalace/tusky/entity/Attachment.kt index bc47e9f89..f7d68d576 100644 --- a/app/src/main/java/com/keylesspalace/tusky/entity/Attachment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/entity/Attachment.kt @@ -15,13 +15,16 @@ package com.keylesspalace.tusky.entity +import android.os.Parcelable import com.google.gson.JsonDeserializationContext import com.google.gson.JsonDeserializer import com.google.gson.JsonElement import com.google.gson.JsonParseException import com.google.gson.annotations.JsonAdapter import com.google.gson.annotations.SerializedName +import kotlinx.android.parcel.Parcelize +@Parcelize data class Attachment( var id: String, var url: String, @@ -29,7 +32,7 @@ data class Attachment( @SerializedName("text_url") val textUrl: String?, var type: Type, var description: String? -) { +) : Parcelable { @JsonAdapter(MediaTypeDeserializer::class) enum class Type { diff --git a/app/src/main/java/com/keylesspalace/tusky/entity/Status.kt b/app/src/main/java/com/keylesspalace/tusky/entity/Status.kt index 8f4546de3..238a2c464 100644 --- a/app/src/main/java/com/keylesspalace/tusky/entity/Status.kt +++ b/app/src/main/java/com/keylesspalace/tusky/entity/Status.kt @@ -36,7 +36,7 @@ data class Status( var sensitive: Boolean, @SerializedName("spoiler_text") val spoilerText: String, val visibility: Visibility, - @SerializedName("media_attachments") var attachments: Array, + @SerializedName("media_attachments") var attachments: List, val mentions: Array, val application: Application? ) { diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/AccountMediaFragment.kt b/app/src/main/java/com/keylesspalace/tusky/fragment/AccountMediaFragment.kt index 0430d982c..b8d73b30d 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/AccountMediaFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/AccountMediaFragment.kt @@ -38,6 +38,7 @@ import com.keylesspalace.tusky.entity.Status import com.keylesspalace.tusky.network.MastodonApi import com.keylesspalace.tusky.util.ThemeUtils import com.keylesspalace.tusky.view.SquareImageView +import com.keylesspalace.tusky.viewdata.AttachmentViewData import com.squareup.picasso.Picasso import retrofit2.Call import retrofit2.Callback @@ -74,7 +75,7 @@ class AccountMediaFragment : BaseFragment(), Injectable { private var currentCall: Call>? = null private val statuses = mutableListOf() private var fetchingStatus = FetchingStatus.NOT_FETCHING - lateinit private var swipeLayout: SwipeRefreshLayout + private lateinit var swipeLayout: SwipeRefreshLayout private val callback = object : Callback> { override fun onFailure(call: Call>?, t: Throwable?) { @@ -90,9 +91,9 @@ class AccountMediaFragment : BaseFragment(), Injectable { body?.let { fetched -> statuses.addAll(0, fetched) // flatMap requires iterable but I don't want to box each array into list - val result = mutableListOf() + val result = mutableListOf() for (status in fetched) { - result.addAll(status.attachments) + result.addAll(AttachmentViewData.list(status)) } adapter.addTop(result) } @@ -114,9 +115,9 @@ class AccountMediaFragment : BaseFragment(), Injectable { statuses.addAll(fetched) Log.d(TAG, "now there are ${statuses.size} statuses") // flatMap requires iterable but I don't want to box each array into list - val result = mutableListOf() + val result = mutableListOf() for (status in fetched) { - result.addAll(status.attachments) + result.addAll(AttachmentViewData.list(status)) } adapter.addBottom(result) } @@ -193,17 +194,14 @@ class AccountMediaFragment : BaseFragment(), Injectable { } } - private fun viewMedia(items: List, currentIndex: Int, view: View?) { - val urls = items.map { it.url }.toTypedArray() - val type = items[currentIndex].type + private fun viewMedia(items: List, currentIndex: Int, view: View?) { + val type = items[currentIndex].attachment.type when (type) { Attachment.Type.IMAGE -> { - val intent = Intent(context, ViewMediaActivity::class.java) - intent.putExtra("urls", urls) - intent.putExtra("urlIndex", currentIndex) + val intent = ViewMediaActivity.newIntent(context, items, currentIndex) if (view != null && activity != null) { - val url = urls[currentIndex] + val url = items[currentIndex].attachment.url ViewCompat.setTransitionName(view, url) val options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity!!, view, url) startActivity(intent, options.toBundle()) @@ -213,7 +211,7 @@ class AccountMediaFragment : BaseFragment(), Injectable { } Attachment.Type.GIFV, Attachment.Type.VIDEO -> { val intent = Intent(context, ViewVideoActivity::class.java) - intent.putExtra("url", urls[currentIndex]) + intent.putExtra("url", items[currentIndex].attachment.url) startActivity(intent) } Attachment.Type.UNKNOWN -> { @@ -232,16 +230,16 @@ class AccountMediaFragment : BaseFragment(), Injectable { var baseItemColor = Color.BLACK - private val items = mutableListOf() + private val items = mutableListOf() private val itemBgBaseHSV = FloatArray(3) private val random = Random() - fun addTop(newItems: List) { + fun addTop(newItems: List) { items.addAll(0, newItems) notifyItemRangeInserted(0, newItems.size) } - fun addBottom(newItems: List) { + fun addBottom(newItems: List) { if (newItems.isEmpty()) return val oldLen = items.size @@ -268,7 +266,7 @@ class AccountMediaFragment : BaseFragment(), Injectable { holder.imageView.setBackgroundColor(Color.HSVToColor(itemBgBaseHSV)) val item = items[position] Picasso.with(holder.imageView.context) - .load(item.previewUrl) + .load(item.attachment.previewUrl) .into(holder.imageView) } diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java index 4d4c52ca3..acd82e17e 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java @@ -365,9 +365,10 @@ public class NotificationsFragment extends SFragment implements } @Override - public void onViewMedia(String[] urls, int urlIndex, Attachment.Type type, - View view) { - super.viewMedia(urls, urlIndex, type, view); + public void onViewMedia(int position, int attachmentIndex, View view) { + Notification notification = notifications.get(position).getAsRightOrNull(); + if (notification == null || notification.getStatus() == null) return; + super.viewMedia(attachmentIndex, notification.getStatus(), view); } @Override diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/SFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/SFragment.java index c3ad63de8..184926118 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/SFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/SFragment.java @@ -43,8 +43,10 @@ import com.keylesspalace.tusky.interfaces.AdapterItemRemover; import com.keylesspalace.tusky.network.MastodonApi; import com.keylesspalace.tusky.network.TimelineCases; import com.keylesspalace.tusky.util.HtmlUtils; +import com.keylesspalace.tusky.viewdata.AttachmentViewData; import java.util.LinkedHashSet; +import java.util.List; import java.util.Set; import javax.inject.Inject; @@ -201,15 +203,17 @@ public abstract class SFragment extends BaseFragment implements AdapterItemRemov popup.show(); } - protected void viewMedia(String[] urls, int urlIndex, Attachment.Type type, - @Nullable View view) { + protected void viewMedia(int urlIndex, Status status, @Nullable View view) { + final Status actionable = status.getActionableStatus(); + final Attachment active = actionable.getAttachments().get(urlIndex); + Attachment.Type type = active.getType(); switch (type) { case IMAGE: { - Intent intent = new Intent(getContext(), ViewMediaActivity.class); - intent.putExtra("urls", urls); - intent.putExtra("urlIndex", urlIndex); + final List attachments = AttachmentViewData.list(actionable); + final Intent intent = ViewMediaActivity.newIntent(getContext(), attachments, + urlIndex); if (view != null) { - String url = urls[urlIndex]; + String url = active.getUrl(); ViewCompat.setTransitionName(view, url); ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(getActivity(), @@ -223,7 +227,7 @@ public abstract class SFragment extends BaseFragment implements AdapterItemRemov case GIFV: case VIDEO: { Intent intent = new Intent(getContext(), ViewVideoActivity.class); - intent.putExtra("url", urls[urlIndex]); + intent.putExtra("url", active.getUrl()); startActivity(intent); break; } diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/SearchFragment.kt b/app/src/main/java/com/keylesspalace/tusky/fragment/SearchFragment.kt index 8ba65df81..7afae7519 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/SearchFragment.kt +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/SearchFragment.kt @@ -175,8 +175,9 @@ class SearchFragment : SFragment(), StatusActionListener, Injectable { } } - override fun onViewMedia(urls: Array?, index: Int, type: Attachment.Type?, view: View?) { - viewMedia(urls, index, type, view) + override fun onViewMedia(position: Int, attachmentIndex: Int, view: View?) { + val status = searchAdapter.getStatusAtPosition(position) ?: return + viewMedia(attachmentIndex, status, view) } override fun onViewThread(position: Int) { diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java index fdeca9a06..1ee9ca649 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java @@ -443,9 +443,10 @@ public class TimelineFragment extends SFragment implements } @Override - public void onViewMedia(String[] urls, int urlIndex, Attachment.Type type, - View view) { - super.viewMedia(urls, urlIndex, type, view); + public void onViewMedia(int position, int attachmentIndex, View view) { + Status status = statuses.get(position).getAsRightOrNull(); + if (status == null) return; + super.viewMedia(attachmentIndex, status, view); } @Override diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/ViewMediaFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/ViewMediaFragment.java index 6fc6f0366..0ee0015b4 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/ViewMediaFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/ViewMediaFragment.java @@ -15,28 +15,39 @@ package com.keylesspalace.tusky.fragment; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; import android.content.Context; import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v4.view.ViewCompat; +import android.text.TextUtils; import android.view.LayoutInflater; -import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; +import android.widget.TextView; -import com.github.chrisbanes.photoview.OnOutsidePhotoTapListener; -import com.github.chrisbanes.photoview.OnSingleFlingListener; import com.github.chrisbanes.photoview.PhotoView; import com.github.chrisbanes.photoview.PhotoViewAttacher; import com.keylesspalace.tusky.R; +import com.keylesspalace.tusky.ViewMediaActivity; +import com.keylesspalace.tusky.entity.Attachment; import com.squareup.picasso.Callback; import com.squareup.picasso.NetworkPolicy; import com.squareup.picasso.Picasso; -public class ViewMediaFragment extends BaseFragment { +import java.util.Objects; + +import kotlin.jvm.functions.Function0; + +public final class ViewMediaFragment extends BaseFragment { public interface PhotoActionsListener { void onBringUp(); + void onDismiss(); + void onPhotoTap(); } @@ -44,13 +55,20 @@ public class ViewMediaFragment extends BaseFragment { private PhotoActionsListener photoActionsListener; private View rootView; private PhotoView photoView; + private TextView descriptionView; + + private boolean showingDescription; + private boolean isDescriptionVisible; + private Function0 toolbarVisibiltyDisposable; private static final String ARG_START_POSTPONED_TRANSITION = "startPostponedTransition"; + private static final String ATTACH_ARG = "attach"; - public static ViewMediaFragment newInstance(String url, boolean shouldStartPostponedTransition) { + public static ViewMediaFragment newInstance(@NonNull Attachment attachment, + boolean shouldStartPostponedTransition) { Bundle arguments = new Bundle(); ViewMediaFragment fragment = new ViewMediaFragment(); - arguments.putString("url", url); + arguments.putParcelable(ATTACH_ARG, attachment); arguments.putBoolean(ARG_START_POSTPONED_TRANSITION, shouldStartPostponedTransition); fragment.setArguments(arguments); @@ -64,43 +82,42 @@ public class ViewMediaFragment extends BaseFragment { } @Override - public View onCreateView(LayoutInflater inflater, final ViewGroup container, + public View onCreateView(@NonNull LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) { rootView = inflater.inflate(R.layout.fragment_view_media, container, false); photoView = rootView.findViewById(R.id.view_media_image); + descriptionView = rootView.findViewById(R.id.tv_media_description); - final Bundle arguments = getArguments(); - final String url = arguments.getString("url"); + final Bundle arguments = Objects.requireNonNull(getArguments(), "Empty arguments"); + final Attachment attachment = arguments.getParcelable(ATTACH_ARG); + final String url = attachment.getUrl(); + @Nullable final String description = attachment.getDescription(); + + descriptionView.setText(description); + showingDescription = !TextUtils.isEmpty(description); + isDescriptionVisible = showingDescription; + + // Setting visibility without animations so it looks nice when you scroll images + //noinspection ConstantConditions + descriptionView.setVisibility(showingDescription + && (((ViewMediaActivity) getActivity())).isToolbarVisible() + ? View.VISIBLE : View.GONE); attacher = new PhotoViewAttacher(photoView); // Clicking outside the photo closes the viewer. - attacher.setOnOutsidePhotoTapListener(new OnOutsidePhotoTapListener() { - @Override - public void onOutsidePhotoTap(ImageView imageView) { - photoActionsListener.onDismiss(); - } - }); + attacher.setOnOutsidePhotoTapListener(imageView -> photoActionsListener.onDismiss()); - attacher.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - photoActionsListener.onPhotoTap(); - } - }); + attacher.setOnClickListener(v -> onMediaTap()); /* A vertical swipe motion also closes the viewer. This is especially useful when the photo * mostly fills the screen so clicking outside is difficult. */ - attacher.setOnSingleFlingListener(new OnSingleFlingListener() { - @Override - public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, - float velocityY) { - if (Math.abs(velocityY) > Math.abs(velocityX)) { - photoActionsListener.onDismiss(); - return true; - } - return false; + attacher.setOnSingleFlingListener((e1, e2, velocityX, velocityY) -> { + if (Math.abs(velocityY) > Math.abs(velocityX)) { + photoActionsListener.onDismiss(); + return true; } + return false; }); ViewCompat.setTransitionName(photoView, url); @@ -150,9 +167,37 @@ public class ViewMediaFragment extends BaseFragment { loadImageFromNetwork(url, photoView); } + toolbarVisibiltyDisposable = ((ViewMediaActivity) getActivity()) + .addToolbarVisibilityListener(this::onToolbarVisibilityChange); + return rootView; } + @Override + public void onDestroyView() { + if (toolbarVisibiltyDisposable != null) toolbarVisibiltyDisposable.invoke(); + super.onDestroyView(); + } + + private void onMediaTap() { + photoActionsListener.onPhotoTap(); + } + + private void onToolbarVisibilityChange(boolean visible) { + isDescriptionVisible = showingDescription && visible; + final int visibility = isDescriptionVisible ? View.VISIBLE : View.INVISIBLE; + int alpha = isDescriptionVisible ? 1 : 0; + descriptionView.animate().alpha(alpha) + .setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + descriptionView.setVisibility(visibility); + animation.removeListener(this); + } + }) + .start(); + } + @Override public void onDetach() { super.onDetach(); diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/ViewThreadFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/ViewThreadFragment.java index 75a573f94..1c1c6329d 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/ViewThreadFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/ViewThreadFragment.java @@ -267,9 +267,9 @@ public final class ViewThreadFragment extends SFragment implements } @Override - public void onViewMedia(String[] urls, int urlIndex, Attachment.Type type, - View view) { - super.viewMedia(urls, urlIndex, type, view); + public void onViewMedia(int position, int attachmentIndex, View view) { + Status status = statuses.get(position); + super.viewMedia(attachmentIndex, status, view); } @Override diff --git a/app/src/main/java/com/keylesspalace/tusky/interfaces/StatusActionListener.java b/app/src/main/java/com/keylesspalace/tusky/interfaces/StatusActionListener.java index 4a5d7b5c6..94fd4f0a6 100644 --- a/app/src/main/java/com/keylesspalace/tusky/interfaces/StatusActionListener.java +++ b/app/src/main/java/com/keylesspalace/tusky/interfaces/StatusActionListener.java @@ -24,7 +24,7 @@ public interface StatusActionListener extends LinkListener { void onReblog(final boolean reblog, final int position); void onFavourite(final boolean favourite, final int position); void onMore(View view, final int position); - void onViewMedia(String[] urls, int index, Attachment.Type type, View view); + void onViewMedia(int position, int attachmentIndex, View view); void onViewThread(int position); void onOpenReblog(int position); void onExpandedChange(boolean expanded, int position); diff --git a/app/src/main/java/com/keylesspalace/tusky/pager/ImagePagerAdapter.java b/app/src/main/java/com/keylesspalace/tusky/pager/ImagePagerAdapter.java index 274f04ec5..5fce0b907 100644 --- a/app/src/main/java/com/keylesspalace/tusky/pager/ImagePagerAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/pager/ImagePagerAdapter.java @@ -4,24 +4,27 @@ import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; +import com.keylesspalace.tusky.entity.Attachment; import com.keylesspalace.tusky.fragment.ViewMediaFragment; +import java.util.List; import java.util.Locale; -public class ImagePagerAdapter extends FragmentPagerAdapter { - private String[] urls; +public final class ImagePagerAdapter extends FragmentPagerAdapter { + + private List attachments; private int initialPosition; - public ImagePagerAdapter(FragmentManager fragmentManager, String[] urls, int initialPosition) { + public ImagePagerAdapter(FragmentManager fragmentManager, List attachments, int initialPosition) { super(fragmentManager); - this.urls = urls; + this.attachments = attachments; this.initialPosition = initialPosition; } @Override public Fragment getItem(int position) { - if (position >= 0 && position < urls.length) { - return ViewMediaFragment.newInstance(urls[position], position == initialPosition); + if (position >= 0 && position < attachments.size()) { + return ViewMediaFragment.newInstance(attachments.get(position), position == initialPosition); } else { return null; } @@ -29,11 +32,11 @@ public class ImagePagerAdapter extends FragmentPagerAdapter { @Override public int getCount() { - return urls.length; + return attachments.size(); } @Override public CharSequence getPageTitle(int position) { - return String.format(Locale.getDefault(), "%d/%d", position + 1, urls.length); + return String.format(Locale.getDefault(), "%d/%d", position + 1, attachments.size()); } } diff --git a/app/src/main/java/com/keylesspalace/tusky/viewdata/AttachmentViewData.kt b/app/src/main/java/com/keylesspalace/tusky/viewdata/AttachmentViewData.kt new file mode 100644 index 000000000..aea0582db --- /dev/null +++ b/app/src/main/java/com/keylesspalace/tusky/viewdata/AttachmentViewData.kt @@ -0,0 +1,23 @@ +package com.keylesspalace.tusky.viewdata + +import android.os.Parcelable +import com.keylesspalace.tusky.entity.Attachment +import com.keylesspalace.tusky.entity.Status +import kotlinx.android.parcel.Parcelize + +@Parcelize +data class AttachmentViewData( + val attachment: Attachment, + val statusId: String, + val statusUrl: String +) : Parcelable { + companion object { + @JvmStatic + fun list(status: Status): List { + val actionable = status.actionableStatus + return actionable.attachments.map { + AttachmentViewData(it, actionable.id, actionable.url) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/keylesspalace/tusky/viewdata/StatusViewData.java b/app/src/main/java/com/keylesspalace/tusky/viewdata/StatusViewData.java index 639677bcd..647b8266d 100644 --- a/app/src/main/java/com/keylesspalace/tusky/viewdata/StatusViewData.java +++ b/app/src/main/java/com/keylesspalace/tusky/viewdata/StatusViewData.java @@ -23,13 +23,14 @@ import com.keylesspalace.tusky.entity.Card; import com.keylesspalace.tusky.entity.Emoji; import com.keylesspalace.tusky.entity.Status; +import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.List; /** * Created by charlag on 11/07/2017. - * + *

* Class to represent data required to display either a notification or a placeholder. * It is either a {@link StatusViewData.Concrete} or a {@link StatusViewData.Placeholder}. */ @@ -47,7 +48,7 @@ public abstract class StatusViewData { @Nullable private final String spoilerText; private final Status.Visibility visibility; - private final Attachment[] attachments; + private final List attachments; @Nullable private final String rebloggedByUsername; @Nullable @@ -74,7 +75,7 @@ public abstract class StatusViewData { private final Card card; public Concrete(String id, Spanned content, boolean reblogged, boolean favourited, - @Nullable String spoilerText, Status.Visibility visibility, Attachment[] attachments, + @Nullable String spoilerText, Status.Visibility visibility, List attachments, @Nullable String rebloggedByUsername, @Nullable String rebloggedAvatar, boolean sensitive, boolean isExpanded, boolean isShowingContent, String userFullName, String nickname, String avatar, Date createdAt, int reblogsCount, int favouritesCount, @Nullable String inReplyToId, @@ -132,7 +133,7 @@ public abstract class StatusViewData { return visibility; } - public Attachment[] getAttachments() { + public List getAttachments() { return attachments; } @@ -234,7 +235,7 @@ public abstract class StatusViewData { private boolean favourited; private String spoilerText; private Status.Visibility visibility; - private Attachment[] attachments; + private List attachments; private String rebloggedByUsername; private String rebloggedAvatar; private boolean isSensitive; @@ -264,7 +265,7 @@ public abstract class StatusViewData { favourited = viewData.favourited; spoilerText = viewData.spoilerText; visibility = viewData.visibility; - attachments = viewData.attachments == null ? null : viewData.attachments.clone(); + attachments = viewData.attachments == null ? null : new ArrayList<>(viewData.attachments); rebloggedByUsername = viewData.rebloggedByUsername; rebloggedAvatar = viewData.rebloggedAvatar; isSensitive = viewData.isSensitive; @@ -315,7 +316,7 @@ public abstract class StatusViewData { return this; } - public Builder setAttachments(Attachment[] attachments) { + public Builder setAttachments(List attachments) { this.attachments = attachments; return this; } diff --git a/app/src/main/res/layout/activity_account.xml b/app/src/main/res/layout/activity_account.xml index 140c779cf..a66dd0343 100644 --- a/app/src/main/res/layout/activity_account.xml +++ b/app/src/main/res/layout/activity_account.xml @@ -179,7 +179,7 @@ android:layout_gravity="top" android:background="@android:color/transparent" app:layout_collapseMode="pin" - app:popupTheme="?attr/account_toolbar_popup_theme" /> + app:popupTheme="?attr/toolbar_popup_theme" /> diff --git a/app/src/main/res/layout/activity_view_media.xml b/app/src/main/res/layout/activity_view_media.xml index 99d8e1077..cce611987 100644 --- a/app/src/main/res/layout/activity_view_media.xml +++ b/app/src/main/res/layout/activity_view_media.xml @@ -15,8 +15,8 @@ android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" + android:background="@color/toolbar_view_media" android:theme="@style/AppTheme.Account.AppBarLayout" - app:popupTheme="@style/AppTheme.Account.ToolbarPopupTheme.Dark" - android:background="@color/toolbar_view_media" /> + app:popupTheme="?attr/toolbar_popup_theme"/> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_view_media.xml b/app/src/main/res/layout/fragment_view_media.xml index 723f523b0..0a0299c50 100644 --- a/app/src/main/res/layout/fragment_view_media.xml +++ b/app/src/main/res/layout/fragment_view_media.xml @@ -1,9 +1,11 @@ + android:clickable="true" + android:focusable="true"> + + \ No newline at end of file diff --git a/app/src/main/res/menu/view_media_toolbar.xml b/app/src/main/res/menu/view_media_toolbar.xml index 1de914f5f..927584290 100644 --- a/app/src/main/res/menu/view_media_toolbar.xml +++ b/app/src/main/res/menu/view_media_toolbar.xml @@ -6,4 +6,8 @@ android:icon="@drawable/ic_file_download_black_24dp" android:title="@string/dialog_download_image" app:showAsAction="always" /> + \ No newline at end of file diff --git a/app/src/main/res/values-night/styles.xml b/app/src/main/res/values-night/styles.xml index a1e88bf0c..273d3e87b 100644 --- a/app/src/main/res/values-night/styles.xml +++ b/app/src/main/res/values-night/styles.xml @@ -41,7 +41,7 @@ @color/account_header_background_dark @color/toolbar_icon_dark @color/account_toolbar_icon_collapsed_dark - @style/AppTheme.Account.ToolbarPopupTheme.Dark + @style/AppTheme.Account.ToolbarPopupTheme.Dark @color/toolbar_icon_dark @color/compose_media_button_disabled_dark @color/color_accent_dark diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 23f677b0d..6eb43e322 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -27,7 +27,7 @@ - + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 92da96ccc..a25c698ef 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -315,6 +315,7 @@ You\'ll need to download these emoji sets first Performing lookup... Expand/Collapse all statuses + Open toot App restart required You\'ll need to restart Tusky in order to apply these changes Later diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index eb90dc4a6..1847b8807 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -74,7 +74,7 @@ @color/account_header_background_light @color/toolbar_icon_dark @color/account_toolbar_icon_collapsed_light - @style/AppTheme.Account.ToolbarPopupTheme.Light + @style/AppTheme.Account.ToolbarPopupTheme.Light @color/toolbar_icon_light @color/compose_media_button_disabled_light @color/compose_mention_light diff --git a/app/src/test/java/com/keylesspalace/tusky/BottomSheetActivityTest.kt b/app/src/test/java/com/keylesspalace/tusky/BottomSheetActivityTest.kt index 0ffda3540..9bc4f96ed 100644 --- a/app/src/test/java/com/keylesspalace/tusky/BottomSheetActivityTest.kt +++ b/app/src/test/java/com/keylesspalace/tusky/BottomSheetActivityTest.kt @@ -78,7 +78,7 @@ class BottomSheetActivityTest { false, "", Status.Visibility.PUBLIC, - arrayOf(), + listOf(), arrayOf(), null )