Made pins clickable and highlight when open

filtering
Floens 10 years ago
parent e3519915b2
commit ad02acaefe
  1. 29
      Clover/app/src/main/java/org/floens/chan/ChanApplication.java
  2. 8
      Clover/app/src/main/java/org/floens/chan/controller/NavigationController.java
  3. 6
      Clover/app/src/main/java/org/floens/chan/core/loader/LoaderPool.java
  4. 47
      Clover/app/src/main/java/org/floens/chan/core/manager/WatchManager.java
  5. 13
      Clover/app/src/main/java/org/floens/chan/core/model/Pin.java
  6. 5
      Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java
  7. 14
      Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java
  8. 7
      Clover/app/src/main/java/org/floens/chan/core/watch/PinWatcher.java
  9. 17
      Clover/app/src/main/java/org/floens/chan/ui/activity/BaseActivity.java
  10. 111
      Clover/app/src/main/java/org/floens/chan/ui/activity/BoardActivity.java
  11. 106
      Clover/app/src/main/java/org/floens/chan/ui/activity/StartActivity.java
  12. 125
      Clover/app/src/main/java/org/floens/chan/ui/adapter/PinAdapter.java
  13. 2
      Clover/app/src/main/java/org/floens/chan/ui/adapter/PinnedAdapter.java
  14. 13
      Clover/app/src/main/java/org/floens/chan/ui/controller/BrowseController.java
  15. 2
      Clover/app/src/main/java/org/floens/chan/ui/controller/ImageViewerController.java
  16. 37
      Clover/app/src/main/java/org/floens/chan/ui/controller/RootNavigationController.java
  17. 4
      Clover/app/src/main/java/org/floens/chan/ui/controller/ThreadController.java
  18. 54
      Clover/app/src/main/java/org/floens/chan/ui/controller/ViewThreadController.java
  19. 3
      Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java
  20. 14
      Clover/app/src/main/java/org/floens/chan/ui/toolbar/NavigationItem.java
  21. 13
      Clover/app/src/main/java/org/floens/chan/ui/toolbar/Toolbar.java
  22. 4
      Clover/app/src/main/java/org/floens/chan/ui/toolbar/ToolbarMenuItem.java
  23. 11
      Clover/app/src/main/java/org/floens/chan/utils/AndroidUtils.java
  24. 2
      Clover/app/src/main/res/layout/cell_header.xml
  25. 15
      Clover/app/src/main/res/layout/cell_pin.xml

@ -40,8 +40,8 @@ import org.floens.chan.utils.Logger;
import java.io.File; import java.io.File;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List; import de.greenrobot.event.EventBus;
public class ChanApplication extends Application { public class ChanApplication extends Application {
private static final String TAG = "ChanApplication"; private static final String TAG = "ChanApplication";
@ -62,7 +62,6 @@ public class ChanApplication extends Application {
private static DatabaseManager databaseManager; private static DatabaseManager databaseManager;
private static FileCache fileCache; private static FileCache fileCache;
private List<ForegroundChangedListener> foregroundChangedListeners = new ArrayList<>();
private int activityForegroundCounter = 0; private int activityForegroundCounter = 0;
public ChanApplication() { public ChanApplication() {
@ -152,9 +151,7 @@ public class ChanApplication extends Application {
activityForegroundCounter++; activityForegroundCounter++;
if (getApplicationInForeground() != lastForeground) { if (getApplicationInForeground() != lastForeground) {
for (ForegroundChangedListener listener : foregroundChangedListeners) { EventBus.getDefault().post(new ForegroundChangedMessage(getApplicationInForeground()));
listener.onForegroundChanged(getApplicationInForeground());
}
} }
} }
@ -167,9 +164,7 @@ public class ChanApplication extends Application {
} }
if (getApplicationInForeground() != lastForeground) { if (getApplicationInForeground() != lastForeground) {
for (ForegroundChangedListener listener : foregroundChangedListeners) { EventBus.getDefault().post(new ForegroundChangedMessage(getApplicationInForeground()));
listener.onForegroundChanged(getApplicationInForeground());
}
} }
} }
@ -177,14 +172,6 @@ public class ChanApplication extends Application {
return activityForegroundCounter > 0; return activityForegroundCounter > 0;
} }
public void addForegroundChangedListener(ForegroundChangedListener listener) {
foregroundChangedListeners.add(listener);
}
public void removeForegroundChangedListener(ForegroundChangedListener listener) {
foregroundChangedListeners.remove(listener);
}
private void cleanupOutdated() { private void cleanupOutdated() {
File ionCacheFolder = new File(getCacheDir() + "/ion"); File ionCacheFolder = new File(getCacheDir() + "/ion");
if (ionCacheFolder.exists() && ionCacheFolder.isDirectory()) { if (ionCacheFolder.exists() && ionCacheFolder.isDirectory()) {
@ -202,7 +189,11 @@ public class ChanApplication extends Application {
} }
} }
public interface ForegroundChangedListener { public static class ForegroundChangedMessage {
void onForegroundChanged(boolean foreground); public boolean inForeground;
public ForegroundChangedMessage(boolean inForeground) {
this.inForeground = inForeground;
}
} }
} }

@ -137,6 +137,14 @@ public abstract class NavigationController extends Controller implements Control
protected void controllerPopped(Controller controller) { protected void controllerPopped(Controller controller) {
} }
public Controller getTop() {
if (controllerList.size() > 0) {
return controllerList.get(controllerList.size() - 1);
} else {
return null;
}
}
@Override @Override
public void onControllerTransitionCompleted(ControllerTransition transition) { public void onControllerTransitionCompleted(ControllerTransition transition) {
ControllerLogic.finishTransition(transition); ControllerLogic.finishTransition(transition);

@ -25,15 +25,11 @@ import java.util.Map;
public class LoaderPool { public class LoaderPool {
// private static final String TAG = "LoaderPool"; // private static final String TAG = "LoaderPool";
private static LoaderPool instance; private static LoaderPool instance = new LoaderPool();
private static Map<Loadable, ChanLoader> loaders = new HashMap<>(); private static Map<Loadable, ChanLoader> loaders = new HashMap<>();
public static LoaderPool getInstance() { public static LoaderPool getInstance() {
if (instance == null) {
instance = new LoaderPool();
}
return instance; return instance;
} }

@ -39,12 +39,11 @@ import java.util.concurrent.TimeUnit;
import de.greenrobot.event.EventBus; import de.greenrobot.event.EventBus;
public class WatchManager implements ChanApplication.ForegroundChangedListener { public class WatchManager {
private static final String TAG = "WatchManager"; private static final String TAG = "WatchManager";
private static final int FOREGROUND_TIME = 5; private static final int FOREGROUND_TIME = 5;
private final Context context; private final Context context;
private final List<PinListener> listeners = new ArrayList<>();
private final List<Pin> pins; private final List<Pin> pins;
private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); private ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
private PendingTimer pendingTimer; private PendingTimer pendingTimer;
@ -54,7 +53,7 @@ public class WatchManager implements ChanApplication.ForegroundChangedListener {
pins = ChanApplication.getDatabaseManager().getPinned(); pins = ChanApplication.getDatabaseManager().getPinned();
ChanApplication.getInstance().addForegroundChangedListener(this); EventBus.getDefault().register(this);
updateTimerState(true); updateTimerState(true);
updateNotificationServiceState(); updateNotificationServiceState();
@ -189,19 +188,20 @@ public class WatchManager implements ChanApplication.ForegroundChangedListener {
ChanApplication.getDatabaseManager().updatePins(pins); ChanApplication.getDatabaseManager().updatePins(pins);
} }
public void addPinListener(PinListener l) { public void toggleWatch(Pin pin) {
listeners.add(l); pin.watching = !pin.watching;
}
public void removePinListener(PinListener l) { EventBus.getDefault().post(new PinChangedMessage(pin));
listeners.remove(l); ChanApplication.getWatchManager().onPinsChanged();
ChanApplication.getWatchManager().invokeLoadNow();
} }
public void onPinsChanged() { public void pinWatcherUpdated(Pin pin) {
for (PinListener l : listeners) { EventBus.getDefault().post(new PinChangedMessage(pin));
l.onPinsChanged(); onPinsChanged();
} }
public void onPinsChanged() {
updateTimerState(false); updateTimerState(false);
updateNotificationServiceState(); updateNotificationServiceState();
updatePinWatchers(); updatePinWatchers();
@ -231,21 +231,26 @@ public class WatchManager implements ChanApplication.ForegroundChangedListener {
} }
} }
public void onEvent(ChanApplication.ForegroundChangedMessage message) {
updateNotificationServiceState();
updateTimerState(true);
}
public void onWatchEnabledChanged(boolean watchEnabled) { public void onWatchEnabledChanged(boolean watchEnabled) {
updateNotificationServiceState(watchEnabled, getWatchBackgroundEnabled()); updateNotificationServiceState(watchEnabled, getWatchBackgroundEnabled());
updateTimerState(watchEnabled, getWatchBackgroundEnabled(), false); updateTimerState(watchEnabled, getWatchBackgroundEnabled(), false);
updatePinWatchers(watchEnabled); updatePinWatchers(watchEnabled);
for (Pin pin : getPins()) {
EventBus.getDefault().post(new PinChangedMessage(pin));
}
} }
public void onBackgroundWatchingChanged(boolean backgroundEnabled) { public void onBackgroundWatchingChanged(boolean backgroundEnabled) {
updateNotificationServiceState(getTimerEnabled(), backgroundEnabled); updateNotificationServiceState(getTimerEnabled(), backgroundEnabled);
updateTimerState(getTimerEnabled(), backgroundEnabled, false); updateTimerState(getTimerEnabled(), backgroundEnabled, false);
for (Pin pin : getPins()) {
EventBus.getDefault().post(new PinChangedMessage(pin));
} }
@Override
public void onForegroundChanged(final boolean foreground) {
updateNotificationServiceState();
updateTimerState(true);
} }
private boolean getTimerEnabled() { private boolean getTimerEnabled() {
@ -294,7 +299,7 @@ public class WatchManager implements ChanApplication.ForegroundChangedListener {
setTimer(invokeLoadNow ? 1 : FOREGROUND_TIME); setTimer(invokeLoadNow ? 1 : FOREGROUND_TIME);
} else { } else {
if (backgroundEnabled) { if (backgroundEnabled) {
setTimer(ChanSettings.getWatchBackgroundTimeout()); setTimer(Integer.parseInt(ChanSettings.watchBackgroundTimeout.get()));
} else { } else {
if (pendingTimer != null) { if (pendingTimer != null) {
pendingTimer.cancel(); pendingTimer.cancel();
@ -343,14 +348,12 @@ public class WatchManager implements ChanApplication.ForegroundChangedListener {
pendingTimer = null; pendingTimer = null;
for (Pin pin : getWatchingPins()) { for (Pin pin : getWatchingPins()) {
pin.update(); if (pin.update()) {
EventBus.getDefault().post(new PinChangedMessage(pin));
} }
updateTimerState(false);
} }
public interface PinListener { updateTimerState(false);
void onPinsChanged();
} }
public static class PinAddedMessage { public static class PinAddedMessage {

@ -20,7 +20,6 @@ package org.floens.chan.core.model;
import com.j256.ormlite.field.DatabaseField; import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable; import com.j256.ormlite.table.DatabaseTable;
import org.floens.chan.ChanApplication;
import org.floens.chan.core.watch.PinWatcher; import org.floens.chan.core.watch.PinWatcher;
@DatabaseTable @DatabaseTable
@ -80,10 +79,8 @@ public class Pin {
} }
} }
public void update() { public boolean update() {
if (pinWatcher != null && watching) { return pinWatcher != null && watching && pinWatcher.update();
pinWatcher.update();
}
} }
public void createWatcher() { public void createWatcher() {
@ -98,10 +95,4 @@ public class Pin {
pinWatcher = null; pinWatcher = null;
} }
} }
public void toggleWatch() {
watching = !watching;
ChanApplication.getWatchManager().onPinsChanged();
ChanApplication.getWatchManager().invokeLoadNow();
}
} }

@ -55,18 +55,15 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt
} }
public void bindLoadable(Loadable loadable) { public void bindLoadable(Loadable loadable) {
if (chanLoader == null) {
if (!loadable.equals(this.loadable)) { if (!loadable.equals(this.loadable)) {
if (this.loadable != null) { if (chanLoader != null) {
unbindLoadable(); unbindLoadable();
} }
this.loadable = loadable; this.loadable = loadable;
chanLoader = LoaderPool.getInstance().obtain(loadable, this); chanLoader = LoaderPool.getInstance().obtain(loadable, this);
} }
} }
}
public void unbindLoadable() { public void unbindLoadable() {
if (chanLoader != null) { if (chanLoader != null) {

@ -91,9 +91,19 @@ public class ChanSettings {
anonymizeIds = new BooleanSetting(p, "preference_anonymize_ids", false); anonymizeIds = new BooleanSetting(p, "preference_anonymize_ids", false);
repliesButtonsBottom = new BooleanSetting(p, "preference_buttons_bottom", false); repliesButtonsBottom = new BooleanSetting(p, "preference_buttons_bottom", false);
watchEnabled = new BooleanSetting(p, "preference_watch_enabled", false); watchEnabled = new BooleanSetting(p, "preference_watch_enabled", false, new Setting.SettingCallback<Boolean>() {
@Override
public void onValueChange(Setting setting, Boolean value) {
ChanApplication.getWatchManager().onWatchEnabledChanged(value);
}
});
watchCountdown = new BooleanSetting(p, "preference_watch_countdown", false); watchCountdown = new BooleanSetting(p, "preference_watch_countdown", false);
watchBackground = new BooleanSetting(p, "preference_watch_background_enabled", false); watchBackground = new BooleanSetting(p, "preference_watch_background_enabled", false, new Setting.SettingCallback<Boolean>() {
@Override
public void onValueChange(Setting setting, Boolean value) {
ChanApplication.getWatchManager().onBackgroundWatchingChanged(value);
}
});
watchBackgroundTimeout = new StringSetting(p, "preference_watch_background_timeout", "60"); watchBackgroundTimeout = new StringSetting(p, "preference_watch_background_timeout", "60");
watchNotifyMode = new StringSetting(p, "preference_watch_notify_mode", "all"); watchNotifyMode = new StringSetting(p, "preference_watch_notify_mode", "all");
watchSound = new StringSetting(p, "preference_watch_sound", "all"); watchSound = new StringSetting(p, "preference_watch_sound", "all");

@ -55,9 +55,12 @@ public class PinWatcher implements ChanLoader.ChanLoaderCallback {
} }
} }
public void update() { public boolean update() {
if (!pin.isError) { if (!pin.isError) {
chanLoader.loadMoreIfTime(); chanLoader.loadMoreIfTime();
return true;
} else {
return false;
} }
} }
@ -192,7 +195,7 @@ public class PinWatcher implements ChanLoader.ChanLoaderCallback {
AndroidUtils.runOnUiThread(new Runnable() { AndroidUtils.runOnUiThread(new Runnable() {
@Override @Override
public void run() { public void run() {
ChanApplication.getWatchManager().onPinsChanged(); ChanApplication.getWatchManager().pinWatcherUpdated(pin);
} }
}); });
} }

@ -45,21 +45,20 @@ import android.widget.ListView;
import org.floens.chan.ChanApplication; import org.floens.chan.ChanApplication;
import org.floens.chan.R; import org.floens.chan.R;
import org.floens.chan.core.manager.WatchManager;
import org.floens.chan.core.model.ChanThread; import org.floens.chan.core.model.ChanThread;
import org.floens.chan.core.model.Loadable; import org.floens.chan.core.model.Loadable;
import org.floens.chan.core.model.Pin; import org.floens.chan.core.model.Pin;
import org.floens.chan.core.model.Post; import org.floens.chan.core.model.Post;
import org.floens.chan.ui.animation.SwipeDismissListViewTouchListener;
import org.floens.chan.ui.animation.SwipeDismissListViewTouchListener.DismissCallbacks;
import org.floens.chan.ui.ThemeActivity; import org.floens.chan.ui.ThemeActivity;
import org.floens.chan.ui.adapter.PinnedAdapter; import org.floens.chan.ui.adapter.PinnedAdapter;
import org.floens.chan.ui.animation.SwipeDismissListViewTouchListener;
import org.floens.chan.ui.animation.SwipeDismissListViewTouchListener.DismissCallbacks;
import org.floens.chan.utils.AndroidUtils; import org.floens.chan.utils.AndroidUtils;
import org.floens.chan.utils.ThemeHelper; import org.floens.chan.utils.ThemeHelper;
import static org.floens.chan.utils.AndroidUtils.dp; import static org.floens.chan.utils.AndroidUtils.dp;
public abstract class BaseActivity extends ThemeActivity implements PanelSlideListener, WatchManager.PinListener { public abstract class BaseActivity extends ThemeActivity implements PanelSlideListener {
public static boolean doRestartOnResume = false; public static boolean doRestartOnResume = false;
private final static int ACTION_OPEN_URL = 1; private final static int ACTION_OPEN_URL = 1;
@ -110,8 +109,6 @@ public abstract class BaseActivity extends ThemeActivity implements PanelSlideLi
threadPane = (SlidingPaneLayout) findViewById(R.id.pane_container); threadPane = (SlidingPaneLayout) findViewById(R.id.pane_container);
initPane(); initPane();
ChanApplication.getWatchManager().addPinListener(this);
updateIcon(); updateIcon();
} }
@ -127,8 +124,6 @@ public abstract class BaseActivity extends ThemeActivity implements PanelSlideLi
@Override @Override
protected void onDestroy() { protected void onDestroy() {
super.onDestroy(); super.onDestroy();
ChanApplication.getWatchManager().removePinListener(this);
} }
@Override @Override
@ -212,12 +207,6 @@ public abstract class BaseActivity extends ThemeActivity implements PanelSlideLi
pinDrawerView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS); pinDrawerView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
} }
@Override
public void onPinsChanged() {
pinnedAdapter.reload();
updateIcon();
}
private void updateIcon() { private void updateIcon() {
/*List<Pin> list = ChanApplication.getWatchManager().getWatchingPins(); /*List<Pin> list = ChanApplication.getWatchManager().getWatchingPins();
if (list.size() > 0) { if (list.size() > 0) {

@ -17,115 +17,8 @@
*/ */
package org.floens.chan.ui.activity; package org.floens.chan.ui.activity;
import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.ViewGroup;
import org.floens.chan.controller.Controller;
import org.floens.chan.ui.controller.BrowseController;
import org.floens.chan.ui.controller.RootNavigationController;
import org.floens.chan.utils.ThemeHelper;
import java.util.ArrayList;
import java.util.List;
/** /**
* StartActivity * The old starting activity. This exists so that the launcher icon does not disappear.
* <p/>
* (Not actually called StartActivity because then the launcher icon would disappear.
* Instead it's called like the old launcher activity, BoardActivity.)
*/ */
public class BoardActivity extends Activity { public class BoardActivity extends StartActivity {
private static final String TAG = "StartActivity";
private ViewGroup contentView;
private List<Controller> stack = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ThemeHelper.getInstance().reloadPostViewColors(this);
contentView = (ViewGroup) findViewById(android.R.id.content);
RootNavigationController rootNavigationController = new RootNavigationController(this);
rootNavigationController.onCreate();
setContentView(rootNavigationController.view);
addController(rootNavigationController);
rootNavigationController.pushController(new BrowseController(this), false);
rootNavigationController.onShow();
// Prevent overdraw
// Do this after setContentView, or the decor creating will reset the background to a default non-null drawable
getWindow().setBackgroundDrawable(null);
}
public void addController(Controller controller) {
stack.add(controller);
}
public void removeController(Controller controller) {
stack.remove(controller);
}
public ViewGroup getContentView() {
return contentView;
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
for (Controller controller : stack) {
controller.onConfigurationChanged(newConfig);
}
}
@Override
public void onBackPressed() {
if (!stackTop().onBack()) {
// Don't destroy the view, let Android do that or it'll create artifacts
stackTop().onHide();
super.onBackPressed();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
stackTop().onDestroy();
}
private Controller stackTop() {
return stack.get(stack.size() - 1);
}
/*
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// http://stackoverflow.com/a/7748416/1001608
// Possible work around for market launches. See http://code.google.com/p/android/issues/detail?id=2373
// for more details. Essentially, the market launches the main activity on top of other activities.
// we never want this to happen. Instead, we check if we are the root and if not, we finish.
if (!isTaskRoot()) {
final Intent intent = getIntent();
final String intentAction = intent.getAction();
if (intent.hasCategory(Intent.CATEGORY_LAUNCHER) && intentAction != null && intentAction.equals(Intent.ACTION_MAIN)) {
Logger.w(TAG, "StartActivity is not the root. Finishing StartActivity instead of launching.");
finish();
return;
}
}
Intent intent = new Intent(this, ChanActivity.class);
startActivity(intent);
finish();
}*/
} }

@ -0,0 +1,106 @@
package org.floens.chan.ui.activity;
import android.app.Activity;
import android.content.res.Configuration;
import android.os.Bundle;
import android.view.ViewGroup;
import org.floens.chan.ChanApplication;
import org.floens.chan.controller.Controller;
import org.floens.chan.ui.controller.BrowseController;
import org.floens.chan.ui.controller.RootNavigationController;
import org.floens.chan.utils.ThemeHelper;
import java.util.ArrayList;
import java.util.List;
public class StartActivity extends Activity {
private static final String TAG = "StartActivity";
private ViewGroup contentView;
private List<Controller> stack = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ThemeHelper.getInstance().reloadPostViewColors(this);
contentView = (ViewGroup) findViewById(android.R.id.content);
RootNavigationController rootNavigationController = new RootNavigationController(this);
rootNavigationController.onCreate();
setContentView(rootNavigationController.view);
addController(rootNavigationController);
rootNavigationController.pushController(new BrowseController(this), false);
rootNavigationController.onShow();
// Prevent overdraw
// Do this after setContentView, or the decor creating will reset the background to a default non-null drawable
getWindow().setBackgroundDrawable(null);
}
public void addController(Controller controller) {
stack.add(controller);
}
public void removeController(Controller controller) {
stack.remove(controller);
}
public ViewGroup getContentView() {
return contentView;
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
for (Controller controller : stack) {
controller.onConfigurationChanged(newConfig);
}
}
@Override
public void onBackPressed() {
if (!stackTop().onBack()) {
// Don't destroy the view, let Android do that or it'll create artifacts
stackTop().onHide();
super.onBackPressed();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
stackTop().onDestroy();
}
@Override
protected void onStart() {
super.onStart();
ChanApplication.getInstance().activityEnteredForeground();
}
@Override
protected void onStop() {
super.onStop();
ChanApplication.getInstance().activityEnteredBackground();
}
@Override
protected void onPause() {
super.onPause();
ChanApplication.getWatchManager().updateDatabase();
}
private Controller stackTop() {
return stack.get(stack.size() - 1);
}
}

@ -1,5 +1,6 @@
package org.floens.chan.ui.adapter; package org.floens.chan.ui.adapter;
import android.os.Build;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@ -10,16 +11,21 @@ import android.widget.TextView;
import org.floens.chan.ChanApplication; import org.floens.chan.ChanApplication;
import org.floens.chan.R; import org.floens.chan.R;
import org.floens.chan.core.model.Pin; import org.floens.chan.core.model.Pin;
import org.floens.chan.core.settings.ChanSettings;
import org.floens.chan.ui.helper.SwipeListener; import org.floens.chan.ui.helper.SwipeListener;
import org.floens.chan.ui.view.ThumbnailView; import org.floens.chan.ui.view.ThumbnailView;
import org.floens.chan.utils.AndroidUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import static org.floens.chan.utils.AndroidUtils.ROBOTO_MEDIUM; import static org.floens.chan.utils.AndroidUtils.ROBOTO_MEDIUM;
import static org.floens.chan.utils.AndroidUtils.dp; import static org.floens.chan.utils.AndroidUtils.dp;
import static org.floens.chan.utils.AndroidUtils.getAttrDrawable;
public class PinAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements SwipeListener.Callback { public class PinAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements SwipeListener.Callback {
private static final int PIN_OFFSET = 3;
private static final int TYPE_HEADER = 0; private static final int TYPE_HEADER = 0;
private static final int TYPE_PIN = 1; private static final int TYPE_PIN = 1;
private static final int TYPE_LINK = 2; private static final int TYPE_LINK = 2;
@ -52,10 +58,10 @@ public class PinAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> im
((PinHeaderHolder) holder).text.setText(R.string.drawer_pinned); ((PinHeaderHolder) holder).text.setText(R.string.drawer_pinned);
break; break;
case TYPE_PIN: case TYPE_PIN:
final Pin pin = pins.get(position - 3); final Pin pin = pins.get(position - PIN_OFFSET);
PinViewHolder pinHolder = (PinViewHolder) holder; PinViewHolder pinHolder = (PinViewHolder) holder;
pinHolder.textView.setText(pin.loadable.title); updatePinViewHolder(pinHolder, pin);
pinHolder.image.setUrl(pin.thumbnailUrl, dp(40), dp(40));
break; break;
case TYPE_LINK: case TYPE_LINK:
LinkHolder linkHolder = (LinkHolder) holder; LinkHolder linkHolder = (LinkHolder) holder;
@ -75,12 +81,12 @@ public class PinAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> im
@Override @Override
public int getItemCount() { public int getItemCount() {
return pins.size() + 3; return pins.size() + PIN_OFFSET;
} }
@Override @Override
public long getItemId(int position) { public long getItemId(int position) {
position -= 3; position -= PIN_OFFSET;
if (position >= 0 && position < pins.size()) { if (position >= 0 && position < pins.size()) {
return pins.get(position).id + 10; return pins.get(position).id + 10;
} else { } else {
@ -109,7 +115,7 @@ public class PinAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> im
public void onPinAdded(Pin pin) { public void onPinAdded(Pin pin) {
pins.add(pin); pins.add(pin);
notifyItemInserted(pins.size() - 1 + 3); notifyItemInserted(pins.size() - 1 + PIN_OFFSET);
} }
public void onPinRemoved(Pin pin) { public void onPinRemoved(Pin pin) {
@ -120,12 +126,24 @@ public class PinAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> im
} else { } else {
int location = pins.indexOf(pin); int location = pins.indexOf(pin);
pins.remove(pin); pins.remove(pin);
notifyItemRemoved(location + 3); notifyItemRemoved(location + PIN_OFFSET);
} }
} }
public void onPinChanged(Pin pin) { public void onPinChanged(RecyclerView recyclerView, Pin pin) {
notifyItemChanged(pins.indexOf(pin) + 3); PinViewHolder holder = (PinViewHolder) recyclerView.findViewHolderForAdapterPosition(pins.indexOf(pin) + PIN_OFFSET);
if (holder != null) {
updatePinViewHolder(holder, pin);
}
}
public void updateHighlighted(RecyclerView recyclerView) {
for (int i = 0; i < pins.size(); i++) {
PinViewHolder holder = (PinViewHolder) recyclerView.findViewHolderForAdapterPosition(i + PIN_OFFSET);
if (holder != null) {
updatePinViewHolder(holder, pins.get(i));
}
}
} }
@Override @Override
@ -135,7 +153,7 @@ public class PinAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> im
@Override @Override
public void removeItem(int position) { public void removeItem(int position) {
ChanApplication.getWatchManager().removePin(pins.get(position - 3)); ChanApplication.getWatchManager().removePin(pins.get(position - PIN_OFFSET));
} }
@Override @Override
@ -145,8 +163,8 @@ public class PinAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> im
@Override @Override
public void moveItem(int from, int to) { public void moveItem(int from, int to) {
Pin item = pins.remove(from - 3); Pin item = pins.remove(from - PIN_OFFSET);
pins.add(to - 3, item); pins.add(to - PIN_OFFSET, item);
notifyItemMoved(from, to); notifyItemMoved(from, to);
} }
@ -154,21 +172,88 @@ public class PinAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> im
public void movingDone() { public void movingDone() {
} }
public void updatePinViewHolder(PinViewHolder holder, Pin pin) {
holder.textView.setText(pin.loadable.title);
holder.image.setUrl(pin.thumbnailUrl, dp(40), dp(40));
if (ChanSettings.watchEnabled.get()) {
String count;
if (pin.isError) {
count = "Err";
} else {
int c = pin.getNewPostCount();
if (c > 999) {
count = "1k+";
} else {
count = Integer.toString(c);
}
}
holder.watchCountText.setVisibility(View.VISIBLE);
holder.watchCountText.setText(count);
if (!pin.watching) {
holder.watchCountText.setTextColor(0xff898989); // TODO material colors
} else if (pin.getNewQuoteCount() > 0) {
holder.watchCountText.setTextColor(0xffFF4444);
} else {
holder.watchCountText.setTextColor(0xff33B5E5);
}
// The 16dp padding now belongs to the counter, for a bigger touch area
holder.textView.setPadding(holder.textView.getPaddingLeft(), holder.textView.getPaddingTop(),
0, holder.textView.getPaddingBottom());
holder.watchCountText.setPadding(dp(16), holder.watchCountText.getPaddingTop(),
holder.watchCountText.getPaddingRight(), holder.watchCountText.getPaddingBottom());
} else {
// The 16dp padding now belongs to the textview, for better ellipsize
holder.watchCountText.setVisibility(View.GONE);
holder.textView.setPadding(holder.textView.getPaddingLeft(), holder.textView.getPaddingTop(),
dp(16), holder.textView.getPaddingBottom());
}
boolean highlighted = callback.isHighlighted(pin);
if (highlighted && !holder.highlighted) {
holder.itemView.setBackgroundColor(0x22000000);
holder.highlighted = true;
} else if (!highlighted && holder.highlighted) {
//noinspection deprecation
holder.itemView.setBackgroundDrawable(AndroidUtils.getAttrDrawable(holder.itemView.getContext(), android.R.attr.selectableItemBackground));
holder.highlighted = false;
}
}
public class PinViewHolder extends RecyclerView.ViewHolder { public class PinViewHolder extends RecyclerView.ViewHolder {
private boolean highlighted;
private ThumbnailView image; private ThumbnailView image;
private TextView textView; private TextView textView;
private TextView watchCountText;
public PinViewHolder(View pinCell) { public PinViewHolder(View itemView) {
super(pinCell); super(itemView);
image = (ThumbnailView) pinCell.findViewById(R.id.thumb); image = (ThumbnailView) itemView.findViewById(R.id.thumb);
image.setCircular(true); image.setCircular(true);
textView = (TextView) pinCell.findViewById(R.id.text); textView = (TextView) itemView.findViewById(R.id.text);
textView.setTypeface(ROBOTO_MEDIUM); textView.setTypeface(ROBOTO_MEDIUM);
watchCountText = (TextView) itemView.findViewById(R.id.watch_count);
watchCountText.setTypeface(ROBOTO_MEDIUM);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
watchCountText.setBackground(getAttrDrawable(itemView.getContext(), android.R.attr.selectableItemBackgroundBorderless));
} else {
watchCountText.setBackgroundResource(R.drawable.gray_background_selector);
}
pinCell.setOnClickListener(new View.OnClickListener() { itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
callback.onPinClicked(pins.get(getAdapterPosition() - PIN_OFFSET));
}
});
watchCountText.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
callback.onPinClicked(pins.get(getAdapterPosition() - 3)); callback.onWatchCountClicked(pins.get(getAdapterPosition() - PIN_OFFSET));
} }
}); });
} }
@ -205,5 +290,9 @@ public class PinAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> im
public interface Callback { public interface Callback {
void onPinClicked(Pin pin); void onPinClicked(Pin pin);
void onWatchCountClicked(Pin pin);
boolean isHighlighted(Pin pin);
} }
} }

@ -178,7 +178,7 @@ public class PinnedAdapter extends BaseAdapter {
countContainer.setOnClickListener(new View.OnClickListener() { countContainer.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View v) {
pin.toggleWatch(); // pin.toggleWatch();
} }
}); });

@ -31,6 +31,7 @@ import org.floens.chan.chan.ChanUrls;
import org.floens.chan.core.manager.BoardManager; import org.floens.chan.core.manager.BoardManager;
import org.floens.chan.core.model.Board; import org.floens.chan.core.model.Board;
import org.floens.chan.core.model.Loadable; import org.floens.chan.core.model.Loadable;
import org.floens.chan.core.model.Pin;
import org.floens.chan.ui.layout.ThreadLayout; import org.floens.chan.ui.layout.ThreadLayout;
import org.floens.chan.ui.toolbar.ToolbarMenu; import org.floens.chan.ui.toolbar.ToolbarMenu;
import org.floens.chan.ui.toolbar.ToolbarMenuItem; import org.floens.chan.ui.toolbar.ToolbarMenuItem;
@ -41,7 +42,7 @@ import org.floens.chan.utils.AndroidUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class BrowseController extends ThreadController implements ToolbarMenuItem.ToolbarMenuItemCallback, ThreadLayout.ThreadLayoutCallback, FloatingMenu.FloatingMenuCallback, BoardManager.BoardChangeListener { public class BrowseController extends ThreadController implements ToolbarMenuItem.ToolbarMenuItemCallback, ThreadLayout.ThreadLayoutCallback, FloatingMenu.FloatingMenuCallback, BoardManager.BoardChangeListener, RootNavigationController.DrawerCallbacks {
private static final int REFRESH_ID = 1; private static final int REFRESH_ID = 1;
private static final int POST_ID = 2; private static final int POST_ID = 2;
private static final int SEARCH_ID = 101; private static final int SEARCH_ID = 101;
@ -144,6 +145,16 @@ public class BrowseController extends ThreadController implements ToolbarMenuIte
loadBoards(); loadBoards();
} }
@Override
public void onPinClicked(Pin pin) {
openThread(pin.loadable);
}
@Override
public boolean isPinCurrent(Pin pin) {
return false;
}
private void loadBoard(Board board) { private void loadBoard(Board board) {
Loadable loadable = new Loadable(board.value); Loadable loadable = new Loadable(board.value);
loadable.mode = Loadable.Mode.CATALOG; loadable.mode = Loadable.Mode.CATALOG;

@ -217,7 +217,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.updateTitle(navigationItem); navigationItem.updateTitle();
} }
public void scrollTo(PostImage postImage) { public void scrollTo(PostImage postImage) {

@ -28,6 +28,7 @@ import android.widget.FrameLayout;
import org.floens.chan.ChanApplication; import org.floens.chan.ChanApplication;
import org.floens.chan.R; import org.floens.chan.R;
import org.floens.chan.controller.Controller; import org.floens.chan.controller.Controller;
import org.floens.chan.controller.ControllerTransition;
import org.floens.chan.controller.NavigationController; import org.floens.chan.controller.NavigationController;
import org.floens.chan.core.manager.WatchManager; import org.floens.chan.core.manager.WatchManager;
import org.floens.chan.core.model.Pin; import org.floens.chan.core.model.Pin;
@ -121,9 +122,37 @@ public class RootNavigationController extends NavigationController implements Pi
setDrawerEnabled(controller.navigationItem.hasDrawer); setDrawerEnabled(controller.navigationItem.hasDrawer);
} }
@Override
public void onControllerTransitionCompleted(ControllerTransition transition) {
super.onControllerTransitionCompleted(transition);
updateHighlighted();
}
public void updateHighlighted() {
pinAdapter.updateHighlighted(recyclerView);
}
@Override @Override
public void onPinClicked(Pin pin) { public void onPinClicked(Pin pin) {
Controller top = getTop();
if (top instanceof DrawerCallbacks) {
((DrawerCallbacks) top).onPinClicked(pin);
drawerLayout.closeDrawer(Gravity.LEFT);
pinAdapter.updateHighlighted(recyclerView);
}
}
public boolean isHighlighted(Pin pin) {
Controller top = getTop();
if (top instanceof DrawerCallbacks) {
return ((DrawerCallbacks) top).isPinCurrent(pin);
}
return false;
}
@Override
public void onWatchCountClicked(Pin pin) {
ChanApplication.getWatchManager().toggleWatch(pin);
} }
public void onEvent(WatchManager.PinAddedMessage message) { public void onEvent(WatchManager.PinAddedMessage message) {
@ -136,7 +165,7 @@ public class RootNavigationController extends NavigationController implements Pi
} }
public void onEvent(WatchManager.PinChangedMessage message) { public void onEvent(WatchManager.PinChangedMessage message) {
pinAdapter.onPinChanged(message.pin); pinAdapter.onPinChanged(recyclerView, message.pin);
} }
private void setDrawerEnabled(boolean enabled) { private void setDrawerEnabled(boolean enabled) {
@ -153,4 +182,10 @@ public class RootNavigationController extends NavigationController implements Pi
return false; return false;
} }
} }
public interface DrawerCallbacks {
void onPinClicked(Pin pin);
boolean isPinCurrent(Pin pin);
}
} }

@ -49,4 +49,8 @@ public abstract class ThreadController extends Controller implements ThreadLayou
public void scrollTo(PostImage postImage) { public void scrollTo(PostImage postImage) {
threadLayout.getPresenter().scrollTo(postImage); threadLayout.getPresenter().scrollTo(postImage);
} }
@Override
public void onShowPosts() {
}
} }

@ -26,6 +26,7 @@ import org.floens.chan.R;
import org.floens.chan.chan.ChanUrls; import org.floens.chan.chan.ChanUrls;
import org.floens.chan.core.manager.WatchManager; import org.floens.chan.core.manager.WatchManager;
import org.floens.chan.core.model.Loadable; import org.floens.chan.core.model.Loadable;
import org.floens.chan.core.model.Pin;
import org.floens.chan.ui.layout.ThreadLayout; import org.floens.chan.ui.layout.ThreadLayout;
import org.floens.chan.ui.toolbar.ToolbarMenu; import org.floens.chan.ui.toolbar.ToolbarMenu;
import org.floens.chan.ui.toolbar.ToolbarMenuItem; import org.floens.chan.ui.toolbar.ToolbarMenuItem;
@ -36,7 +37,7 @@ import java.util.Arrays;
import de.greenrobot.event.EventBus; import de.greenrobot.event.EventBus;
public class ViewThreadController extends ThreadController implements ThreadLayout.ThreadLayoutCallback, ToolbarMenuItem.ToolbarMenuItemCallback { public class ViewThreadController extends ThreadController implements ThreadLayout.ThreadLayoutCallback, ToolbarMenuItem.ToolbarMenuItemCallback, RootNavigationController.DrawerCallbacks {
private static final int POST_ID = 1; private static final int POST_ID = 1;
private static final int PIN_ID = 2; private static final int PIN_ID = 2;
private static final int REFRESH_ID = 101; private static final int REFRESH_ID = 101;
@ -62,11 +63,7 @@ public class ViewThreadController extends ThreadController implements ThreadLayo
view.setBackgroundColor(0xffffffff); view.setBackgroundColor(0xffffffff);
threadLayout.getPresenter().bindLoadable(loadable);
threadLayout.getPresenter().requestData();
navigationItem.hasDrawer = true; navigationItem.hasDrawer = true;
navigationItem.title = loadable.title;
navigationItem.menu = new ToolbarMenu(context); navigationItem.menu = new ToolbarMenu(context);
navigationItem.menu.addItem(new ToolbarMenuItem(context, this, POST_ID, R.drawable.ic_action_write)); navigationItem.menu.addItem(new ToolbarMenuItem(context, this, POST_ID, R.drawable.ic_action_write));
@ -77,7 +74,15 @@ public class ViewThreadController extends ThreadController implements ThreadLayo
new FloatingMenuItem(SHARE_ID, context.getString(R.string.action_share)) new FloatingMenuItem(SHARE_ID, context.getString(R.string.action_share))
)); ));
setPinIconState(threadLayout.getPresenter().isPinned()); loadLoadable(loadable);
}
@Override
public void onShow() {
super.onShow();
if (navigationController instanceof RootNavigationController) {
((RootNavigationController)navigationController).updateHighlighted();
}
} }
@Override @Override
@ -100,14 +105,17 @@ public class ViewThreadController extends ThreadController implements ThreadLayo
} }
@Override @Override
public void openThread(Loadable threadLoadable) { public void openThread(final Loadable threadLoadable) {
// TODO implement, scroll to post and fix title // TODO implement, scroll to post and fix title
new AlertDialog.Builder(context) new AlertDialog.Builder(context)
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
@Override @Override
public void onClick(final DialogInterface dialog, final int which) { public void onClick(final DialogInterface dialog, final int which) {
// threadManagerListener.onOpenThread(thread, link.postId); loadLoadable(threadLoadable);
if (navigationController instanceof RootNavigationController) {
((RootNavigationController)navigationController).updateHighlighted();
}
} }
}) })
.setTitle(R.string.open_thread_confirmation) .setTitle(R.string.open_thread_confirmation)
@ -115,6 +123,36 @@ public class ViewThreadController extends ThreadController implements ThreadLayo
.show(); .show();
} }
@Override
public void onPinClicked(Pin pin) {
loadLoadable(pin.loadable);
}
@Override
public boolean isPinCurrent(Pin pin) {
return pin.loadable.equals(loadable);
}
private void loadLoadable(Loadable loadable) {
if (!loadable.equals(threadLayout.getPresenter().getLoadable())) {
this.loadable = loadable;
threadLayout.getPresenter().bindLoadable(loadable);
threadLayout.getPresenter().requestData();
navigationItem.title = loadable.title;
navigationItem.updateTitle();
setPinIconState(threadLayout.getPresenter().isPinned());
}
}
@Override
public void onShowPosts() {
super.onShowPosts();
if (!navigationItem.title.equals(loadable.title)) {
navigationItem.title = loadable.title;
navigationItem.updateTitle();
}
}
@Override @Override
public void onMenuItemClicked(ToolbarMenuItem item) { public void onMenuItemClicked(ToolbarMenuItem item) {
switch (item.getId()) { switch (item.getId()) {

@ -91,6 +91,7 @@ public class ThreadLayout extends LoadView implements ThreadPresenter.ThreadPres
public void showPosts(ChanThread thread) { public void showPosts(ChanThread thread) {
threadListLayout.showPosts(thread, !visible); threadListLayout.showPosts(thread, !visible);
switchVisible(true); switchVisible(true);
callback.onShowPosts();
} }
@Override @Override
@ -188,5 +189,7 @@ public class ThreadLayout extends LoadView implements ThreadPresenter.ThreadPres
void openThread(Loadable threadLoadable); void openThread(Loadable threadLoadable);
void showImages(List<PostImage> images, int index, Loadable loadable, ThumbnailView thumbnail); void showImages(List<PostImage> images, int index, Loadable loadable, ThumbnailView thumbnail);
void onShowPosts();
} }
} }

@ -20,7 +20,9 @@ package org.floens.chan.ui.toolbar;
import android.content.Context; import android.content.Context;
import android.view.View; import android.view.View;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView;
import org.floens.chan.R;
import org.floens.chan.ui.view.FloatingMenu; import org.floens.chan.ui.view.FloatingMenu;
import org.floens.chan.ui.view.FloatingMenuItem; import org.floens.chan.ui.view.FloatingMenuItem;
@ -30,15 +32,25 @@ public class NavigationItem {
public String title = ""; public String title = "";
public ToolbarMenu menu; public ToolbarMenu menu;
public boolean hasBack = true; public boolean hasBack = true;
public LinearLayout view;
public FloatingMenu middleMenu; public FloatingMenu middleMenu;
public View rightView; public View rightView;
public boolean hasDrawer = false; public boolean hasDrawer = false;
LinearLayout view;
public ToolbarMenuItem 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 overflow; return overflow;
} }
public void updateTitle() {
if (view != null) {
TextView titleView = (TextView) view.findViewById(R.id.title);
if (titleView != null) {
titleView.setText(title);
}
}
}
} }

@ -89,15 +89,6 @@ 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;
} }
@ -132,10 +123,8 @@ public class Toolbar extends LinearLayout implements View.OnClickListener {
arrowMenuView.setImageDrawable(arrowMenuDrawable); arrowMenuView.setImageDrawable(arrowMenuDrawable);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//noinspection deprecation arrowMenuView.setBackground(getAttrDrawable(getContext(), android.R.attr.selectableItemBackgroundBorderless));
arrowMenuView.setBackgroundDrawable(getAttrDrawable(android.R.attr.selectableItemBackgroundBorderless));
} else { } else {
//noinspection deprecation
arrowMenuView.setBackgroundResource(R.drawable.gray_background_selector); arrowMenuView.setBackgroundResource(R.drawable.gray_background_selector);
} }

@ -58,10 +58,8 @@ public class ToolbarMenuItem implements View.OnClickListener, FloatingMenu.Float
imageView.setImageDrawable(drawable); imageView.setImageDrawable(drawable);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//noinspection deprecation imageView.setBackground(getAttrDrawable(context, android.R.attr.selectableItemBackgroundBorderless));
imageView.setBackgroundDrawable(getAttrDrawable(android.R.attr.selectableItemBackgroundBorderless));
} else { } else {
//noinspection deprecation
imageView.setBackgroundResource(R.drawable.gray_background_selector); imageView.setBackgroundResource(R.drawable.gray_background_selector);
} }
} }

@ -100,13 +100,6 @@ public class AndroidUtils {
} }
} }
public static int getAttrPixel(int attr) {
TypedArray typedArray = ChanApplication.con.getTheme().obtainStyledAttributes(new int[]{attr});
int pixels = typedArray.getDimensionPixelSize(0, 0);
typedArray.recycle();
return pixels;
}
public static int getAttrColor(Context context, int attr) { public static int getAttrColor(Context context, int attr) {
TypedArray typedArray = context.getTheme().obtainStyledAttributes(new int[]{attr}); TypedArray typedArray = context.getTheme().obtainStyledAttributes(new int[]{attr});
int color = typedArray.getColor(0, 0); int color = typedArray.getColor(0, 0);
@ -114,8 +107,8 @@ public class AndroidUtils {
return color; return color;
} }
public static Drawable getAttrDrawable(int attr) { public static Drawable getAttrDrawable(Context context, int attr) {
TypedArray typedArray = ChanApplication.con.getTheme().obtainStyledAttributes(new int[]{attr}); TypedArray typedArray = context.obtainStyledAttributes(new int[]{attr});
Drawable drawable = typedArray.getDrawable(0); Drawable drawable = typedArray.getDrawable(0);
typedArray.recycle(); typedArray.recycle();
return drawable; return drawable;

@ -7,7 +7,7 @@
<TextView <TextView
android:id="@+id/text" android:id="@+id/text"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="48dp" android:layout_height="match_parent"
android:ellipsize="end" android:ellipsize="end"
android:gravity="center_vertical" android:gravity="center_vertical"
android:paddingLeft="16dp" android:paddingLeft="16dp"

@ -3,7 +3,7 @@
android:orientation="horizontal" android:orientation="horizontal"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="48dp" android:layout_height="48dp"
android:background="?attr/selectableItemBackground"> android:background="?android:attr/selectableItemBackground">
<org.floens.chan.ui.view.ThumbnailView <org.floens.chan.ui.view.ThumbnailView
android:id="@+id/thumb" android:id="@+id/thumb"
@ -17,7 +17,7 @@
<TextView <TextView
android:id="@+id/text" android:id="@+id/text"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="48dp" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
android:ellipsize="end" android:ellipsize="end"
android:gravity="center_vertical" android:gravity="center_vertical"
@ -27,4 +27,15 @@
android:textColor="#ff212121" android:textColor="#ff212121"
android:textSize="14sp" /> android:textSize="14sp" />
<TextView
android:id="@+id/watch_count"
android:layout_width="48dp"
android:layout_height="match_parent"
android:background="?android:attr/selectableItemBackground"
android:singleLine="true"
android:gravity="center"
android:paddingRight="16dp"
android:textColor="#ff000000"
android:textSize="14sp" />
</LinearLayout> </LinearLayout>

Loading…
Cancel
Save