diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/ImageDescriptionSheet.java b/mastodon/src/main/java/org/joinmastodon/android/ui/ImageDescriptionSheet.java new file mode 100644 index 000000000..fa2ab5338 --- /dev/null +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/ImageDescriptionSheet.java @@ -0,0 +1,87 @@ +package org.joinmastodon.android.ui; + +import android.app.Activity; +import android.graphics.Typeface; +import android.graphics.drawable.ColorDrawable; +import android.os.Build; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowInsets; +import android.widget.FrameLayout; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.LinearLayoutManager; + +import org.joinmastodon.android.R; +import org.joinmastodon.android.model.Attachment; +import org.joinmastodon.android.ui.utils.UiUtils; + +import me.grishka.appkit.utils.SingleViewRecyclerAdapter; +import me.grishka.appkit.utils.V; +import me.grishka.appkit.views.BottomSheet; +import me.grishka.appkit.views.UsableRecyclerView; + +public class ImageDescriptionSheet extends BottomSheet{ + private UsableRecyclerView list; + + public ImageDescriptionSheet(@NonNull Activity activity, Attachment attachment){ + super(activity); + + View handleView=new View(activity); + handleView.setBackgroundResource(R.drawable.bg_bottom_sheet_handle); + ViewGroup handle=new FrameLayout(activity); + handle.addView(handleView); + handle.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, V.dp(24))); + + TextView textView = new TextView(activity); + if (attachment.description == null || attachment.description.isEmpty()) { + textView.setText(R.string.media_no_description); + textView.setTypeface(null, Typeface.ITALIC); + } else { + textView.setText(attachment.description); + textView.setTextIsSelectable(true); + } + + TextView heading=new TextView(activity); + heading.setText(R.string.image_description); + heading.setAllCaps(true); + heading.setTypeface(null, Typeface.BOLD); + heading.setPadding(0, V.dp(24), 0, V.dp(8)); + + LinearLayout linearLayout = new LinearLayout(activity); + linearLayout.setOrientation(LinearLayout.VERTICAL); + linearLayout.setPadding(V.dp(24), 0, V.dp(24), 0); + linearLayout.addView(heading); + linearLayout.addView(textView); + + FrameLayout layout=new FrameLayout(activity); + layout.addView(handle); + layout.addView(linearLayout); + + list=new UsableRecyclerView(activity); + list.setLayoutManager(new LinearLayoutManager(activity)); + list.setBackgroundResource(R.drawable.bg_bottom_sheet); + list.setAdapter(new SingleViewRecyclerAdapter(layout)); + list.setClipToPadding(false); + + setContentView(list); + setNavigationBarBackground(new ColorDrawable(UiUtils.getThemeColor(activity, R.attr.colorWindowBackground)), !UiUtils.isDarkTheme()); + } + + @Override + protected void onWindowInsetsUpdated(WindowInsets insets){ + if(Build.VERSION.SDK_INT>=29){ + int tappableBottom=insets.getTappableElementInsets().bottom; + int insetBottom=insets.getSystemWindowInsetBottom(); + if(tappableBottom==0 && insetBottom>0){ + list.setPadding(0, 0, 0, V.dp(48)-insetBottom); + }else{ + list.setPadding(0, 0, 0, V.dp(24)); + } + }else{ + list.setPadding(0, 0, 0, V.dp(24)); + } + } +} diff --git a/mastodon/src/main/java/org/joinmastodon/android/ui/photoviewer/PhotoViewer.java b/mastodon/src/main/java/org/joinmastodon/android/ui/photoviewer/PhotoViewer.java index d9c0c8334..0e128d53a 100644 --- a/mastodon/src/main/java/org/joinmastodon/android/ui/photoviewer/PhotoViewer.java +++ b/mastodon/src/main/java/org/joinmastodon/android/ui/photoviewer/PhotoViewer.java @@ -19,6 +19,7 @@ import android.media.AudioManager; import android.media.MediaPlayer; import android.media.MediaScannerConnection; import android.net.Uri; +import android.opengl.Visibility; import android.os.Build; import android.os.Environment; import android.os.SystemClock; @@ -39,6 +40,7 @@ import android.view.WindowManager; import android.widget.FrameLayout; import android.widget.ImageButton; import android.widget.ImageView; +import android.widget.PopupWindow; import android.widget.ProgressBar; import android.widget.SeekBar; import android.widget.TextView; @@ -48,12 +50,14 @@ import android.widget.Toolbar; import org.joinmastodon.android.R; import org.joinmastodon.android.api.MastodonAPIController; import org.joinmastodon.android.model.Attachment; +import org.joinmastodon.android.ui.ImageDescriptionSheet; import org.joinmastodon.android.ui.M3AlertDialogBuilder; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -69,6 +73,7 @@ import me.grishka.appkit.imageloader.requests.UrlImageLoaderRequest; import me.grishka.appkit.utils.BindableViewHolder; import me.grishka.appkit.utils.CubicBezierInterpolator; import me.grishka.appkit.utils.V; +import me.grishka.appkit.views.BottomSheet; import me.grishka.appkit.views.FragmentRootLinearLayout; import okio.BufferedSink; import okio.Okio; @@ -97,6 +102,7 @@ public class PhotoViewer implements ZoomPanView.Listener{ private TextView videoTimeView; private ImageButton videoPlayPauseButton; private View videoControls; + private MenuItem imageDescriptionButton; private boolean uiVisible=true; private AudioManager.OnAudioFocusChangeListener audioFocusListener=this::onAudioFocusChanged; private Runnable uiAutoHider=()->{ @@ -174,11 +180,24 @@ public class PhotoViewer implements ZoomPanView.Listener{ toolbarWrap=uiOverlay.findViewById(R.id.toolbar_wrap); toolbar=uiOverlay.findViewById(R.id.toolbar); toolbar.setNavigationOnClickListener(v->onStartSwipeToDismissTransition(0)); - toolbar.getMenu().add(R.string.download).setIcon(R.drawable.ic_fluent_arrow_download_24_regular).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); - toolbar.setOnMenuItemClickListener(item->{ - saveCurrentFile(); - return true; - }); + imageDescriptionButton = toolbar.getMenu() + .add(R.string.image_description) + .setIcon(R.drawable.ic_fluent_image_alt_text_24_regular) + .setVisible(attachments.get(pager.getCurrentItem()).description != null + && !attachments.get(pager.getCurrentItem()).description.isEmpty()) + .setOnMenuItemClickListener(item -> { + new ImageDescriptionSheet(activity,attachments.get(pager.getCurrentItem())).show(); + return true; + }); + imageDescriptionButton.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); + toolbar.getMenu() + .add(R.string.download) + .setIcon(R.drawable.ic_fluent_arrow_download_24_regular) + .setOnMenuItemClickListener(item -> { + saveCurrentFile(); + return true; + }) + .setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS); uiOverlay.setAlpha(0f); videoControls=uiOverlay.findViewById(R.id.video_player_controls); videoSeekBar=uiOverlay.findViewById(R.id.seekbar); @@ -374,6 +393,8 @@ public class PhotoViewer implements ZoomPanView.Listener{ private void onPageChanged(int index){ currentIndex=index; Attachment att=attachments.get(index); + imageDescriptionButton.setVisible(att.description != null && !att.description.isEmpty()); + toolbar.invalidate(); V.setVisibilityAnimated(videoControls, att.type==Attachment.Type.VIDEO ? View.VISIBLE : View.GONE); if(att.type==Attachment.Type.VIDEO){ videoSeekBar.setSecondaryProgress(0); diff --git a/mastodon/src/main/res/drawable/ic_fluent_image_alt_text_24_regular.xml b/mastodon/src/main/res/drawable/ic_fluent_image_alt_text_24_regular.xml new file mode 100644 index 000000000..037d623c3 --- /dev/null +++ b/mastodon/src/main/res/drawable/ic_fluent_image_alt_text_24_regular.xml @@ -0,0 +1,3 @@ + + + diff --git a/mastodon/src/main/res/values-de-rDE/strings.xml b/mastodon/src/main/res/values-de-rDE/strings.xml index 0f904471a..f3a3efca3 100644 --- a/mastodon/src/main/res/values-de-rDE/strings.xml +++ b/mastodon/src/main/res/values-de-rDE/strings.xml @@ -203,6 +203,7 @@ Bestätigungs-E-Mail gesendet Was gibt\'s Neues? Inhaltswarnung + Bildbeschreibung Füge eine Bildbeschreibung hinzu… Upload erneut versuchen Fehler beim Hochladen des Bildes @@ -316,7 +317,7 @@ Genehmigt Folgende manuell Aktuelles Konto %s ausloggen - + %,d Follower %,d Follower diff --git a/mastodon/src/main/res/values/strings.xml b/mastodon/src/main/res/values/strings.xml index 9f0b83b2e..4a80c45f5 100644 --- a/mastodon/src/main/res/values/strings.xml +++ b/mastodon/src/main/res/values/strings.xml @@ -209,6 +209,7 @@ Type or paste what\'s on your mind Content warning Add image description… + Image description Retry upload Image failed to upload Video failed to upload