From 0714952b23624f23ba1b27c5b60af60937717492 Mon Sep 17 00:00:00 2001 From: tom79 Date: Wed, 9 Oct 2019 18:49:33 +0200 Subject: [PATCH] Change mediaActivity --- app/src/main/AndroidManifest.xml | 6 + .../activities/ShowAccountActivity.java | 2 +- .../activities/SlideMediaActivity.java | 182 +++++ .../android/drawers/ArtListAdapter.java | 10 +- .../fedilab/android/drawers/ImageAdapter.java | 10 +- .../drawers/NotificationsListAdapter.java | 9 +- .../android/drawers/PixelfedListAdapter.java | 9 +- .../android/drawers/SliderAdapter.java | 7 +- .../android/drawers/StatusListAdapter.java | 9 +- .../fragments/MediaSliderFragment.java | 647 ++++++++++++++++++ .../main/res/layout/activity_media_pager.xml | 31 + .../main/res/layout/fragment_slide_media.xml | 256 +++++++ 12 files changed, 1165 insertions(+), 13 deletions(-) create mode 100644 app/src/main/java/app/fedilab/android/activities/SlideMediaActivity.java create mode 100644 app/src/main/java/app/fedilab/android/fragments/MediaSliderFragment.java create mode 100644 app/src/main/res/layout/activity_media_pager.xml create mode 100644 app/src/main/res/layout/fragment_slide_media.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f96b6fdfd..462771183 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -313,6 +313,12 @@ android:theme="@style/Theme.Transparent" android:configChanges="keyboardHidden|orientation|screenSize" android:noHistory="true" /> + . */ +package app.fedilab.android.activities; + + + +import android.content.SharedPreferences; +import android.os.Bundle; +import android.util.Log; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.ViewGroup; +import android.widget.RelativeLayout; + +import androidx.coordinatorlayout.widget.CoordinatorLayout; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentStatePagerAdapter; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; + + +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; + +import app.fedilab.android.R; +import app.fedilab.android.client.Entities.Attachment; +import app.fedilab.android.fragments.MediaSliderFragment; +import app.fedilab.android.helper.Helper; + + + +/** + * Created by Thomas on 25/06/2017. + * Media Activity + */ + +public class SlideMediaActivity extends BaseActivity { + + private ArrayList attachments; + private int mediaPosition; + private ViewPager mPager; + + @Override + protected void onCreate(Bundle savedInstanceState) { + SharedPreferences sharedpreferences = getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); + int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK); + if (theme == Helper.THEME_BLACK) + setTheme(R.style.TransparentBlack); + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_media_pager); + supportPostponeEnterTransition(); + supportStartPostponedEnterTransition(); + CoordinatorLayout main_container_media = findViewById(R.id.main_container_media); + if (theme == Helper.THEME_LIGHT) { + main_container_media.setBackgroundResource(R.color.mastodonC2); + } else if (theme == Helper.THEME_BLACK) { + main_container_media.setBackgroundResource(R.color.black); + } else if (theme == Helper.THEME_DARK) { + main_container_media.setBackgroundResource(R.color.mastodonC1_); + } + attachments = getIntent().getParcelableArrayListExtra("mediaArray"); + if (getIntent().getExtras() != null) + mediaPosition = getIntent().getExtras().getInt("position", 1); + gestureDetector = new GestureDetector(new SwipeDetector()); + + if (attachments == null || attachments.size() == 0) + finish(); + mPager = findViewById(R.id.media_viewpager); + + PagerAdapter mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager()); + mPager.setAdapter(mPagerAdapter); + + mPager.setCurrentItem(mediaPosition-1); + + } + + private MediaSliderFragment mCurrentFragment; + + + public MediaSliderFragment getCurrentFragment() { + return mCurrentFragment; + } + + /** + * Media Pager + */ + private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter { + + ScreenSlidePagerAdapter(FragmentManager fm) { + super(fm); + } + + @NotNull + @Override + public Fragment getItem(int position) { + Bundle bundle = new Bundle(); + MediaSliderFragment mediaSliderFragment = new MediaSliderFragment(); + bundle.putInt("position", position); + Log.v(Helper.TAG,"position: " + position); + Log.v(Helper.TAG,"attachments.get(position): " + attachments.get(position)); + bundle.putParcelable("attachment", attachments.get(position)); + mediaSliderFragment.setArguments(bundle); + return mediaSliderFragment; + } + + @Override + public void setPrimaryItem(@NotNull ViewGroup container, int position, @NotNull Object object) { + if (getCurrentFragment() != object) { + mCurrentFragment = ((MediaSliderFragment) object); + } + super.setPrimaryItem(container, position, object); + } + + @Override + public int getCount() { + return attachments.size(); + } + } + + private static final int SWIPE_MIN_DISTANCE = 120; + private static final int SWIPE_MAX_OFF_PATH = 250; + private static final int SWIPE_THRESHOLD_VELOCITY = 200; + private GestureDetector gestureDetector; + + private class SwipeDetector extends GestureDetector.SimpleOnGestureListener { + @Override + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + + // Check movement along the Y-axis. If it exceeds SWIPE_MAX_OFF_PATH, + // then dismiss the swipe. + if (Math.abs(e1.getX() - e2.getX()) > SWIPE_MAX_OFF_PATH) + return false; + + // Swipe from left to right. + // The swipe needs to exceed a certain distance (SWIPE_MIN_DISTANCE) + // and a certain velocity (SWIPE_THRESHOLD_VELOCITY). + if (e2.getY() - e1.getY() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) { + if( mCurrentFragment.canSwipe()) { + finish(); + return true; + }else{ + return false; + } + } + + return false; + } + } + + + @Override + public boolean dispatchTouchEvent(MotionEvent ev) { + // TouchEvent dispatcher. + if (gestureDetector != null) { + if (gestureDetector.onTouchEvent(ev)) + // If the gestureDetector handles the event, a swipe has been + // executed and no more needs to be done. + return true; + } + return super.dispatchTouchEvent(ev); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + return gestureDetector.onTouchEvent(event); + } + +} diff --git a/app/src/main/java/app/fedilab/android/drawers/ArtListAdapter.java b/app/src/main/java/app/fedilab/android/drawers/ArtListAdapter.java index 6ddd5d45a..9500c7a58 100644 --- a/app/src/main/java/app/fedilab/android/drawers/ArtListAdapter.java +++ b/app/src/main/java/app/fedilab/android/drawers/ArtListAdapter.java @@ -15,6 +15,7 @@ package app.fedilab.android.drawers; * see . */ import android.annotation.SuppressLint; +import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; @@ -22,6 +23,8 @@ import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; import androidx.annotation.NonNull; +import androidx.core.app.ActivityOptionsCompat; +import androidx.core.view.ViewCompat; import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; @@ -38,6 +41,7 @@ import com.bumptech.glide.Glide; import java.util.ArrayList; import java.util.List; +import app.fedilab.android.activities.SlideMediaActivity; import app.fedilab.android.client.API; import app.fedilab.android.client.APIResponse; import app.fedilab.android.client.Entities.Attachment; @@ -203,7 +207,7 @@ public class ArtListAdapter extends RecyclerView.Adapter implements OnPostAction holder.art_media.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - Intent intent = new Intent(context, MediaActivity.class); + Intent intent = new Intent(context, SlideMediaActivity.class); Bundle b = new Bundle(); ArrayList attachments = new ArrayList<>(); if (status.getArt_attachment() != null) @@ -213,7 +217,9 @@ public class ArtListAdapter extends RecyclerView.Adapter implements OnPostAction intent.putParcelableArrayListExtra("mediaArray", attachments); b.putInt("position", 0); intent.putExtras(b); - context.startActivity(intent); + ViewCompat.setTransitionName(v, status.getMedia_attachments().get(0).getUrl()); + ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation((Activity) context, v, status.getMedia_attachments().get(0).getUrl()); + context.startActivity(intent, options.toBundle()); } }); holder.art_author.setOnClickListener(new View.OnClickListener() { diff --git a/app/src/main/java/app/fedilab/android/drawers/ImageAdapter.java b/app/src/main/java/app/fedilab/android/drawers/ImageAdapter.java index 048d20b9c..21a5ad8f3 100644 --- a/app/src/main/java/app/fedilab/android/drawers/ImageAdapter.java +++ b/app/src/main/java/app/fedilab/android/drawers/ImageAdapter.java @@ -14,11 +14,14 @@ package app.fedilab.android.drawers; * You should have received a copy of the GNU General Public License along with Fedilab; if not, * see . */ +import android.app.Activity; import android.content.Context; import android.content.Intent; import android.os.Bundle; import androidx.annotation.NonNull; +import androidx.core.app.ActivityOptionsCompat; +import androidx.core.view.ViewCompat; import androidx.recyclerview.widget.RecyclerView; import android.view.LayoutInflater; @@ -31,6 +34,7 @@ import com.bumptech.glide.Glide; import java.util.ArrayList; import java.util.List; +import app.fedilab.android.activities.SlideMediaActivity; import app.fedilab.android.client.Entities.Attachment; import app.fedilab.android.client.Entities.Status; import app.fedilab.android.R; @@ -79,7 +83,7 @@ public class ImageAdapter extends RecyclerView.Adapter { holder.imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - Intent intent = new Intent(context, MediaActivity.class); + Intent intent = new Intent(context, SlideMediaActivity.class); Bundle b = new Bundle(); ArrayList attachmentsTmp = new ArrayList<>(); for (Status status1 : statuses) { @@ -88,7 +92,9 @@ public class ImageAdapter extends RecyclerView.Adapter { intent.putParcelableArrayListExtra("mediaArray", attachmentsTmp); b.putInt("position", (viewHolder.getAdapterPosition() + 1)); intent.putExtras(b); - context.startActivity(intent); + ViewCompat.setTransitionName(v, status.getMedia_attachments().get(0).getUrl()); + ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation((Activity) context, v, status.getMedia_attachments().get(0).getUrl()); + context.startActivity(intent, options.toBundle()); } }); holder.imageView.setOnLongClickListener(new View.OnLongClickListener() { diff --git a/app/src/main/java/app/fedilab/android/drawers/NotificationsListAdapter.java b/app/src/main/java/app/fedilab/android/drawers/NotificationsListAdapter.java index a8fa57898..4febdc014 100644 --- a/app/src/main/java/app/fedilab/android/drawers/NotificationsListAdapter.java +++ b/app/src/main/java/app/fedilab/android/drawers/NotificationsListAdapter.java @@ -32,9 +32,11 @@ import android.os.Handler; import androidx.annotation.NonNull; import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.core.app.ActivityOptionsCompat; import androidx.core.content.ContextCompat; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.PopupMenu; +import androidx.core.view.ViewCompat; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -75,6 +77,7 @@ import java.util.TimerTask; import app.fedilab.android.activities.AccountReportActivity; import app.fedilab.android.activities.BaseMainActivity; import app.fedilab.android.activities.OwnerNotificationChartsActivity; +import app.fedilab.android.activities.SlideMediaActivity; import app.fedilab.android.client.API; import app.fedilab.android.client.APIResponse; import app.fedilab.android.client.Entities.Account; @@ -1380,12 +1383,14 @@ public class NotificationsListAdapter extends RecyclerView.Adapter implements On imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - Intent intent = new Intent(context, MediaActivity.class); + Intent intent = new Intent(context, SlideMediaActivity.class); Bundle b = new Bundle(); intent.putParcelableArrayListExtra("mediaArray", notification.getStatus().getMedia_attachments()); b.putInt("position", finalPosition); intent.putExtras(b); - context.startActivity(intent); + ViewCompat.setTransitionName(v, notification.getStatus().getMedia_attachments().get(0).getUrl()); + ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation((Activity) context, v, notification.getStatus().getMedia_attachments().get(0).getUrl()); + context.startActivity(intent, options.toBundle()); } }); i++; diff --git a/app/src/main/java/app/fedilab/android/drawers/PixelfedListAdapter.java b/app/src/main/java/app/fedilab/android/drawers/PixelfedListAdapter.java index 8a160597a..ef89ca75d 100644 --- a/app/src/main/java/app/fedilab/android/drawers/PixelfedListAdapter.java +++ b/app/src/main/java/app/fedilab/android/drawers/PixelfedListAdapter.java @@ -33,8 +33,10 @@ import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.PopupMenu; import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.core.app.ActivityOptionsCompat; import androidx.core.content.ContextCompat; import androidx.cardview.widget.CardView; +import androidx.core.view.ViewCompat; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -80,6 +82,7 @@ import java.util.List; import app.fedilab.android.activities.MediaActivity; import app.fedilab.android.activities.PixelfedComposeActivity; +import app.fedilab.android.activities.SlideMediaActivity; import app.fedilab.android.activities.TootActivity; import app.fedilab.android.activities.TootInfoActivity; import app.fedilab.android.asynctasks.PostActionAsyncTask; @@ -481,12 +484,14 @@ public class PixelfedListAdapter extends RecyclerView.Adapter implements OnPostA holder.art_media.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - Intent intent = new Intent(context, MediaActivity.class); + Intent intent = new Intent(context, SlideMediaActivity.class); Bundle b = new Bundle(); intent.putParcelableArrayListExtra("mediaArray", status.getMedia_attachments()); b.putInt("position", 0); intent.putExtras(b); - context.startActivity(intent); + ViewCompat.setTransitionName(v, status.getMedia_attachments().get(0).getUrl()); + ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation((Activity) context, v, status.getMedia_attachments().get(0).getUrl()); + context.startActivity(intent, options.toBundle()); } }); diff --git a/app/src/main/java/app/fedilab/android/drawers/SliderAdapter.java b/app/src/main/java/app/fedilab/android/drawers/SliderAdapter.java index bedf85881..f8754093f 100644 --- a/app/src/main/java/app/fedilab/android/drawers/SliderAdapter.java +++ b/app/src/main/java/app/fedilab/android/drawers/SliderAdapter.java @@ -36,6 +36,7 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; import androidx.appcompat.app.AlertDialog; +import androidx.core.app.ActivityOptionsCompat; import com.bumptech.glide.Glide; import com.bumptech.glide.request.target.SimpleTarget; @@ -49,6 +50,7 @@ import java.util.List; import app.fedilab.android.R; import app.fedilab.android.activities.MediaActivity; import app.fedilab.android.activities.PixelfedComposeActivity; +import app.fedilab.android.activities.SlideMediaActivity; import app.fedilab.android.asynctasks.UpdateDescriptionAttachmentAsyncTask; import app.fedilab.android.client.Entities.Attachment; import app.fedilab.android.client.Entities.Error; @@ -105,13 +107,14 @@ public class SliderAdapter extends SliderViewAdapter. */ + +import android.Manifest; +import android.app.Activity; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.graphics.RectF; +import android.media.MediaPlayer; +import android.net.Uri; +import android.os.AsyncTask; +import android.os.Build; +import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.WindowManager; +import android.webkit.WebView; +import android.widget.FrameLayout; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.target.SimpleTarget; +import com.bumptech.glide.request.transition.Transition; +import com.cleveroad.audiovisualization.DbmHandler; +import com.cleveroad.audiovisualization.GLAudioVisualizationView; +import com.github.chrisbanes.photoview.OnMatrixChangedListener; +import com.github.chrisbanes.photoview.PhotoView; +import com.google.android.exoplayer2.ExoPlayerFactory; +import com.google.android.exoplayer2.Player; +import com.google.android.exoplayer2.SimpleExoPlayer; +import com.google.android.exoplayer2.source.ExtractorMediaSource; +import com.google.android.exoplayer2.ui.SimpleExoPlayerView; +import com.google.android.exoplayer2.upstream.DataSource; +import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; +import com.google.android.exoplayer2.util.Util; +import com.gw.swipeback.SwipeBackLayout; + +import org.jetbrains.annotations.NotNull; + +import java.io.File; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; + +import javax.net.ssl.HttpsURLConnection; + +import app.fedilab.android.R; +import app.fedilab.android.activities.MediaActivity; +import app.fedilab.android.asynctasks.RetrieveFeedsAsyncTask; +import app.fedilab.android.client.APIResponse; +import app.fedilab.android.client.Entities.Attachment; +import app.fedilab.android.client.Entities.Error; +import app.fedilab.android.client.Entities.Status; +import app.fedilab.android.client.HttpsConnection; +import app.fedilab.android.client.TLSSocketFactory; +import app.fedilab.android.drawers.ImageAdapter; +import app.fedilab.android.helper.Helper; +import app.fedilab.android.interfaces.OnDownloadInterface; +import app.fedilab.android.interfaces.OnRetrieveFeedsInterface; +import app.fedilab.android.webview.MastalabWebChromeClient; +import app.fedilab.android.webview.MastalabWebViewClient; +import cafe.adriel.androidaudiorecorder.VisualizerHandler; +import es.dmoral.toasty.Toasty; + +import static android.content.Context.MODE_PRIVATE; +import static app.fedilab.android.helper.Helper.changeDrawableColor; +import static cafe.adriel.androidaudiorecorder.Util.formatSeconds; +import static cafe.adriel.androidaudiorecorder.Util.getDarkerColor; + + +/** + * Created by Thomas on 09/10/2019. + * Fragment to display media from SlideMediaActivity + */ +public class MediaSliderFragment extends Fragment implements OnDownloadInterface, MediaPlayer.OnCompletionListener { + + + private boolean flag_loading; + private Context context; + private AsyncTask asyncTask; + private String max_id; + private RelativeLayout mainLoader, nextElementLoader, textviewNoAction; + private boolean firstLoad; + private String targetedId; + private boolean showMediaOnly, showPinned, showReply; + boolean firstTootsLoaded; + private SharedPreferences sharedpreferences; + private ArrayList statuses; + private ImageAdapter gridAdaper; + private RecyclerView gridview; + private int mediaPosition; + + + + private WebView webview_video; + private ImageButton media_save, media_share, media_close; + private boolean scheduleHidden, scheduleHiddenDescription; + private SimpleExoPlayer player; + private boolean isSHaring; + private String instance; + private RelativeLayout content_audio; + private MediaPlayer playeraudio; + private Timer timer; + private int playerSecondsElapsed; + private static final Handler HANDLER = new Handler(); + private String url; + + private RelativeLayout loader; + private ArrayList attachments; + private PhotoView imageView; + private SimpleExoPlayerView videoView; + private float downX; + private float downY; + static final int MIN_DISTANCE = 100; + private String finalUrlDownload; + private String preview_url; + private ImageView prev, next; + private boolean isControlElementShown = true; + private Bitmap downloadedImage; + private File fileVideo; + private TextView progress; + private ProgressBar pbar_inf; + private TextView message_ready; + private boolean canSwipe; + private TextView media_description; + private Attachment attachment; + private float imageScale = 0; + private RelativeLayout action_bar_container; + private VisualizerHandler visualizerHandler; + private TextView statusView; + private TextView timerView; + private ImageButton playView; + private GLAudioVisualizationView visualizerView; + public MediaSliderFragment() { + } + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View rootView = inflater.inflate(R.layout.fragment_slide_media, container, false); + + context = getContext(); + Bundle bundle = this.getArguments(); + + if (bundle != null) { + mediaPosition = bundle.getInt("position", 1); + attachment = bundle.getParcelable("attachment"); + } + Log.v(Helper.TAG,mediaPosition + " -> " + attachment); + media_description = rootView.findViewById(R.id.media_description); + message_ready = rootView.findViewById(R.id.message_ready); + media_save = rootView.findViewById(R.id.media_save); + media_share = rootView.findViewById(R.id.media_share); + media_close = rootView.findViewById(R.id.media_close); + progress = rootView.findViewById(R.id.loader_progress); + webview_video = rootView.findViewById(R.id.webview_video); + content_audio = rootView.findViewById(R.id.content_audio); + media_save.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + isSHaring = false; + if (attachment.getType().toLowerCase().equals("video") || attachment.getType().toLowerCase().equals("audio") || attachment.getType().toLowerCase().equals("gifv") || attachment.getType().toLowerCase().equals("web")) { + if (attachment != null) { + progress.setText("0 %"); + progress.setVisibility(View.VISIBLE); + new HttpsConnection(context, instance).download(attachment.getUrl(), MediaSliderFragment.this); + } + } else { + if (Build.VERSION.SDK_INT >= 23) { + if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions((Activity)context, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, Helper.EXTERNAL_STORAGE_REQUEST_CODE); + } else { + Helper.manageMoveFileDownload(context, preview_url, finalUrlDownload, downloadedImage, fileVideo, false); + } + } else { + Helper.manageMoveFileDownload(context, preview_url, finalUrlDownload, downloadedImage, fileVideo, false); + } + } + } + }); + media_share.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + isSHaring = true; + if (attachment.getType().toLowerCase().equals("video") || attachment.getType().toLowerCase().equals("audio") || attachment.getType().toLowerCase().equals("gifv")) { + if (attachment != null) { + progress.setText("0 %"); + progress.setVisibility(View.VISIBLE); + new HttpsConnection(context, instance).download(attachment.getUrl(), MediaSliderFragment.this); + } + } else { + if (Build.VERSION.SDK_INT >= 23) { + if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions((Activity)context, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, Helper.EXTERNAL_STORAGE_REQUEST_CODE); + } else { + Helper.manageMoveFileDownload(context, preview_url, finalUrlDownload, downloadedImage, fileVideo, true); + } + } else { + Helper.manageMoveFileDownload(context, preview_url, finalUrlDownload, downloadedImage, fileVideo, true); + } + } + } + }); + media_close.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + ((Activity)context).finish(); + } + }); + sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, MODE_PRIVATE); + int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK); + + loader = rootView.findViewById(R.id.loader); + imageView = rootView.findViewById(R.id.media_picture); + videoView = rootView.findViewById(R.id.media_video); + prev = rootView.findViewById(R.id.media_prev); + next = rootView.findViewById(R.id.media_next); + if (theme == Helper.THEME_BLACK) { + changeDrawableColor(context, prev, R.color.dark_icon); + changeDrawableColor(context, next, R.color.dark_icon); + } else if (theme == Helper.THEME_LIGHT) { + changeDrawableColor(context, prev, R.color.mastodonC4); + changeDrawableColor(context, next, R.color.mastodonC4); + } else { + changeDrawableColor(context, prev, R.color.white); + changeDrawableColor(context, next, R.color.white); + } + prev.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mediaPosition--; + } + }); + next.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mediaPosition++; + } + }); + + url = attachment.getUrl(); + imageView.setOnMatrixChangeListener(new OnMatrixChangedListener() { + @Override + public void onMatrixChanged(RectF rect) { + imageScale = imageView.getScale(); + canSwipe = (imageView.getScale() == 1); + } + }); + if (attachments != null && attachments.size() > 1) { + prev.setVisibility(View.VISIBLE); + next.setVisibility(View.VISIBLE); + } + pbar_inf = rootView.findViewById(R.id.pbar_inf); + String type = attachment.getType(); + preview_url = attachment.getPreview_url(); + if (type.equals("unknown")) { + preview_url = attachment.getRemote_url(); + if (preview_url.endsWith(".png") || preview_url.endsWith(".jpg") || preview_url.endsWith(".jpeg") || preview_url.endsWith(".gif")) { + type = "image"; + } else if (preview_url.endsWith(".mp4") || preview_url.endsWith(".mp3")) { + type = "video"; + } + url = attachment.getRemote_url(); + attachment.setType(type); + } + + switch (type.toLowerCase()) { + case "image": + pbar_inf.setScaleY(1f); + imageView.setVisibility(View.VISIBLE); + fileVideo = null; + pbar_inf.setIndeterminate(true); + loader.setVisibility(View.VISIBLE); + fileVideo = null; + if (!url.endsWith(".gif")) { + Glide.with(context) + .asBitmap() + .load(preview_url).into( + new SimpleTarget() { + @Override + public void onResourceReady(@NonNull final Bitmap resource, Transition transition) { + Bitmap imageCompressed = Helper.compressImageIfNeeded(context, resource); + imageView.setImageBitmap(imageCompressed); + Glide.with(context) + .asBitmap() + .load(url).into( + new SimpleTarget() { + @Override + public void onResourceReady(@NonNull final Bitmap resource, Transition transition) { + loader.setVisibility(View.GONE); + Bitmap imageCompressed = Helper.compressImageIfNeeded(context, resource); + if (imageView.getScale() < 1.1) { + downloadedImage = resource; + imageView.setImageBitmap(imageCompressed); + } else { + message_ready.setVisibility(View.VISIBLE); + } + message_ready.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + downloadedImage = resource; + imageView.setImageBitmap(imageCompressed); + message_ready.setVisibility(View.GONE); + } + }); + } + } + ); + } + } + ); + } else { + loader.setVisibility(View.GONE); + Glide.with(context) + .load(url).into(imageView); + } + break; + case "video": + case "gifv": + pbar_inf.setIndeterminate(false); + pbar_inf.setScaleY(3f); + try { + HttpsURLConnection.setDefaultSSLSocketFactory(new TLSSocketFactory(instance)); + } catch (KeyManagementException e) { + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } + videoView.setVisibility(View.VISIBLE); + Uri uri = Uri.parse(url); + DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(context, + Util.getUserAgent(context, "Fedilab"), null); + ExtractorMediaSource videoSource = new ExtractorMediaSource.Factory(dataSourceFactory) + .createMediaSource(uri); + player = ExoPlayerFactory.newSimpleInstance(context); + if (type.toLowerCase().equals("gifv")) + player.setRepeatMode(Player.REPEAT_MODE_ONE); + videoView.setPlayer(player); + loader.setVisibility(View.GONE); + player.prepare(videoSource); + player.setPlayWhenReady(true); + break; + case "web": + loader.setVisibility(View.GONE); + webview_video = Helper.initializeWebview((Activity)context, R.id.webview_video); + webview_video.setVisibility(View.VISIBLE); + FrameLayout webview_container = rootView.findViewById(R.id.main_media_frame); + final ViewGroup videoLayout = rootView.findViewById(R.id.videoLayout); + + MastalabWebChromeClient mastalabWebChromeClient = new MastalabWebChromeClient((Activity)context, webview_video, webview_container, videoLayout); + mastalabWebChromeClient.setOnToggledFullscreen(new MastalabWebChromeClient.ToggledFullscreenCallback() { + @Override + public void toggledFullscreen(boolean fullscreen) { + + if (fullscreen) { + videoLayout.setVisibility(View.VISIBLE); + WindowManager.LayoutParams attrs = ((Activity)context).getWindow().getAttributes(); + attrs.flags |= WindowManager.LayoutParams.FLAG_FULLSCREEN; + attrs.flags |= WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; + ((Activity)context).getWindow().setAttributes(attrs); + ((Activity)context).getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE); + } else { + WindowManager.LayoutParams attrs = ((Activity)context).getWindow().getAttributes(); + attrs.flags &= ~WindowManager.LayoutParams.FLAG_FULLSCREEN; + attrs.flags &= ~WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON; + ((Activity)context).getWindow().setAttributes(attrs); + ((Activity)context).getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); + videoLayout.setVisibility(View.GONE); + } + } + }); + webview_video.getSettings().setAllowFileAccess(true); + webview_video.setWebChromeClient(mastalabWebChromeClient); + webview_video.getSettings().setDomStorageEnabled(true); + webview_video.getSettings().setAppCacheEnabled(true); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + webview_video.getSettings().setMediaPlaybackRequiresUserGesture(false); + } + webview_video.setWebViewClient(new MastalabWebViewClient((Activity)context)); + webview_video.loadUrl(attachment.getUrl()); + break; + case "audio": + loader.setVisibility(View.GONE); + content_audio.setVisibility(View.VISIBLE); + int color = getResources().getColor(R.color.mastodonC1); + visualizerView = new GLAudioVisualizationView.Builder(context) + .setLayersCount(1) + .setWavesCount(6) + .setWavesHeight(R.dimen.aar_wave_height) + .setWavesFooterHeight(R.dimen.aar_footer_height) + .setBubblesPerLayer(20) + .setBubblesSize(R.dimen.aar_bubble_size) + .setBubblesRandomizeSize(true) + .setBackgroundColor(getDarkerColor(color)) + .setLayerColors(new int[]{color}) + .build(); + + statusView = rootView.findViewById(R.id.status); + timerView = rootView.findViewById(R.id.timer); + playView = rootView.findViewById(R.id.play); + content_audio.setBackgroundColor(getDarkerColor(color)); + content_audio.addView(visualizerView, 0); + playView.setVisibility(View.INVISIBLE); + this.url = attachment.getUrl(); + + startPlaying(); + break; + } + return rootView; + } + + + private void startPlaying() { + try { + + playeraudio = new MediaPlayer(); + playeraudio.setDataSource(url); + playeraudio.prepare(); + playeraudio.start(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + if (ContextCompat.checkSelfPermission(context, Manifest.permission.RECORD_AUDIO) == + PackageManager.PERMISSION_GRANTED) { + visualizerView.linkTo(DbmHandler.Factory.newVisualizerHandler(context, playeraudio)); + } + + } + visualizerView.post(new Runnable() { + @Override + public void run() { + playeraudio.setOnCompletionListener(MediaSliderFragment.this); + } + }); + + timerView.setText("00:00:00"); + playView.setVisibility(View.VISIBLE); + statusView.setText(R.string.aar_playing); + statusView.setVisibility(View.VISIBLE); + playView.setImageResource(R.drawable.aar_ic_stop); + + playerSecondsElapsed = 0; + startTimer(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + + private void stopPlaying() { + statusView.setText(""); + statusView.setVisibility(View.INVISIBLE); + playView.setImageResource(R.drawable.aar_ic_play); + + visualizerView.release(); + if (visualizerHandler != null) { + visualizerHandler.stop(); + } + + if (playeraudio != null) { + try { + playeraudio.pause(); + } catch (Exception ignored) { + } + } + + stopTimer(); + } + + private void startTimer() { + stopTimer(); + timer = new Timer(); + timer.scheduleAtFixedRate(new TimerTask() { + @Override + public void run() { + updateTimer(); + } + }, 0, 1000); + } + + private void updateTimer() { + ((Activity)context).runOnUiThread(new Runnable() { + @Override + public void run() { + playerSecondsElapsed++; + timerView.setText(formatSeconds(playerSecondsElapsed)); + } + }); + } + + private void stopTimer() { + if (timer != null) { + timer.cancel(); + timer.purge(); + timer = null; + } + } + + private boolean isPlaying() { + try { + return playeraudio != null && playeraudio.isPlaying(); + } catch (Exception e) { + return false; + } + } + + + + @Override + public void onCreate(Bundle saveInstance) { + super.onCreate(saveInstance); + } + + + + @Override + public void onAttach(@NotNull Context context) { + super.onAttach(context); + this.context = context; + } + + + @Override + public void onPause() { + super.onPause(); + if (player != null) { + player.setPlayWhenReady(false); + } + if (playeraudio != null) { + playeraudio.pause(); + } + try { + visualizerView.onPause(); + } catch (Exception ignored) { + } + } + + @Override + public void onDestroy() { + try { + if (visualizerView != null) { + visualizerView.release(); + } + if (player != null) { + player.release(); + } + if (playeraudio != null) { + playeraudio.release(); + } + } catch (Exception ignored) { + } + super.onDestroy(); + } + + @Override + public void onResume() { + super.onResume(); + if (player != null) { + player.setPlayWhenReady(true); + } + if (playeraudio != null) { + playeraudio.start(); + } + try { + visualizerView.onResume(); + } catch (Exception e) { + } + } + + + + @Override + public void onDownloaded(String path, String originUrl, Error error) { + if (path != null) { + File response = new File(path); + File dir = context.getCacheDir(); + File from = new File(dir, response.getName()); + File to = new File(dir, Helper.md5(originUrl) + ".mp4"); + if (from.exists()) + //noinspection ResultOfMethodCallIgnored + from.renameTo(to); + fileVideo = to; + downloadedImage = null; + } + if (Build.VERSION.SDK_INT >= 23) { + if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions((Activity)context, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, Helper.EXTERNAL_STORAGE_REQUEST_CODE); + } else { + Helper.manageMoveFileDownload(context, preview_url, finalUrlDownload, downloadedImage, fileVideo, isSHaring); + } + } else { + Helper.manageMoveFileDownload(context, preview_url, finalUrlDownload, downloadedImage, fileVideo, isSHaring); + } + if (progress != null) + progress.setVisibility(View.GONE); + if (loader != null) + loader.setVisibility(View.GONE); + } + + + public boolean canSwipe(){ + return canSwipe; + } + + @Override + public void onUpdateProgress(int progressPercentage) { + progress.setText(String.format("%s%%", String.valueOf(progressPercentage))); + pbar_inf.setProgress(progressPercentage); + } + + @Override + public void onCompletion(MediaPlayer mp) { + stopPlaying(); + } +} diff --git a/app/src/main/res/layout/activity_media_pager.xml b/app/src/main/res/layout/activity_media_pager.xml new file mode 100644 index 000000000..18d908872 --- /dev/null +++ b/app/src/main/res/layout/activity_media_pager.xml @@ -0,0 +1,31 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_slide_media.xml b/app/src/main/res/layout/fragment_slide_media.xml new file mode 100644 index 000000000..17f29a504 --- /dev/null +++ b/app/src/main/res/layout/fragment_slide_media.xml @@ -0,0 +1,256 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file