Add image viewer menu options

filtering
Floens 10 years ago
parent a06f2b9283
commit 32a4955504
  1. 6
      Clover/app/src/main/java/org/floens/chan/core/model/PostImage.java
  2. 17
      Clover/app/src/main/java/org/floens/chan/core/presenter/ImageViewerPresenter.java
  3. 6
      Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java
  4. 92
      Clover/app/src/main/java/org/floens/chan/ui/controller/ImageViewerController.java
  5. 5
      Clover/app/src/main/java/org/floens/chan/ui/controller/ImageViewerNavigationController.java
  6. 5
      Clover/app/src/main/java/org/floens/chan/ui/controller/ThreadController.java
  7. 6
      Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java
  8. 4
      Clover/app/src/main/java/org/floens/chan/ui/toolbar/NavigationItem.java
  9. 9
      Clover/app/src/main/java/org/floens/chan/ui/toolbar/Toolbar.java

@ -5,18 +5,22 @@ public class PostImage {
STATIC, GIF, MOVIE STATIC, GIF, MOVIE
} }
public String originalName;
public String thumbnailUrl; public String thumbnailUrl;
public String imageUrl; public String imageUrl;
public String filename; public String filename;
public String extension;
public int imageWidth; public int imageWidth;
public int imageHeight; public int imageHeight;
public Type type; public Type type;
public PostImage(String thumbnailUrl, String imageUrl, String filename, String extension, int imageWidth, int imageHeight) { public PostImage(String originalName, String thumbnailUrl, String imageUrl, String filename, String extension, int imageWidth, int imageHeight) {
this.originalName = originalName;
this.thumbnailUrl = thumbnailUrl; this.thumbnailUrl = thumbnailUrl;
this.imageUrl = imageUrl; this.imageUrl = imageUrl;
this.filename = filename + "." + extension; this.filename = filename + "." + extension;
this.extension = extension;
this.imageWidth = imageWidth; this.imageWidth = imageWidth;
this.imageHeight = imageHeight; this.imageHeight = imageHeight;

@ -2,6 +2,7 @@ package org.floens.chan.core.presenter;
import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager;
import org.floens.chan.core.model.Loadable;
import org.floens.chan.core.model.PostImage; import org.floens.chan.core.model.PostImage;
import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.core.settings.ChanSettings;
import org.floens.chan.ui.view.MultiImageView; import org.floens.chan.ui.view.MultiImageView;
@ -23,6 +24,7 @@ public class ImageViewerPresenter implements MultiImageView.Callback, ViewPager.
private List<PostImage> images; private List<PostImage> images;
private List<Float> progress; private List<Float> progress;
private int selectedPosition; private int selectedPosition;
private Loadable loadable;
// Disables swiping until the view pager is visible // Disables swiping until the view pager is visible
private boolean viewPagerVisible = false; private boolean viewPagerVisible = false;
@ -32,9 +34,10 @@ public class ImageViewerPresenter implements MultiImageView.Callback, ViewPager.
this.callback = callback; this.callback = callback;
} }
public void showImages(List<PostImage> images, int position) { public void showImages(List<PostImage> images, int position, Loadable loadable) {
this.images = images; this.images = images;
selectedPosition = position; selectedPosition = position;
this.loadable = loadable;
progress = new ArrayList<>(images.size()); progress = new ArrayList<>(images.size());
for (int i = 0; i < images.size(); i++) { for (int i = 0; i < images.size(); i++) {
@ -71,6 +74,18 @@ public class ImageViewerPresenter implements MultiImageView.Callback, ViewPager.
callback.showProgress(false); callback.showProgress(false);
} }
public List<PostImage> getAllPostImages() {
return images;
}
public PostImage getCurrentPostImage() {
return images.get(selectedPosition);
}
public Loadable getLoadable() {
return loadable;
}
@Override @Override
public void onPageSelected(int position) { public void onPageSelected(int position) {
if (!viewPagerVisible) { if (!viewPagerVisible) {

@ -153,14 +153,14 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt
for (int i = 0; i < chanLoader.getThread().posts.size(); i++) { for (int i = 0; i < chanLoader.getThread().posts.size(); i++) {
Post item = chanLoader.getThread().posts.get(i); Post item = chanLoader.getThread().posts.get(i);
if (item.hasImage) { if (item.hasImage) {
images.add(new PostImage(item.thumbnailUrl, item.imageUrl, item.filename, item.ext, item.imageWidth, item.imageHeight)); images.add(new PostImage(String.valueOf(item.tim), item.thumbnailUrl, item.imageUrl, item.filename, item.ext, item.imageWidth, item.imageHeight));
if (item.no == post.no) { if (item.no == post.no) {
index = images.size() - 1; index = images.size() - 1;
} }
} }
} }
threadPresenterCallback.showImages(images, index, thumbnail); threadPresenterCallback.showImages(images, index, chanLoader.getLoadable(), thumbnail);
} }
@Override @Override
@ -339,7 +339,7 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt
public void showPostsPopup(Post forPost, List<Post> posts); public void showPostsPopup(Post forPost, List<Post> posts);
public void showImages(List<PostImage> images, int index, ImageView thumbnail); public void showImages(List<PostImage> images, int index, Loadable loadable, ImageView thumbnail);
public void scrollTo(int position); public void scrollTo(int position);
} }

@ -13,6 +13,7 @@ import android.graphics.Point;
import android.graphics.PointF; import android.graphics.PointF;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
import android.os.Build; import android.os.Build;
import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.view.View; import android.view.View;
import android.view.Window; import android.view.Window;
@ -25,28 +26,43 @@ import com.davemorrissey.labs.subscaleview.ImageViewState;
import org.floens.chan.ChanApplication; import org.floens.chan.ChanApplication;
import org.floens.chan.R; import org.floens.chan.R;
import org.floens.chan.chan.ImageSearch;
import org.floens.chan.controller.Controller; import org.floens.chan.controller.Controller;
import org.floens.chan.core.model.PostImage; import org.floens.chan.core.model.PostImage;
import org.floens.chan.core.presenter.ImageViewerPresenter; import org.floens.chan.core.presenter.ImageViewerPresenter;
import org.floens.chan.core.settings.ChanSettings;
import org.floens.chan.ui.adapter.ImageViewerAdapter; import org.floens.chan.ui.adapter.ImageViewerAdapter;
import org.floens.chan.ui.toolbar.Toolbar; import org.floens.chan.ui.toolbar.Toolbar;
import org.floens.chan.ui.toolbar.ToolbarMenu;
import org.floens.chan.ui.toolbar.ToolbarMenuItem;
import org.floens.chan.ui.view.CustomScaleImageView; import org.floens.chan.ui.view.CustomScaleImageView;
import org.floens.chan.ui.view.FloatingMenu;
import org.floens.chan.ui.view.FloatingMenuItem;
import org.floens.chan.ui.view.LoadingBar; import org.floens.chan.ui.view.LoadingBar;
import org.floens.chan.ui.view.MultiImageView; import org.floens.chan.ui.view.MultiImageView;
import org.floens.chan.ui.view.OptionalSwipeViewPager; import org.floens.chan.ui.view.OptionalSwipeViewPager;
import org.floens.chan.ui.view.TransitionImageView; import org.floens.chan.ui.view.TransitionImageView;
import org.floens.chan.utils.AndroidUtils; import org.floens.chan.utils.AndroidUtils;
import org.floens.chan.utils.ImageSaver;
import org.floens.chan.utils.Logger; import org.floens.chan.utils.Logger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
import static org.floens.chan.utils.AndroidUtils.dp; import static org.floens.chan.utils.AndroidUtils.dp;
public class ImageViewerController extends Controller implements View.OnClickListener, ImageViewerPresenter.Callback { public class ImageViewerController extends Controller implements View.OnClickListener, ImageViewerPresenter.Callback, ToolbarMenuItem.ToolbarMenuItemCallback {
private static final String TAG = "ImageViewerController"; private static final String TAG = "ImageViewerController";
private static final int TRANSITION_DURATION = 200; private static final int TRANSITION_DURATION = 200;
private static final float TRANSITION_FINAL_ALPHA = 0.85f; private static final float TRANSITION_FINAL_ALPHA = 0.85f;
private static final int SAVE_ID = 101;
private static final int OPEN_BROWSER_ID = 102;
private static final int SHARE_ID = 103;
private static final int SEARCH_ID = 104;
private static final int SAVE_ALBUM = 105;
private int statusBarColorPrevious; private int statusBarColorPrevious;
private AnimatorSet startAnimation; private AnimatorSet startAnimation;
private AnimatorSet endAnimation; private AnimatorSet endAnimation;
@ -59,6 +75,8 @@ public class ImageViewerController extends Controller implements View.OnClickLis
private OptionalSwipeViewPager pager; private OptionalSwipeViewPager pager;
private LoadingBar loadingBar; private LoadingBar loadingBar;
private ToolbarMenuItem overflowMenuItem;
public ImageViewerController(Context context, Toolbar toolbar) { public ImageViewerController(Context context, Toolbar toolbar) {
super(context); super(context);
this.toolbar = toolbar; this.toolbar = toolbar;
@ -70,6 +88,15 @@ public class ImageViewerController extends Controller implements View.OnClickLis
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
navigationItem.menu = new ToolbarMenu(context);
overflowMenuItem = navigationItem.createOverflow(context, this, Arrays.asList(
new FloatingMenuItem(SAVE_ID, string(R.string.image_save)),
new FloatingMenuItem(OPEN_BROWSER_ID, string(R.string.action_open_browser)),
new FloatingMenuItem(SHARE_ID, string(R.string.action_share)),
new FloatingMenuItem(SEARCH_ID, string(R.string.action_search_image)),
new FloatingMenuItem(SAVE_ALBUM, string(R.string.action_download_album))
));
view = inflateRes(R.layout.controller_image_viewer); view = inflateRes(R.layout.controller_image_viewer);
view.setOnClickListener(this); view.setOnClickListener(this);
previewImage = (TransitionImageView) view.findViewById(R.id.preview_image); previewImage = (TransitionImageView) view.findViewById(R.id.preview_image);
@ -86,6 +113,67 @@ public class ImageViewerController extends Controller implements View.OnClickLis
}); });
} }
@Override
public void onMenuItemClicked(ToolbarMenuItem item) {
}
@Override
public void onSubMenuItemClicked(ToolbarMenuItem parent, FloatingMenuItem item) {
PostImage postImage = presenter.getCurrentPostImage();
switch ((Integer) item.getId()) {
case SAVE_ID:
case SHARE_ID:
if (ChanSettings.shareUrl.get()) {
AndroidUtils.shareLink(postImage.imageUrl);
} else {
ImageSaver.getInstance().saveImage(context, postImage.imageUrl,
ChanSettings.saveOriginalFilename.get() ? postImage.originalName : postImage.filename,
postImage.extension,
((Integer) item.getId()) == SHARE_ID);
}
break;
case OPEN_BROWSER_ID:
AndroidUtils.openLink(postImage.imageUrl);
break;
case SEARCH_ID:
List<FloatingMenuItem> items = new ArrayList<>();
for (ImageSearch imageSearch : ImageSearch.engines) {
items.add(new FloatingMenuItem(imageSearch.getId(), imageSearch.getName()));
}
FloatingMenu menu = new FloatingMenu(context, overflowMenuItem.getView(), items);
menu.setCallback(new FloatingMenu.FloatingMenuCallback() {
@Override
public void onFloatingMenuItemClicked(FloatingMenu menu, FloatingMenuItem item) {
for (ImageSearch imageSearch : ImageSearch.engines) {
if (((Integer) item.getId()) == imageSearch.getId()) {
AndroidUtils.openLink(imageSearch.getUrl(presenter.getCurrentPostImage().imageUrl));
break;
}
}
}
});
menu.show();
break;
case SAVE_ALBUM:
List<PostImage> all = presenter.getAllPostImages();
List<ImageSaver.DownloadPair> list = new ArrayList<>();
String folderName = presenter.getLoadable().title;
if (TextUtils.isEmpty(folderName)) {
folderName = String.valueOf(presenter.getLoadable().no);
}
String filename;
for (PostImage post : all) {
filename = (ChanSettings.saveOriginalFilename.get() ? postImage.originalName : postImage.filename) + "." + post.extension;
list.add(new ImageSaver.DownloadPair(post.imageUrl, filename));
}
ImageSaver.getInstance().saveAll(context, folderName, list);
break;
}
}
@Override @Override
public void onClick(View v) { public void onClick(View v) {
presenter.onExit(); presenter.onExit();
@ -130,7 +218,7 @@ public class ImageViewerController extends Controller implements View.OnClickLis
public void setTitle(PostImage postImage) { public void setTitle(PostImage postImage) {
navigationItem.title = postImage.filename; navigationItem.title = postImage.filename;
toolbar.setNavigationItem(false, false, navigationItem); toolbar.updateTitle(navigationItem);
} }
public void scrollTo(PostImage postImage) { public void scrollTo(PostImage postImage) {

@ -5,6 +5,7 @@ import android.widget.FrameLayout;
import org.floens.chan.R; import org.floens.chan.R;
import org.floens.chan.controller.NavigationController; import org.floens.chan.controller.NavigationController;
import org.floens.chan.core.model.Loadable;
import org.floens.chan.core.model.PostImage; import org.floens.chan.core.model.PostImage;
import org.floens.chan.ui.toolbar.Toolbar; import org.floens.chan.ui.toolbar.Toolbar;
@ -31,8 +32,8 @@ public class ImageViewerNavigationController extends NavigationController {
pushController(imageViewerController, false); pushController(imageViewerController, false);
} }
public void showImages(final List<PostImage> images, final int index, final ImageViewerController.PreviewCallback previewCallback) { public void showImages(final List<PostImage> images, final int index, final Loadable loadable, final ImageViewerController.PreviewCallback previewCallback) {
imageViewerController.setPreviewCallback(previewCallback); imageViewerController.setPreviewCallback(previewCallback);
imageViewerController.getPresenter().showImages(images, index); imageViewerController.getPresenter().showImages(images, index, loadable);
} }
} }

@ -4,6 +4,7 @@ import android.content.Context;
import android.widget.ImageView; import android.widget.ImageView;
import org.floens.chan.controller.Controller; import org.floens.chan.controller.Controller;
import org.floens.chan.core.model.Loadable;
import org.floens.chan.core.model.PostImage; import org.floens.chan.core.model.PostImage;
import org.floens.chan.ui.layout.ThreadLayout; import org.floens.chan.ui.layout.ThreadLayout;
@ -21,12 +22,12 @@ public abstract class ThreadController extends Controller implements ThreadLayou
} }
@Override @Override
public void showImages(List<PostImage> images, int index, final ImageView thumbnail) { public void showImages(List<PostImage> images, int index, Loadable loadable, final ImageView thumbnail) {
// Just ignore the showImages request when the image is not loaded // Just ignore the showImages request when the image is not loaded
if (thumbnail.getDrawable() != null && thumbnail.getDrawable().getIntrinsicWidth() > 0 && thumbnail.getDrawable().getIntrinsicHeight() > 0) { if (thumbnail.getDrawable() != null && thumbnail.getDrawable().getIntrinsicWidth() > 0 && thumbnail.getDrawable().getIntrinsicHeight() > 0) {
final ImageViewerNavigationController imageViewerNavigationController = new ImageViewerNavigationController(context); final ImageViewerNavigationController imageViewerNavigationController = new ImageViewerNavigationController(context);
presentController(imageViewerNavigationController, false); presentController(imageViewerNavigationController, false);
imageViewerNavigationController.showImages(images, index, this); imageViewerNavigationController.showImages(images, index, loadable, this);
} }
} }

@ -164,8 +164,8 @@ public class ThreadLayout extends LoadView implements ThreadPresenter.ThreadPres
} }
@Override @Override
public void showImages(List<PostImage> images, int index, ImageView thumbnail) { public void showImages(List<PostImage> images, int index, Loadable loadable, ImageView thumbnail) {
callback.showImages(images, index, thumbnail); callback.showImages(images, index, loadable, thumbnail);
} }
@Override @Override
@ -187,6 +187,6 @@ public class ThreadLayout extends LoadView implements ThreadPresenter.ThreadPres
public interface ThreadLayoutCallback { public interface ThreadLayoutCallback {
public void openThread(Loadable threadLoadable); public void openThread(Loadable threadLoadable);
public void showImages(List<PostImage> images, int index, ImageView thumbnail); public void showImages(List<PostImage> images, int index, Loadable loadable, ImageView thumbnail);
} }
} }

@ -34,10 +34,10 @@ public class NavigationItem {
public FloatingMenu middleMenu; public FloatingMenu middleMenu;
public View rightView; public View rightView;
public FloatingMenu createOverflow(Context context, ToolbarMenuItem.ToolbarMenuItemCallback callback, List<FloatingMenuItem> items) { public ToolbarMenuItem createOverflow(Context context, ToolbarMenuItem.ToolbarMenuItemCallback callback, List<FloatingMenuItem> items) {
ToolbarMenuItem overflow = menu.createOverflow(callback); ToolbarMenuItem overflow = menu.createOverflow(callback);
FloatingMenu overflowMenu = new FloatingMenu(context, overflow.getView(), items); FloatingMenu overflowMenu = new FloatingMenu(context, overflow.getView(), items);
overflow.setSubMenu(overflowMenu); overflow.setSubMenu(overflowMenu);
return overflowMenu; return overflow;
} }
} }

@ -89,6 +89,15 @@ public class Toolbar extends LinearLayout implements View.OnClickListener {
} }
} }
public void updateTitle(NavigationItem item) {
if (item.view != null) {
TextView title = (TextView) item.view.findViewById(R.id.title);
if (title != null) {
title.setText(item.title);
}
}
}
public void setCallback(ToolbarCallback callback) { public void setCallback(ToolbarCallback callback) {
this.callback = callback; this.callback = callback;
} }

Loading…
Cancel
Save