From 18870824805634ea51ae8adae0e878946804ccb9 Mon Sep 17 00:00:00 2001 From: Florens Douwes Date: Sun, 22 Jun 2014 20:06:40 +0200 Subject: [PATCH] Added grid view You can now for the board pane choose between list view and grid view. Also boards are now loaded with the mode.catalog option, there's almost no difference now between the speed of paged mode vs catalog mode. This will later on be an option. (if people complain about speed) --- .../org/floens/chan/core/ChanPreferences.java | 8 + .../org/floens/chan/core/loader/Loader.java | 2 +- .../chan/core/manager/ThreadManager.java | 21 +- .../chan/core/manager/WatchManager.java | 12 + .../org/floens/chan/ui/ScrollerRunnable.java | 5 +- .../chan/ui/activity/BoardActivity.java | 47 +++- .../floens/chan/ui/adapter/PostAdapter.java | 6 +- .../chan/ui/fragment/ReplyFragment.java | 2 +- .../chan/ui/fragment/ThreadFragment.java | 144 ++++++----- .../org/floens/chan/ui/view/PostView.java | 224 +++++++++++------- .../chan/ui/view/ThreadWatchCounterView.java | 4 +- Clover/app/src/main/res/menu/base.xml | 17 ++ Clover/app/src/main/res/values/dimens.xml | 10 +- Clover/app/src/main/res/values/strings.xml | 4 +- 14 files changed, 342 insertions(+), 164 deletions(-) diff --git a/Clover/app/src/main/java/org/floens/chan/core/ChanPreferences.java b/Clover/app/src/main/java/org/floens/chan/core/ChanPreferences.java index 724eed30..5edecc34 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/ChanPreferences.java +++ b/Clover/app/src/main/java/org/floens/chan/core/ChanPreferences.java @@ -129,4 +129,12 @@ public class ChanPreferences { public static boolean setBoardEditorFillerEnabled(boolean enabled) { return p().edit().putBoolean("preference_board_editor_filler", enabled).commit(); } + + public static String getBoardViewMode() { + return p().getString("preference_board_view_mode", "list"); + } + + public static void setBoardViewMode(String mode) { + p().edit().putString("preference_board_view_mode", mode).commit(); + } } diff --git a/Clover/app/src/main/java/org/floens/chan/core/loader/Loader.java b/Clover/app/src/main/java/org/floens/chan/core/loader/Loader.java index 2023ef86..27d8943c 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/loader/Loader.java +++ b/Clover/app/src/main/java/org/floens/chan/core/loader/Loader.java @@ -124,7 +124,7 @@ public class Loader { request.cancel(); } - if (loadable.isBoardMode()) { + if (loadable.isBoardMode() || loadable.isCatalogMode()) { loadable.no = 0; loadable.listViewIndex = 0; loadable.listViewTop = 0; diff --git a/Clover/app/src/main/java/org/floens/chan/core/manager/ThreadManager.java b/Clover/app/src/main/java/org/floens/chan/core/manager/ThreadManager.java index dce167c4..ea7a3e88 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/manager/ThreadManager.java +++ b/Clover/app/src/main/java/org/floens/chan/core/manager/ThreadManager.java @@ -63,6 +63,10 @@ import java.util.List; * etc. onDestroy, onStart and onStop must be called from the activity/fragment */ public class ThreadManager implements Loader.LoaderListener { + public static enum ViewMode { + LIST, GRID + } + private static final String TAG = "ThreadManager"; private final Activity activity; @@ -211,7 +215,7 @@ public class ThreadManager implements Loader.LoaderListener { } public void onPostClicked(Post post) { - if (loader != null && loader.getLoadable().isBoardMode()) { + if (loader != null && (loader.getLoadable().isBoardMode() || loader.getLoadable().isCatalogMode())) { threadManagerListener.onOPClicked(post); } } @@ -219,6 +223,10 @@ public class ThreadManager implements Loader.LoaderListener { public void showPostOptions(final Post post, PopupMenu popupMenu) { Menu menu = popupMenu.getMenu(); + if (loader.getLoadable().isBoardMode() || loader.getLoadable().isCatalogMode()) { + menu.add(Menu.NONE, 8, Menu.NONE, activity.getString(R.string.action_pin)); + } + String[] baseOptions = activity.getResources().getStringArray(R.array.post_options); for (int i = 0; i < baseOptions.length; i++) { menu.add(Menu.NONE, i, Menu.NONE, baseOptions[i]); @@ -266,6 +274,11 @@ public class ThreadManager implements Loader.LoaderListener { case 7: // Save reply ChanApplication.getDatabaseManager().saveReply(new SavedReply(post.board, post.no, "foo")); break; + case 8: // Pin + Pin pin = new Pin(); + pin.loadable = new Loadable(loader.getLoadable().board, post.no, WatchManager.generateTitle(post)); + ChanApplication.getWatchManager().addPin(pin); + break; } return false; } @@ -395,6 +408,10 @@ public class ThreadManager implements Loader.LoaderListener { } } + public ThreadManager.ViewMode getViewMode() { + return threadManagerListener.getViewMode(); + } + /** * Handle when a linkable has been clicked. * @@ -559,6 +576,8 @@ public class ThreadManager implements Loader.LoaderListener { public void onRefreshView(); public void onOpenThread(Loadable thread, int highlightedPost); + + public ThreadManager.ViewMode getViewMode(); } public static class RepliesPopup { diff --git a/Clover/app/src/main/java/org/floens/chan/core/manager/WatchManager.java b/Clover/app/src/main/java/org/floens/chan/core/manager/WatchManager.java index 290ae145..90dcce08 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/manager/WatchManager.java +++ b/Clover/app/src/main/java/org/floens/chan/core/manager/WatchManager.java @@ -19,11 +19,13 @@ package org.floens.chan.core.manager; import android.content.Context; import android.content.Intent; +import android.text.TextUtils; import org.floens.chan.ChanApplication; import org.floens.chan.core.ChanPreferences; import org.floens.chan.core.model.Loadable; import org.floens.chan.core.model.Pin; +import org.floens.chan.core.model.Post; import org.floens.chan.ui.service.WatchNotifier; import org.floens.chan.utils.Logger; import org.floens.chan.utils.Utils; @@ -46,6 +48,16 @@ public class WatchManager implements ChanApplication.ForegroundChangedListener { private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); private PendingTimer pendingTimer; + public static String generateTitle(Post post) { + if (!TextUtils.isEmpty(post.subject)) { + return post.subject; + } else if (!TextUtils.isEmpty(post.comment)) { + return post.comment.subSequence(0, Math.min(post.comment.length(), 100)).toString(); + } else { + return "/" + post.board + "/" + post.no; + } + } + public WatchManager(Context context) { this.context = context; diff --git a/Clover/app/src/main/java/org/floens/chan/ui/ScrollerRunnable.java b/Clover/app/src/main/java/org/floens/chan/ui/ScrollerRunnable.java index 93c082d8..d70e12c8 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/ScrollerRunnable.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/ScrollerRunnable.java @@ -19,6 +19,7 @@ package org.floens.chan.ui; import android.view.View; import android.view.ViewConfiguration; +import android.widget.AbsListView; import android.widget.ListView; public class ScrollerRunnable implements Runnable { @@ -27,7 +28,7 @@ public class ScrollerRunnable implements Runnable { private static final int MOVE_DOWN_POS = 1; private static final int MOVE_UP_POS = 2; - private final ListView mList; + private final AbsListView mList; private int mMode; private int mTargetPos; @@ -35,7 +36,7 @@ public class ScrollerRunnable implements Runnable { private int mScrollDuration; private final int mExtraScroll; - public ScrollerRunnable(ListView listView) { + public ScrollerRunnable(AbsListView listView) { mList = listView; mExtraScroll = ViewConfiguration.get(mList.getContext()).getScaledFadingEdgeLength(); } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/BoardActivity.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/BoardActivity.java index 34d8c2d9..56986910 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/activity/BoardActivity.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/activity/BoardActivity.java @@ -45,6 +45,8 @@ import org.floens.chan.ChanApplication; import org.floens.chan.R; import org.floens.chan.chan.ChanUrls; import org.floens.chan.core.ChanPreferences; +import org.floens.chan.core.manager.ThreadManager; +import org.floens.chan.core.manager.WatchManager; import org.floens.chan.core.model.Loadable; import org.floens.chan.core.model.Pin; import org.floens.chan.core.model.Post; @@ -74,6 +76,8 @@ public class BoardActivity extends BaseActivity implements AdapterView.OnItemSel threadLoadable = new Loadable(); boardFragment = ThreadFragment.newInstance(this); + setBoardFragmentViewMode(); + threadFragment = ThreadFragment.newInstance(this); FragmentTransaction ft = getFragmentManager().beginTransaction(); @@ -210,7 +214,7 @@ public class BoardActivity extends BaseActivity implements AdapterView.OnItemSel @Override public void onOPClicked(Post post) { - startLoadingThread(new Loadable(post.board, post.no, generateTitle(post))); + startLoadingThread(new Loadable(post.board, post.no, WatchManager.generateTitle(post))); } @Override @@ -221,7 +225,7 @@ public class BoardActivity extends BaseActivity implements AdapterView.OnItemSel @Override public void onThreadLoaded(Loadable loadable, List posts) { if (loadable.isThreadMode() && TextUtils.isEmpty(threadLoadable.title) && posts.size() > 0) { - threadLoadable.title = generateTitle(posts.get(0)); + threadLoadable.title = WatchManager.generateTitle(posts.get(0)); updateActionBarState(); } } @@ -344,7 +348,7 @@ public class BoardActivity extends BaseActivity implements AdapterView.OnItemSel actionBar.setTitle(""); pinDrawerListener.setDrawerIndicatorEnabled(true); - if (boardLoadable.isBoardMode()) + if (boardLoadable.isBoardMode() || boardLoadable.isCatalogMode()) setShareUrl(ChanUrls.getBoardUrlDesktop(boardLoadable.board)); } else { actionBar.setDisplayShowCustomEnabled(false); @@ -385,6 +389,14 @@ public class BoardActivity extends BaseActivity implements AdapterView.OnItemSel setMenuItemEnabled(menu.findItem(R.id.action_reply), slidable); setMenuItemEnabled(menu.findItem(R.id.action_reply_tablet), !slidable); + setMenuItemEnabled(menu.findItem(R.id.action_board_view_mode), !slidable || open); + + if (ChanPreferences.getBoardViewMode().equals("list")) { + menu.findItem(R.id.action_board_view_mode_list).setChecked(true); + } else if (ChanPreferences.getBoardViewMode().equals("grid")) { + menu.findItem(R.id.action_board_view_mode_grid).setChecked(true); + } + return super.onPrepareOptionsMenu(menu); } @@ -445,6 +457,20 @@ public class BoardActivity extends BaseActivity implements AdapterView.OnItemSel } } + return true; + case R.id.action_board_view_mode_grid: + if (!ChanPreferences.getBoardViewMode().equals("grid")) { + ChanPreferences.setBoardViewMode("grid"); + setBoardFragmentViewMode(); + startLoadingBoard(boardLoadable); + } + return true; + case R.id.action_board_view_mode_list: + if (!ChanPreferences.getBoardViewMode().equals("list")) { + ChanPreferences.setBoardViewMode("list"); + setBoardFragmentViewMode(); + startLoadingBoard(boardLoadable); + } return true; case android.R.id.home: threadPane.openPane(); @@ -472,6 +498,9 @@ public class BoardActivity extends BaseActivity implements AdapterView.OnItemSel boardLoadable = loadable; + // TODO: make this an option + boardLoadable.mode = Loadable.Mode.CATALOG; + boardFragment.bindLoadable(loadable); boardFragment.requestData(); @@ -553,13 +582,11 @@ public class BoardActivity extends BaseActivity implements AdapterView.OnItemSel }).setCancelable(false).create().show(); } - private String generateTitle(Post post) { - if (!TextUtils.isEmpty(post.subject)) { - return post.subject; - } else if (!TextUtils.isEmpty(post.comment)) { - return post.comment.subSequence(0, Math.min(post.comment.length(), 100)).toString(); - } else { - return "/" + post.board + "/" + post.no; + private void setBoardFragmentViewMode() { + if (ChanPreferences.getBoardViewMode().equals("list")) { + boardFragment.setViewMode(ThreadManager.ViewMode.LIST); + } else if (ChanPreferences.getBoardViewMode().equals("grid")) { + boardFragment.setViewMode(ThreadManager.ViewMode.GRID); } } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/adapter/PostAdapter.java b/Clover/app/src/main/java/org/floens/chan/ui/adapter/PostAdapter.java index 7b9003d0..a6ca0e5f 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/adapter/PostAdapter.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/adapter/PostAdapter.java @@ -21,8 +21,8 @@ import android.content.Context; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; +import android.widget.AbsListView; import android.widget.BaseAdapter; -import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; @@ -41,14 +41,14 @@ import java.util.List; public class PostAdapter extends BaseAdapter { private final Context context; private final ThreadManager threadManager; - private final ListView listView; + private final AbsListView listView; private boolean endOfLine; private final List postList = new ArrayList<>(); private int lastPostCount = 0; private long lastViewedTime = 0; private String loadMessage = null; - public PostAdapter(Context activity, ThreadManager threadManager, ListView listView) { + public PostAdapter(Context activity, ThreadManager threadManager, AbsListView listView) { context = activity; this.threadManager = threadManager; this.listView = listView; diff --git a/Clover/app/src/main/java/org/floens/chan/ui/fragment/ReplyFragment.java b/Clover/app/src/main/java/org/floens/chan/ui/fragment/ReplyFragment.java index ae6826ac..5e336b5e 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/fragment/ReplyFragment.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/fragment/ReplyFragment.java @@ -477,7 +477,7 @@ public class ReplyFragment extends DialogFragment { } } - draft.resto = loadable.isBoardMode() ? -1 : loadable.no; + draft.resto = loadable.isThreadMode() ? loadable.no : -1; draft.board = loadable.board; if (ChanPreferences.getPassEnabled()) { diff --git a/Clover/app/src/main/java/org/floens/chan/ui/fragment/ThreadFragment.java b/Clover/app/src/main/java/org/floens/chan/ui/fragment/ThreadFragment.java index 289e5338..6edae5c6 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/fragment/ThreadFragment.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/fragment/ThreadFragment.java @@ -26,6 +26,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.AbsListView.OnScrollListener; +import android.widget.GridView; import android.widget.ImageView; import android.widget.ListView; import android.widget.RelativeLayout; @@ -56,10 +57,11 @@ public class ThreadFragment extends Fragment implements ThreadManager.ThreadMana private PostAdapter postAdapter; private LoadView container; - private ListView listView; + private AbsListView listView; private ImageView skip; private SkipLogic skipLogic; private int highlightedPost = -1; + private ThreadManager.ViewMode viewMode = ThreadManager.ViewMode.LIST; public static ThreadFragment newInstance(BaseActivity activity) { ThreadFragment fragment = new ThreadFragment(); @@ -100,6 +102,10 @@ public class ThreadFragment extends Fragment implements ThreadManager.ThreadMana return threadManager.hasLoader(); } + public void setViewMode(ThreadManager.ViewMode viewMode) { + this.viewMode = viewMode; + } + @Override public void onDestroy() { super.onDestroy(); @@ -136,16 +142,68 @@ public class ThreadFragment extends Fragment implements ThreadManager.ThreadMana } @Override - public void onThreadLoaded(List posts, boolean append) { + public void onOPClicked(Post post) { + baseActivity.onOPClicked(post); + } + + @Override + public void onThumbnailClicked(Post source) { + if (postAdapter != null) { + ImageViewActivity.setAdapter(postAdapter, source.no); + + Intent intent = new Intent(baseActivity, ImageViewActivity.class); + baseActivity.startActivity(intent); + baseActivity.overridePendingTransition(R.anim.fade_in, R.anim.fade_out); + } + } + + @Override + public void onScrollTo(int post) { + if (postAdapter != null) { + postAdapter.scrollToPost(post); + } + } + + @Override + public void onRefreshView() { + if (postAdapter != null) { + postAdapter.notifyDataSetChanged(); + } + } + + @Override + public void onOpenThread(final Loadable thread, int highlightedPost) { + baseActivity.onOpenThread(thread); + this.highlightedPost = highlightedPost; + } + + @Override + public ThreadManager.ViewMode getViewMode() { + return viewMode; + } + + @Override + public void onThreadLoaded(List posts, boolean append) { if (postAdapter == null) { RelativeLayout compound = new RelativeLayout(baseActivity); - listView = new ListView(baseActivity); - - postAdapter = new PostAdapter(baseActivity, threadManager, listView); - listView.setLayoutParams(Utils.MATCH_PARAMS); - listView.setAdapter(postAdapter); - listView.setSelectionFromTop(loadable.listViewIndex, loadable.listViewTop); + if (viewMode == ThreadManager.ViewMode.LIST) { + ListView list = new ListView(baseActivity); + listView = list; + postAdapter = new PostAdapter(baseActivity, threadManager, listView); + listView.setAdapter(postAdapter); + list.setSelectionFromTop(loadable.listViewIndex, loadable.listViewTop); + } else if (viewMode == ThreadManager.ViewMode.GRID) { + GridView grid = new GridView(baseActivity); + grid.setNumColumns(GridView.AUTO_FIT); + grid.setColumnWidth(baseActivity.getResources().getDimensionPixelSize(R.dimen.post_grid_width)); + grid.setVerticalSpacing(baseActivity.getResources().getDimensionPixelSize(R.dimen.post_grid_spacing)); + grid.setHorizontalSpacing(baseActivity.getResources().getDimensionPixelSize(R.dimen.post_grid_spacing)); + listView = grid; + postAdapter = new PostAdapter(baseActivity, threadManager, listView); + listView.setAdapter(postAdapter); + listView.setSelection(loadable.listViewIndex); + } listView.setOnScrollListener(new OnScrollListener() { @Override @@ -168,7 +226,7 @@ public class ThreadFragment extends Fragment implements ThreadManager.ThreadMana } }); - compound.addView(listView); + compound.addView(listView, Utils.MATCH_PARAMS); if (loadable.isThreadMode()) { skip = new ImageView(baseActivity); @@ -207,22 +265,6 @@ public class ThreadFragment extends Fragment implements ThreadManager.ThreadMana baseActivity.onThreadLoaded(loadable, posts); } - private void setEmpty() { - postAdapter = null; - - if (container != null) { - container.setView(null); - } - - if (listView != null) { - listView.setOnScrollListener(null); - listView = null; - } - - skip = null; - skipLogic = null; - } - @Override public void onThreadLoadError(VolleyError error) { if (error instanceof EndOfLineException) { @@ -240,6 +282,22 @@ public class ThreadFragment extends Fragment implements ThreadManager.ThreadMana highlightedPost = -1; } + private void setEmpty() { + postAdapter = null; + + if (container != null) { + container.setView(null); + } + + if (listView != null) { + listView.setOnScrollListener(null); + listView = null; + } + + skip = null; + skipLogic = null; + } + /** * Returns an TextView containing the appropriate error message * @@ -272,42 +330,6 @@ public class ThreadFragment extends Fragment implements ThreadManager.ThreadMana return errorMessage; } - @Override - public void onOPClicked(Post post) { - baseActivity.onOPClicked(post); - } - - @Override - public void onThumbnailClicked(Post source) { - if (postAdapter != null) { - ImageViewActivity.setAdapter(postAdapter, source.no); - - Intent intent = new Intent(baseActivity, ImageViewActivity.class); - baseActivity.startActivity(intent); - baseActivity.overridePendingTransition(R.anim.fade_in, R.anim.fade_out); - } - } - - @Override - public void onScrollTo(int post) { - if (postAdapter != null) { - postAdapter.scrollToPost(post); - } - } - - @Override - public void onRefreshView() { - if (postAdapter != null) { - postAdapter.notifyDataSetChanged(); - } - } - - @Override - public void onOpenThread(final Loadable thread, int highlightedPost) { - baseActivity.onOpenThread(thread); - this.highlightedPost = highlightedPost; - } - private static class SkipLogic { private final ImageView skip; private int lastFirstVisibleItem; diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/PostView.java b/Clover/app/src/main/java/org/floens/chan/ui/view/PostView.java index a3839809..d8436d8c 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/view/PostView.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/view/PostView.java @@ -34,6 +34,7 @@ import android.text.style.ClickableSpan; import android.text.style.ForegroundColorSpan; import android.text.style.UnderlineSpan; import android.util.AttributeSet; +import android.util.TypedValue; import android.view.MotionEvent; import android.view.View; import android.widget.ImageView; @@ -72,12 +73,12 @@ public class PostView extends LinearLayout implements View.OnClickListener { private boolean isBuild = false; private LinearLayout full; - private LinearLayout right; + private LinearLayout contentContainer; private CustomNetworkImageView imageView; private TextView titleView; private TextView commentView; private TextView repliesCountView; - private LinearLayout iconView; + private LinearLayout iconsView; private ImageView stickyView; private ImageView closedView; private NetworkImageView countryView; @@ -126,6 +127,7 @@ public class PostView extends LinearLayout implements View.OnClickListener { public void setPost(final Post post, final ThreadManager manager) { this.post = post; this.manager = manager; + boolean boardCatalogMode = manager.getLoadable().isBoardMode() || manager.getLoadable().isCatalogMode(); post.setLinkableListener(null); @@ -147,34 +149,45 @@ public class PostView extends LinearLayout implements View.OnClickListener { CharSequence total = new SpannableString(""); if (post.subjectSpan != null) { - total = TextUtils.concat(total, post.subjectSpan, "\n"); + total = TextUtils.concat(total, post.subjectSpan); } - if (post.nameSpan != null) { - total = TextUtils.concat(total, post.nameSpan, " "); - } + if (isList()) { + if (post.subjectSpan != null) { + total = TextUtils.concat(total, "\n"); + } - if (post.tripcodeSpan != null) { - total = TextUtils.concat(total, post.tripcodeSpan, " "); - } + if (post.nameSpan != null) { + total = TextUtils.concat(total, post.nameSpan, " "); + } - if (post.idSpan != null) { - total = TextUtils.concat(total, post.idSpan, " "); - } + if (post.tripcodeSpan != null) { + total = TextUtils.concat(total, post.tripcodeSpan, " "); + } - if (post.capcodeSpan != null) { - total = TextUtils.concat(total, post.capcodeSpan, " "); - } + if (post.idSpan != null) { + total = TextUtils.concat(total, post.idSpan, " "); + } - CharSequence relativeTime = DateUtils.getRelativeTimeSpanString(post.time * 1000L, Time.get(), - DateUtils.SECOND_IN_MILLIS, 0); + if (post.capcodeSpan != null) { + total = TextUtils.concat(total, post.capcodeSpan, " "); + } - SpannableString date = new SpannableString("No." + post.no + " " + relativeTime); - date.setSpan(new ForegroundColorSpan(dateColor), 0, date.length(), 0); - date.setSpan(new AbsoluteSizeSpan(10, true), 0, date.length(), 0); - total = TextUtils.concat(total, date, " "); + CharSequence relativeTime = DateUtils.getRelativeTimeSpanString(post.time * 1000L, Time.get(), + DateUtils.SECOND_IN_MILLIS, 0); - titleView.setText(total); + SpannableString date = new SpannableString("No." + post.no + " " + relativeTime); + date.setSpan(new ForegroundColorSpan(dateColor), 0, date.length(), 0); + date.setSpan(new AbsoluteSizeSpan(10, true), 0, date.length(), 0); + total = TextUtils.concat(total, date, " "); + } + + if (!TextUtils.isEmpty(total)) { + titleView.setText(total); + titleView.setVisibility(View.VISIBLE); + } else { + titleView.setVisibility(View.GONE); + } if (!TextUtils.isEmpty(post.comment)) { commentView.setVisibility(View.VISIBLE); @@ -189,36 +202,28 @@ public class PostView extends LinearLayout implements View.OnClickListener { if (manager.getLoadable().isThreadMode()) { post.setLinkableListener(this); } - - if (manager.getLoadable().isBoardMode()) { - int maxHeight = context.getResources().getDimensionPixelSize(R.dimen.post_max_height); - commentView.setMaxHeight(maxHeight); - } else { - commentView.setMaxHeight(10000); - } } else { commentView.setVisibility(View.GONE); commentView.setText(""); commentView.setOnClickListener(null); - commentView.setOnLongClickListener(null); post.setLinkableListener(null); } - if ((post.isOP && manager.getLoadable().isBoardMode() && post.replies > 0) || (post.repliesFrom.size() > 0)) { + if (isGrid() || ((post.isOP && boardCatalogMode && post.replies > 0) || (post.repliesFrom.size() > 0))) { repliesCountView.setVisibility(View.VISIBLE); String text = ""; - int count = manager.getLoadable().isBoardMode() ? post.replies : post.repliesFrom.size(); + int count = boardCatalogMode ? post.replies : post.repliesFrom.size(); - if (count > 1) { + if (count != 1) { text = count + " " + context.getString(R.string.multiple_replies); } else if (count == 1) { text = count + " " + context.getString(R.string.one_reply); } - if (manager.getLoadable().isBoardMode() && post.images > 0) { - if (post.images > 1) { + if (boardCatalogMode && post.images > 0) { + if (post.images != 1) { text += ", " + post.images + " " + context.getString(R.string.multiple_images); } else { text += ", " + post.images + " " + context.getString(R.string.one_image); @@ -240,11 +245,11 @@ public class PostView extends LinearLayout implements View.OnClickListener { repliesCountView.setOnClickListener(null); } - boolean showCountryFlag = !TextUtils.isEmpty(post.country); - boolean showStickyIcon = post.sticky; - boolean showClosedIcon = post.closed; + boolean showCountryFlag = isList() && !TextUtils.isEmpty(post.country); + boolean showStickyIcon = isList() && post.sticky; + boolean showClosedIcon = isList() && post.closed; - iconView.setVisibility((showCountryFlag || showStickyIcon || showClosedIcon) ? View.VISIBLE : View.GONE); + iconsView.setVisibility((showCountryFlag || showStickyIcon || showClosedIcon) ? View.VISIBLE : View.GONE); stickyView.setVisibility(showStickyIcon ? View.VISIBLE : View.GONE); closedView.setVisibility(showClosedIcon ? View.VISIBLE : View.GONE); @@ -269,10 +274,6 @@ public class PostView extends LinearLayout implements View.OnClickListener { } else { lastSeen.setVisibility(View.GONE); } - - if (manager.getLoadable().isBoardMode()) { - Utils.setPressedDrawable(right); - } } private void init() { @@ -341,19 +342,47 @@ public class PostView extends LinearLayout implements View.OnClickListener { isBuild = true; Resources resources = context.getResources(); - int postPadding = resources.getDimensionPixelSize(R.dimen.post_padding); - int commentPadding = resources.getDimensionPixelSize(R.dimen.post_comment_padding); + int postPadding = 0; + if (isList()) { + postPadding = resources.getDimensionPixelSize(R.dimen.post_padding); + } else if (isGrid()) { + postPadding = resources.getDimensionPixelSize(R.dimen.post_padding_grid); + } + int commentPadding = 0; + if (isList()) { + commentPadding = resources.getDimensionPixelSize(R.dimen.post_comment_padding); + } else if (isGrid()) { + commentPadding = resources.getDimensionPixelSize(R.dimen.post_comment_padding_grid); + } int iconPadding = resources.getDimensionPixelSize(R.dimen.post_icon_padding); int iconWidth = resources.getDimensionPixelSize(R.dimen.post_icon_width); int iconHeight = resources.getDimensionPixelSize(R.dimen.post_icon_height); int imageSize = resources.getDimensionPixelSize(R.dimen.thumbnail_size); + int gridHeight = resources.getDimensionPixelSize(R.dimen.post_grid_height); + int gridImageHeight = resources.getDimensionPixelSize(R.dimen.post_grid_image_height); + + int postCommentSize = 0; + if (isList()) { + postCommentSize = resources.getDimensionPixelSize(R.dimen.post_comment_text); + } else if (isGrid()) { + postCommentSize = resources.getDimensionPixelSize(R.dimen.post_comment_text_grid); + } RelativeLayout wrapper = new RelativeLayout(context); wrapper.setLayoutParams(matchParams); full = new LinearLayout(context); - full.setOrientation(HORIZONTAL); - wrapper.addView(full, matchParams); + if (isList()) { + full.setOrientation(HORIZONTAL); + wrapper.addView(full, matchParams); + } else if (isGrid()) { + full.setOrientation(VERTICAL); + wrapper.addView(full, new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, gridHeight)); + } + + LinearLayout imageContainer = new LinearLayout(context); + imageContainer.setOrientation(VERTICAL); + imageContainer.setBackgroundColor(thumbnailBackground); // Create thumbnail imageView = new CustomNetworkImageView(context); @@ -367,70 +396,97 @@ public class PostView extends LinearLayout implements View.OnClickListener { } }); - LinearLayout left = new LinearLayout(context); - left.setOrientation(VERTICAL); - left.setBackgroundColor(thumbnailBackground); - - left.addView(imageView, new LinearLayout.LayoutParams(imageSize, imageSize)); + if (isList()) { + imageContainer.addView(imageView, new LinearLayout.LayoutParams(imageSize, imageSize)); + full.addView(imageContainer, wrapMatchParams); + full.setMinimumHeight(imageSize); + } else if (isGrid()) { + imageContainer.addView(imageView, new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, gridImageHeight)); + full.addView(imageContainer, matchWrapParams); + } - full.addView(left, wrapMatchParams); - full.setMinimumHeight(imageSize); + contentContainer = new LinearLayout(context); + contentContainer.setOrientation(VERTICAL); - right = new LinearLayout(context); - right.setOrientation(VERTICAL); + LinearLayout titleContainer = new LinearLayout(context); + titleContainer.setOrientation(HORIZONTAL); - LinearLayout header = new LinearLayout(context); - header.setOrientation(HORIZONTAL); - // 25 padding to give optionsView some space - header.setPadding(0, 0, Utils.dp(25), 0); + if (isList()) { + // 25 padding to give optionsView some space + titleContainer.setPadding(0, 0, Utils.dp(25), 0); + } titleView = new TextView(context); titleView.setTextSize(14); titleView.setPadding(postPadding, postPadding, postPadding, 0); - header.addView(titleView, wrapParams); - right.addView(header, matchWrapParams); + titleContainer.addView(titleView, wrapParams); + + contentContainer.addView(titleContainer, matchWrapParams); - iconView = new LinearLayout(context); - iconView.setOrientation(HORIZONTAL); - iconView.setPadding(postPadding, iconPadding, postPadding, 0); + iconsView = new LinearLayout(context); + iconsView.setOrientation(HORIZONTAL); + iconsView.setPadding(postPadding, iconPadding, postPadding, 0); stickyView = new ImageView(context); stickyView.setImageBitmap(IconCache.stickyIcon); - iconView.addView(stickyView, new LinearLayout.LayoutParams(iconWidth, iconHeight)); + iconsView.addView(stickyView, new LinearLayout.LayoutParams(iconWidth, iconHeight)); closedView = new ImageView(context); closedView.setImageBitmap(IconCache.closedIcon); - iconView.addView(closedView, new LinearLayout.LayoutParams(iconWidth, iconHeight)); + iconsView.addView(closedView, new LinearLayout.LayoutParams(iconWidth, iconHeight)); countryView = new NetworkImageView(context); countryView.setScaleType(ImageView.ScaleType.FIT_CENTER); - iconView.addView(countryView, new LinearLayout.LayoutParams(iconWidth, iconHeight)); + iconsView.addView(countryView, new LinearLayout.LayoutParams(iconWidth, iconHeight)); - right.addView(iconView, matchWrapParams); + contentContainer.addView(iconsView, matchWrapParams); commentView = new TextView(context); - commentView.setTextSize(15); - commentView.setPadding(postPadding, commentPadding, postPadding, commentPadding); - right.addView(commentView, matchWrapParams); + commentView.setTextSize(TypedValue.COMPLEX_UNIT_PX, postCommentSize); - repliesCountView = new TextView(context); + if (isList()) { + commentView.setPadding(postPadding, commentPadding, postPadding, commentPadding); - // Set the drawable before the padding, because setting the background resets the padding - // This behavior differs with 4.4 / 4.1 - Utils.setPressedDrawable(repliesCountView); + if (manager.getLoadable().isBoardMode() || manager.getLoadable().isCatalogMode()) { + int maxHeight = context.getResources().getDimensionPixelSize(R.dimen.post_max_height); + commentView.setMaxHeight(maxHeight); + } + } else if (isGrid()) { + commentView.setPadding(postPadding, commentPadding, postPadding, 0); + // So that is fills up all the height using weight later on + commentView.setMinHeight(10000); + commentView.setEllipsize(TextUtils.TruncateAt.END); + } + if (isList()) { + contentContainer.addView(commentView, matchWrapParams); + } else if (isGrid()) { + contentContainer.addView(commentView, new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, 0, 1f)); + } + + repliesCountView = new TextView(context); + Utils.setPressedDrawable(repliesCountView); repliesCountView.setTextColor(replyCountColor); repliesCountView.setPadding(postPadding, postPadding, postPadding, postPadding); - repliesCountView.setTextSize(14); + if (isList()) { + repliesCountView.setTextSize(14); + } else if (isGrid()) { + repliesCountView.setTextSize(11); + } + repliesCountView.setSingleLine(); - right.addView(repliesCountView, wrapParams); + contentContainer.addView(repliesCountView, wrapParams); lastSeen = new View(context); lastSeen.setBackgroundColor(0xffff0000); - right.addView(lastSeen, new LayoutParams(LayoutParams.MATCH_PARENT, Utils.dp(6f))); + contentContainer.addView(lastSeen, new LayoutParams(LayoutParams.MATCH_PARENT, Utils.dp(6f))); - full.addView(right, matchWrapParams); + if (!manager.getLoadable().isThreadMode()) { + Utils.setPressedDrawable(contentContainer); + } + + full.addView(contentContainer, matchWrapParams); optionsView = new ImageView(context); optionsView.setImageResource(R.drawable.ic_overflow); @@ -478,6 +534,14 @@ public class PostView extends LinearLayout implements View.OnClickListener { manager.onPostClicked(post); } + private boolean isList() { + return manager.getViewMode() == ThreadManager.ViewMode.LIST; + } + + private boolean isGrid() { + return manager.getViewMode() == ThreadManager.ViewMode.GRID; + } + private class PostViewMovementMethod extends LinkMovementMethod { @Override public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) { diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/ThreadWatchCounterView.java b/Clover/app/src/main/java/org/floens/chan/ui/view/ThreadWatchCounterView.java index 2cc776db..1481ff81 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/view/ThreadWatchCounterView.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/view/ThreadWatchCounterView.java @@ -21,7 +21,7 @@ import android.content.Context; import android.os.Handler; import android.util.AttributeSet; import android.view.View; -import android.widget.ListView; +import android.widget.AbsListView; import android.widget.TextView; import org.floens.chan.core.loader.Loader; @@ -45,7 +45,7 @@ public class ThreadWatchCounterView extends TextView implements View.OnClickList super(activity, attbs, style); } - public void init(final ThreadManager threadManager, final ListView listView, final PostAdapter adapter) { + public void init(final ThreadManager threadManager, final AbsListView listView, final PostAdapter adapter) { tm = threadManager; ad = adapter; diff --git a/Clover/app/src/main/res/menu/base.xml b/Clover/app/src/main/res/menu/base.xml index 1ccf0d60..a51d47c5 100644 --- a/Clover/app/src/main/res/menu/base.xml +++ b/Clover/app/src/main/res/menu/base.xml @@ -91,6 +91,23 @@ along with this program. If not, see . android:showAsAction="never" android:title="@string/action_open_browser"/> + + + + + + + + + . 12dp 10dp + 5dp 11dp + 8dp 6dp - 70dp 24dp 14dp 200dp - + 110dp + 300dp + 120dp + 15sp + 14sp + 1dp 8dp diff --git a/Clover/app/src/main/res/values/strings.xml b/Clover/app/src/main/res/values/strings.xml index 4520d1fb..38a7b86a 100644 --- a/Clover/app/src/main/res/values/strings.xml +++ b/Clover/app/src/main/res/values/strings.xml @@ -35,9 +35,11 @@ along with this program. If not, see . Reply to board Reply to thread Open in browser - Open catalog Share Download album + View mode + List + Grid Unsupported link Clover can\'t open this link. Opening it in your browser instead.