diff --git a/Clover/app/src/main/java/org/floens/chan/ChanApplication.java b/Clover/app/src/main/java/org/floens/chan/ChanApplication.java index 47da5745..f0b2f2da 100644 --- a/Clover/app/src/main/java/org/floens/chan/ChanApplication.java +++ b/Clover/app/src/main/java/org/floens/chan/ChanApplication.java @@ -33,7 +33,7 @@ import org.floens.chan.core.manager.BoardManager; import org.floens.chan.core.manager.ReplyManager; import org.floens.chan.core.manager.WatchManager; import org.floens.chan.core.net.BitmapLruImageCache; -import org.floens.chan.core.preferences.ChanPreferences; +import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.database.DatabaseManager; import org.floens.chan.utils.AndroidUtils; import org.floens.chan.utils.FileCache; @@ -131,7 +131,7 @@ public class ChanApplication extends Application { AndroidUtils.init(); - ChanUrls.loadScheme(ChanPreferences.getNetworkHttps()); + ChanUrls.loadScheme(ChanSettings.getNetworkHttps()); IconCache.createIcons(this); diff --git a/Clover/app/src/main/java/org/floens/chan/controller/Controller.java b/Clover/app/src/main/java/org/floens/chan/controller/Controller.java index a1b11bbd..7af83134 100644 --- a/Clover/app/src/main/java/org/floens/chan/controller/Controller.java +++ b/Clover/app/src/main/java/org/floens/chan/controller/Controller.java @@ -58,4 +58,8 @@ public abstract class Controller { public boolean onBack() { return false; } + + public String string(int id) { + return context.getString(id); + } } diff --git a/Clover/app/src/main/java/org/floens/chan/controller/NavigationController.java b/Clover/app/src/main/java/org/floens/chan/controller/NavigationController.java index 1061be0d..e9b3a156 100644 --- a/Clover/app/src/main/java/org/floens/chan/controller/NavigationController.java +++ b/Clover/app/src/main/java/org/floens/chan/controller/NavigationController.java @@ -46,7 +46,7 @@ public abstract class NavigationController extends Controller implements Control public boolean pushController(final Controller to) { if (blockingInput) return false; - if (this.controllerTransition != null) { + if (controllerTransition != null) { throw new IllegalArgumentException("Cannot push controller while a transition is in progress."); } @@ -64,7 +64,7 @@ public abstract class NavigationController extends Controller implements Control container.addView(to.view, FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT); AndroidUtils.waitForMeasure(to.view, new AndroidUtils.OnMeasuredCallback() { @Override - public void onMeasured(View view, int width, int height) { + public void onMeasured(View view) { to.onShow(); doTransition(true, from, to, controllerTransition); @@ -77,7 +77,7 @@ public abstract class NavigationController extends Controller implements Control public boolean popController() { if (blockingInput) return false; - if (this.controllerTransition != null) { + if (controllerTransition != null) { throw new IllegalArgumentException("Cannot pop controller while a transition is in progress."); } @@ -94,7 +94,7 @@ public abstract class NavigationController extends Controller implements Control container.addView(to.view, 0, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT)); AndroidUtils.waitForMeasure(to.view, new AndroidUtils.OnMeasuredCallback() { @Override - public void onMeasured(View view, int width, int height) { + public void onMeasured(View view) { to.onShow(); doTransition(false, from, to, controllerTransition); @@ -158,7 +158,7 @@ public abstract class NavigationController extends Controller implements Control AndroidUtils.waitForMeasure(controller.view, new AndroidUtils.OnMeasuredCallback() { @Override - public void onMeasured(View view, int width, int height) { + public void onMeasured(View view) { onCreate(); onShow(); diff --git a/Clover/app/src/main/java/org/floens/chan/core/loader/ChanParser.java b/Clover/app/src/main/java/org/floens/chan/core/loader/ChanParser.java index c86d26c6..770807cc 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/loader/ChanParser.java +++ b/Clover/app/src/main/java/org/floens/chan/core/loader/ChanParser.java @@ -31,7 +31,7 @@ import android.text.style.TypefaceSpan; import org.floens.chan.ChanApplication; import org.floens.chan.R; -import org.floens.chan.core.preferences.ChanPreferences; +import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.core.model.Post; import org.floens.chan.core.model.PostLinkable; import org.floens.chan.utils.ThemeHelper; @@ -88,8 +88,8 @@ public class ChanParser { } private void parseSpans(Post post, TypedArray ta) { - boolean anonymize = ChanPreferences.getAnonymize(); - boolean anonymizeIds = ChanPreferences.getAnonymizeIds(); + boolean anonymize = ChanSettings.getAnonymize(); + boolean anonymizeIds = ChanSettings.getAnonymizeIds(); if (anonymize) { post.name = ChanApplication.getInstance().getString(R.string.default_name); 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 8b819ad0..bd3a8b20 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 @@ -40,7 +40,7 @@ import com.android.volley.VolleyError; import org.floens.chan.ChanApplication; import org.floens.chan.R; import org.floens.chan.chan.ChanUrls; -import org.floens.chan.core.preferences.ChanPreferences; +import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.core.loader.ChanLoader; import org.floens.chan.core.loader.LoaderPool; import org.floens.chan.core.manager.ReplyManager.DeleteListener; @@ -148,7 +148,7 @@ public class ThreadManager implements ChanLoader.ChanLoaderCallback { public boolean isWatching() { if (!chanLoader.getLoadable().isThreadMode()) { return false; - } else if (!ChanPreferences.getThreadAutoRefresh()) { + } else if (!ChanSettings.getThreadAutoRefresh()) { return false; } else if (chanLoader.getThread() != null && chanLoader.getThread().closed) { return false; @@ -249,7 +249,7 @@ public class ThreadManager implements ChanLoader.ChanLoaderCallback { menu.add(Menu.NONE, 7, Menu.NONE, activity.getString(R.string.delete)); } - if (ChanPreferences.getDeveloper()) { + if (ChanSettings.getDeveloper()) { menu.add(Menu.NONE, 8, Menu.NONE, "Make this a saved reply"); } @@ -436,7 +436,7 @@ public class ThreadManager implements ChanLoader.ChanLoaderCallback { showPostsRepliesFragment(l); } } else if (linkable.type == PostLinkable.Type.LINK) { - if (ChanPreferences.getOpenLinkConfirmation()) { + if (ChanSettings.getOpenLinkConfirmation()) { new AlertDialog.Builder(activity) .setNegativeButton(R.string.cancel, null) .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { 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 334e102a..acfe7c91 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 @@ -21,7 +21,7 @@ import android.content.Context; import android.content.Intent; import org.floens.chan.ChanApplication; -import org.floens.chan.core.preferences.ChanPreferences; +import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.core.model.Loadable; import org.floens.chan.core.model.Pin; import org.floens.chan.core.model.Post; @@ -92,7 +92,7 @@ public class WatchManager implements ChanApplication.ForegroundChangedListener { } public List getWatchingPins() { - if (ChanPreferences.getWatchEnabled()) { + if (ChanSettings.getWatchEnabled()) { List l = new ArrayList<>(); for (Pin p : pins) { @@ -242,11 +242,11 @@ public class WatchManager implements ChanApplication.ForegroundChangedListener { } public boolean getWatchBackgroundEnabled() { - return ChanPreferences.getWatchBackgroundEnabled(); + return ChanSettings.getWatchBackgroundEnabled(); } private void updatePinWatchers() { - updatePinWatchers(ChanPreferences.getWatchEnabled()); + updatePinWatchers(ChanSettings.getWatchEnabled()); } private void updatePinWatchers(boolean watchEnabled) { @@ -282,7 +282,7 @@ public class WatchManager implements ChanApplication.ForegroundChangedListener { setTimer(invokeLoadNow ? 1 : FOREGROUND_TIME); } else { if (backgroundEnabled) { - setTimer(ChanPreferences.getWatchBackgroundTimeout()); + setTimer(ChanSettings.getWatchBackgroundTimeout()); } else { if (pendingTimer != null) { pendingTimer.cancel(); diff --git a/Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java b/Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java index ec4c5aa2..75e7d9a9 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java +++ b/Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java @@ -25,7 +25,7 @@ import com.android.volley.VolleyError; import org.floens.chan.ChanApplication; import org.floens.chan.R; import org.floens.chan.chan.ChanUrls; -import org.floens.chan.core.preferences.ChanPreferences; +import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.core.loader.ChanLoader; import org.floens.chan.core.loader.LoaderPool; import org.floens.chan.core.model.ChanThread; @@ -161,7 +161,7 @@ public class ThreadPresenter implements ChanLoader.ChanLoaderCallback, PostAdapt menu.add(Menu.NONE, 7, Menu.NONE, AndroidUtils.getRes().getString(R.string.delete)); } - if (ChanPreferences.getDeveloper()) { + if (ChanSettings.getDeveloper()) { menu.add(Menu.NONE, 8, Menu.NONE, "Make this a saved reply"); } } diff --git a/Clover/app/src/main/java/org/floens/chan/core/settings/BooleanSetting.java b/Clover/app/src/main/java/org/floens/chan/core/settings/BooleanSetting.java new file mode 100644 index 00000000..782974ea --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/core/settings/BooleanSetting.java @@ -0,0 +1,19 @@ +package org.floens.chan.core.settings; + +import android.content.SharedPreferences; + +public class BooleanSetting extends Setting { + public BooleanSetting(SharedPreferences sharedPreferences, String key, boolean def) { + super(sharedPreferences, key, def); + } + + @Override + public Boolean get() { + return sharedPreferences.getBoolean(key, def); + } + + @Override + public void set(Boolean value) { + sharedPreferences.edit().putBoolean(key, value).apply(); + } +} diff --git a/Clover/app/src/main/java/org/floens/chan/core/preferences/ChanPreferences.java b/Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java similarity index 83% rename from Clover/app/src/main/java/org/floens/chan/core/preferences/ChanPreferences.java rename to Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java index 174418a4..b31fe6ec 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/preferences/ChanPreferences.java +++ b/Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.floens.chan.core.preferences; +package org.floens.chan.core.settings; import android.content.SharedPreferences; import android.os.Environment; @@ -25,14 +25,35 @@ import org.floens.chan.utils.AndroidUtils; import java.io.File; -public class ChanPreferences { - public static StringPreference defaultName; - public static StringPreference testTheme; +public class ChanSettings { + public static StringSetting theme; + public static StringSetting fontSize; + public static BooleanSetting openLinkConfirmation; + public static BooleanSetting autoRefreshThread; + public static BooleanSetting imageAutoLoad; + public static BooleanSetting videoAutoLoad; + public static BooleanSetting videoOpenExternal; + + public static StringSetting postDefaultName; + public static BooleanSetting postPinThread; + + public static BooleanSetting developer; static { SharedPreferences p = AndroidUtils.getPreferences(); - defaultName = new StringPreference(p, "preference_default_name", ""); - testTheme = new StringPreference(p, "preference_test_theme", "dark"); + + theme = new StringSetting(p, "preference_theme", "light"); + fontSize = new StringSetting(p, "preference_font", "14"); + openLinkConfirmation = new BooleanSetting(p, "preference_open_link_confirmation", true); + autoRefreshThread = new BooleanSetting(p, "preference_auto_refresh_thread", true); + imageAutoLoad = new BooleanSetting(p, "preference_image_auto_load", true); + videoAutoLoad = new BooleanSetting(p, "preference_autoplay", false); + videoOpenExternal = new BooleanSetting(p, "preference_video_external", false); + + postDefaultName = new StringSetting(p, "preference_default_name", ""); + postPinThread = new BooleanSetting(p, "preference_pin_on_post", false); + + developer = new BooleanSetting(p, "preference_developer", false); } private static SharedPreferences p() { diff --git a/Clover/app/src/main/java/org/floens/chan/core/preferences/Preference.java b/Clover/app/src/main/java/org/floens/chan/core/settings/Setting.java similarity index 62% rename from Clover/app/src/main/java/org/floens/chan/core/preferences/Preference.java rename to Clover/app/src/main/java/org/floens/chan/core/settings/Setting.java index 0aeb521c..0284a9be 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/preferences/Preference.java +++ b/Clover/app/src/main/java/org/floens/chan/core/settings/Setting.java @@ -1,13 +1,13 @@ -package org.floens.chan.core.preferences; +package org.floens.chan.core.settings; import android.content.SharedPreferences; -public abstract class Preference { +public abstract class Setting { protected final SharedPreferences sharedPreferences; protected final String key; protected final T def; - public Preference(SharedPreferences sharedPreferences, String key, T def) { + public Setting(SharedPreferences sharedPreferences, String key, T def) { this.sharedPreferences = sharedPreferences; this.key = key; this.def = def; @@ -16,4 +16,8 @@ public abstract class Preference { public abstract T get(); public abstract void set(T value); + + public T getDefault() { + return def; + } } diff --git a/Clover/app/src/main/java/org/floens/chan/core/preferences/StringPreference.java b/Clover/app/src/main/java/org/floens/chan/core/settings/StringSetting.java similarity index 62% rename from Clover/app/src/main/java/org/floens/chan/core/preferences/StringPreference.java rename to Clover/app/src/main/java/org/floens/chan/core/settings/StringSetting.java index 7532a9ff..491a1a8d 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/preferences/StringPreference.java +++ b/Clover/app/src/main/java/org/floens/chan/core/settings/StringSetting.java @@ -1,9 +1,9 @@ -package org.floens.chan.core.preferences; +package org.floens.chan.core.settings; import android.content.SharedPreferences; -public class StringPreference extends Preference { - public StringPreference(SharedPreferences sharedPreferences, String key, String def) { +public class StringSetting extends Setting { + public StringSetting(SharedPreferences sharedPreferences, String key, String def) { super(sharedPreferences, key, def); } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/AdvancedSettingsActivity.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/AdvancedSettingsActivity.java index 564301f3..3bf2cab9 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/activity/AdvancedSettingsActivity.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/activity/AdvancedSettingsActivity.java @@ -24,7 +24,7 @@ import android.preference.PreferenceFragment; import org.floens.chan.R; import org.floens.chan.chan.ChanUrls; -import org.floens.chan.core.preferences.ChanPreferences; +import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.ui.ThemeActivity; import org.floens.chan.ui.fragment.FolderPickFragment; @@ -95,13 +95,13 @@ public class AdvancedSettingsActivity extends ThemeActivity { saveLocation.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { - File dir = ChanPreferences.getImageSaveDirectory(); + File dir = ChanSettings.getImageSaveDirectory(); dir.mkdirs(); FolderPickFragment frag = FolderPickFragment.newInstance(new FolderPickFragment.FolderPickListener() { @Override public void folderPicked(File path) { - ChanPreferences.setImageSaveDirectory(path); + ChanSettings.setImageSaveDirectory(path); reloadSavePath(); } }, dir); @@ -123,7 +123,7 @@ public class AdvancedSettingsActivity extends ThemeActivity { private void reloadSavePath() { Preference saveLocation = findPreference("preference_image_save_location"); - saveLocation.setSummary(ChanPreferences.getImageSaveDirectory().getAbsolutePath()); + saveLocation.setSummary(ChanSettings.getImageSaveDirectory().getAbsolutePath()); } private void updateSummary(ListPreference list, String value) { diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/BaseActivity.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/BaseActivity.java index fb9f1e52..ce57c01b 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/activity/BaseActivity.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/activity/BaseActivity.java @@ -50,8 +50,8 @@ import org.floens.chan.core.model.ChanThread; 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.SwipeDismissListViewTouchListener; -import org.floens.chan.ui.SwipeDismissListViewTouchListener.DismissCallbacks; +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.adapter.PinnedAdapter; import org.floens.chan.utils.AndroidUtils; 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 0c58d36a..25831b7c 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 @@ -21,7 +21,6 @@ import android.app.Activity; import android.content.res.Configuration; import android.os.Bundle; -import org.floens.chan.controller.NavigationController; import org.floens.chan.ui.controller.BrowseController; import org.floens.chan.ui.controller.RootNavigationController; import org.floens.chan.utils.ThemeHelper; @@ -34,7 +33,6 @@ public class BoardActivity extends Activity { private static final String TAG = "StartActivity"; private RootNavigationController rootNavigationController; - private NavigationController navigationController; @Override protected void onCreate(Bundle savedInstanceState) { diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/BoardEditor.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/BoardEditor.java index 26091c38..20666d98 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/activity/BoardEditor.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/activity/BoardEditor.java @@ -47,10 +47,10 @@ import com.mobeta.android.dslv.DragSortListView; import org.floens.chan.ChanApplication; import org.floens.chan.R; -import org.floens.chan.core.preferences.ChanPreferences; +import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.core.manager.BoardManager; import org.floens.chan.core.model.Board; -import org.floens.chan.ui.SwipeDismissListViewTouchListener; +import org.floens.chan.ui.animation.SwipeDismissListViewTouchListener; import org.floens.chan.ui.ThemeActivity; import org.floens.chan.utils.AndroidUtils; @@ -173,7 +173,7 @@ public class BoardEditor extends ThemeActivity { public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.board_edit, menu); - menu.findItem(R.id.action_show_filler).setChecked(ChanPreferences.getBoardEditorFillerEnabled()); + menu.findItem(R.id.action_show_filler).setChecked(ChanSettings.getBoardEditorFillerEnabled()); return true; } @@ -185,8 +185,8 @@ public class BoardEditor extends ThemeActivity { showAddBoardDialog(); return true; case R.id.action_show_filler: - ChanPreferences.setBoardEditorFillerEnabled(!ChanPreferences.getBoardEditorFillerEnabled()); - item.setChecked(ChanPreferences.getBoardEditorFillerEnabled()); + ChanSettings.setBoardEditorFillerEnabled(!ChanSettings.getBoardEditorFillerEnabled()); + item.setChecked(ChanSettings.getBoardEditorFillerEnabled()); return true; case android.R.id.home: finish(); @@ -297,7 +297,7 @@ public class BoardEditor extends ThemeActivity { protected void publishResults(CharSequence constraint, FilterResults results) { filtered.clear(); - if (ChanPreferences.getBoardEditorFillerEnabled()) { + if (ChanSettings.getBoardEditorFillerEnabled()) { if (results.values != null) { filtered.addAll((List) results.values); } else { diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/ChanActivity.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/ChanActivity.java index 7a4d0bb5..2397fc2a 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/activity/ChanActivity.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/activity/ChanActivity.java @@ -43,7 +43,7 @@ import android.widget.TextView; import org.floens.chan.ChanApplication; import org.floens.chan.R; import org.floens.chan.chan.ChanUrls; -import org.floens.chan.core.preferences.ChanPreferences; +import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.core.loader.ChanLoader; import org.floens.chan.core.manager.BoardManager; import org.floens.chan.core.manager.ThreadManager; @@ -303,7 +303,7 @@ public class ChanActivity extends BaseActivity implements AdapterView.OnItemSele // Nexus 7 is 600 x 960 dp // Nexus 10 is 800 x 1280 dp - if (ChanPreferences.getForcePhoneLayout()) { + if (ChanSettings.getForcePhoneLayout()) { leftParams.width = width - dp(30); rightParams.width = width; isSlidable = true; @@ -425,9 +425,9 @@ public class ChanActivity extends BaseActivity implements AdapterView.OnItemSele setMenuItemEnabled(menu.findItem(R.id.action_board_view_mode), !slidable || open); - if (ChanPreferences.getBoardViewMode().equals("list")) { + if (ChanSettings.getBoardViewMode().equals("list")) { menu.findItem(R.id.action_board_view_mode_list).setChecked(true); - } else if (ChanPreferences.getBoardViewMode().equals("grid")) { + } else if (ChanSettings.getBoardViewMode().equals("grid")) { menu.findItem(R.id.action_board_view_mode_grid).setChecked(true); } @@ -504,15 +504,15 @@ public class ChanActivity extends BaseActivity implements AdapterView.OnItemSele return true; case R.id.action_board_view_mode_grid: - if (!ChanPreferences.getBoardViewMode().equals("grid")) { - ChanPreferences.setBoardViewMode("grid"); + if (!ChanSettings.getBoardViewMode().equals("grid")) { + ChanSettings.setBoardViewMode("grid"); setBoardFragmentViewMode(); startLoadingBoard(boardLoadable); } return true; case R.id.action_board_view_mode_list: - if (!ChanPreferences.getBoardViewMode().equals("list")) { - ChanPreferences.setBoardViewMode("list"); + if (!ChanSettings.getBoardViewMode().equals("list")) { + ChanSettings.setBoardViewMode("list"); setBoardFragmentViewMode(); startLoadingBoard(boardLoadable); } @@ -556,9 +556,9 @@ public class ChanActivity extends BaseActivity implements AdapterView.OnItemSele boardLoadable = loadable; - if (ChanPreferences.getBoardMode().equals("catalog")) { + if (ChanSettings.getBoardMode().equals("catalog")) { boardLoadable.mode = Loadable.Mode.CATALOG; - } else if (ChanPreferences.getBoardMode().equals("pages")) { + } else if (ChanSettings.getBoardMode().equals("pages")) { boardLoadable.mode = Loadable.Mode.BOARD; } @@ -667,9 +667,9 @@ public class ChanActivity extends BaseActivity implements AdapterView.OnItemSele } private void setBoardFragmentViewMode() { - if (ChanPreferences.getBoardViewMode().equals("list")) { + if (ChanSettings.getBoardViewMode().equals("list")) { boardFragment.setViewMode(ThreadManager.ViewMode.LIST); - } else if (ChanPreferences.getBoardViewMode().equals("grid")) { + } else if (ChanSettings.getBoardViewMode().equals("grid")) { boardFragment.setViewMode(ThreadManager.ViewMode.GRID); } } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/ImageViewActivity.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/ImageViewActivity.java index 4158f98e..5bc8c0c4 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/activity/ImageViewActivity.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/activity/ImageViewActivity.java @@ -29,7 +29,7 @@ import android.widget.ProgressBar; import org.floens.chan.R; import org.floens.chan.chan.ImageSearch; -import org.floens.chan.core.preferences.ChanPreferences; +import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.core.manager.ThreadManager; import org.floens.chan.core.model.Post; import org.floens.chan.ui.ThemeActivity; @@ -213,7 +213,7 @@ public class ImageViewActivity extends ThemeActivity implements ViewPager.OnPage String filename; for (Post post : adapter.getList()) { - filename = (ChanPreferences.getImageSaveOriginalFilename() ? post.tim : post.filename) + "." + post.ext; + filename = (ChanSettings.getImageSaveOriginalFilename() ? post.tim : post.filename) + "." + post.ext; list.add(new ImageSaver.DownloadPair(post.imageUrl, filename)); } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/PassSettingsActivity.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/PassSettingsActivity.java index b875d1ba..a15aa0f5 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/activity/PassSettingsActivity.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/activity/PassSettingsActivity.java @@ -37,7 +37,7 @@ import android.widget.TextView; import org.floens.chan.ChanApplication; import org.floens.chan.R; -import org.floens.chan.core.preferences.ChanPreferences; +import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.core.manager.ReplyManager; import org.floens.chan.core.manager.ReplyManager.PassResponse; import org.floens.chan.core.model.Pass; @@ -67,17 +67,17 @@ public class PassSettingsActivity extends ThemeActivity implements OnCheckedChan toggleStatus = (TextView) findViewById(R.id.toggle_status); onSwitch = (SwitchCompat) findViewById(R.id.toggle); onSwitch.setOnCheckedChangeListener(this); - setSwitch(ChanPreferences.getPassEnabled()); + setSwitch(ChanSettings.getPassEnabled()); - setFragment(ChanPreferences.getPassEnabled()); + setFragment(ChanSettings.getPassEnabled()); } @Override public void onPause() { super.onPause(); - if (TextUtils.isEmpty(ChanPreferences.getPassId())) { - ChanPreferences.setPassEnabled(false); + if (TextUtils.isEmpty(ChanSettings.getPassId())) { + ChanSettings.setPassEnabled(false); setSwitch(false); } } @@ -92,7 +92,7 @@ public class PassSettingsActivity extends ThemeActivity implements OnCheckedChan onSwitch.setChecked(enabled); toggleStatus.setText(enabled ? R.string.on : R.string.off); - ChanPreferences.setPassEnabled(enabled); + ChanSettings.setPassEnabled(enabled); } private void setFragment(boolean enabled) { @@ -137,7 +137,7 @@ public class PassSettingsActivity extends ThemeActivity implements OnCheckedChan login.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override public boolean onPreferenceClick(Preference preference) { - Pass pass = new Pass(ChanPreferences.getPassToken(), ChanPreferences.getPassPin()); + Pass pass = new Pass(ChanSettings.getPassToken(), ChanSettings.getPassPin()); onLoginClick(pass); return true; @@ -148,11 +148,11 @@ public class PassSettingsActivity extends ThemeActivity implements OnCheckedChan } private void updateLoginButton() { - findPreference("preference_pass_login").setTitle(TextUtils.isEmpty(ChanPreferences.getPassId()) ? R.string.pass_login : R.string.pass_logout); + findPreference("preference_pass_login").setTitle(TextUtils.isEmpty(ChanSettings.getPassId()) ? R.string.pass_login : R.string.pass_logout); } private void onLoginClick(Pass pass) { - if (TextUtils.isEmpty(ChanPreferences.getPassId())) { + if (TextUtils.isEmpty(ChanSettings.getPassId())) { // Login final ProgressDialog dialog = ProgressDialog.show(getActivity(), null, "Logging in"); @@ -175,7 +175,7 @@ public class PassSettingsActivity extends ThemeActivity implements OnCheckedChan } else { new AlertDialog.Builder(getActivity()).setMessage(response.message) .setNeutralButton(R.string.ok, null).show(); - ChanPreferences.setPassId(response.passId); + ChanSettings.setPassId(response.passId); } updateLoginButton(); @@ -183,7 +183,7 @@ public class PassSettingsActivity extends ThemeActivity implements OnCheckedChan }); } else { // Logout - ChanPreferences.setPassId(""); + ChanSettings.setPassId(""); updateLoginButton(); } } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/WatchSettingsActivity.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/WatchSettingsActivity.java index 21c6a219..591e889b 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/activity/WatchSettingsActivity.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/activity/WatchSettingsActivity.java @@ -34,7 +34,7 @@ import android.widget.TextView; import org.floens.chan.ChanApplication; import org.floens.chan.R; -import org.floens.chan.core.preferences.ChanPreferences; +import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.ui.ThemeActivity; public class WatchSettingsActivity extends ThemeActivity implements OnCheckedChangeListener { @@ -60,9 +60,9 @@ public class WatchSettingsActivity extends ThemeActivity implements OnCheckedCha toggleStatus = (TextView) findViewById(R.id.toggle_status); watchSwitch = (SwitchCompat) findViewById(R.id.toggle); watchSwitch.setOnCheckedChangeListener(this); - setSwitch(ChanPreferences.getWatchEnabled()); + setSwitch(ChanSettings.getWatchEnabled()); - setFragment(ChanPreferences.getWatchEnabled()); + setFragment(ChanSettings.getWatchEnabled()); } @Override @@ -75,7 +75,7 @@ public class WatchSettingsActivity extends ThemeActivity implements OnCheckedCha watchSwitch.setChecked(enabled); toggleStatus.setText(enabled ? R.string.on : R.string.off); - ChanPreferences.setWatchEnabled(enabled); + ChanSettings.setWatchEnabled(enabled); } private void setFragment(boolean enabled) { diff --git a/Clover/app/src/main/java/org/floens/chan/ui/adapter/PinnedAdapter.java b/Clover/app/src/main/java/org/floens/chan/ui/adapter/PinnedAdapter.java index 054aef3c..8844c0f1 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/adapter/PinnedAdapter.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/adapter/PinnedAdapter.java @@ -32,7 +32,7 @@ import android.widget.TextView; import org.floens.chan.ChanApplication; import org.floens.chan.R; -import org.floens.chan.core.preferences.ChanPreferences; +import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.core.model.Pin; import org.floens.chan.ui.view.CustomNetworkImageView; @@ -133,11 +133,11 @@ public class PinnedAdapter extends BaseAdapter { FrameLayout timeContainer = (FrameLayout) convertView.findViewById(R.id.pin_time_container); FrameLayout countContainer = (FrameLayout) convertView.findViewById(R.id.pin_count_container); - if (ChanPreferences.getWatchEnabled()) { + if (ChanSettings.getWatchEnabled()) { countContainer.setVisibility(View.VISIBLE); TextView timeView = (TextView) convertView.findViewById(R.id.pin_time); - if (pin.watching && pin.getPinWatcher() != null && ChanPreferences.getWatchCountdownVisibleEnabled()) { + if (pin.watching && pin.getPinWatcher() != null && ChanSettings.getWatchCountdownVisibleEnabled()) { timeContainer.setVisibility(View.VISIBLE); long timeRaw = pin.getPinWatcher().getTimeUntilNextLoad(); long time = 0; diff --git a/Clover/app/src/main/java/org/floens/chan/ui/animation/HeightAnimation.java b/Clover/app/src/main/java/org/floens/chan/ui/animation/HeightAnimation.java new file mode 100644 index 00000000..4dba820c --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/ui/animation/HeightAnimation.java @@ -0,0 +1,29 @@ +package org.floens.chan.ui.animation; + +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.Transformation; + +public class HeightAnimation extends Animation { + final int startHeight; + final int targetHeight; + View view; + + public HeightAnimation(View view, int startHeight, int targetHeight, int duration) { + this.view = view; + this.startHeight = startHeight; + this.targetHeight = targetHeight; + setDuration(duration); + } + + @Override + protected void applyTransformation(float interpolatedTime, Transformation t) { + view.getLayoutParams().height = (int) (startHeight + (targetHeight - startHeight) * interpolatedTime); + view.requestLayout(); + } + + @Override + public boolean willChangeBounds() { + return true; + } +} diff --git a/Clover/app/src/main/java/org/floens/chan/ui/ScrollerRunnable.java b/Clover/app/src/main/java/org/floens/chan/ui/animation/ScrollerRunnable.java similarity index 99% rename from Clover/app/src/main/java/org/floens/chan/ui/ScrollerRunnable.java rename to Clover/app/src/main/java/org/floens/chan/ui/animation/ScrollerRunnable.java index d70e12c8..3e984f6e 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/ScrollerRunnable.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/animation/ScrollerRunnable.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.floens.chan.ui; +package org.floens.chan.ui.animation; import android.view.View; import android.view.ViewConfiguration; diff --git a/Clover/app/src/main/java/org/floens/chan/ui/SwipeDismissListViewTouchListener.java b/Clover/app/src/main/java/org/floens/chan/ui/animation/SwipeDismissListViewTouchListener.java similarity index 99% rename from Clover/app/src/main/java/org/floens/chan/ui/SwipeDismissListViewTouchListener.java rename to Clover/app/src/main/java/org/floens/chan/ui/animation/SwipeDismissListViewTouchListener.java index 987a325a..367d1e1f 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/SwipeDismissListViewTouchListener.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/animation/SwipeDismissListViewTouchListener.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.floens.chan.ui; +package org.floens.chan.ui.animation; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; diff --git a/Clover/app/src/main/java/org/floens/chan/ui/ViewFlipperAnimations.java b/Clover/app/src/main/java/org/floens/chan/ui/animation/ViewFlipperAnimations.java similarity index 98% rename from Clover/app/src/main/java/org/floens/chan/ui/ViewFlipperAnimations.java rename to Clover/app/src/main/java/org/floens/chan/ui/animation/ViewFlipperAnimations.java index 7cf949f7..54e7a0cf 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/ViewFlipperAnimations.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/animation/ViewFlipperAnimations.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package org.floens.chan.ui; +package org.floens.chan.ui.animation; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.animation.Animation; diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/AdvancedSettingsController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/AdvancedSettingsController.java new file mode 100644 index 00000000..f6842cca --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/AdvancedSettingsController.java @@ -0,0 +1,36 @@ +package org.floens.chan.ui.controller; + +import android.content.Context; +import android.widget.LinearLayout; + +import org.floens.chan.R; +import org.floens.chan.ui.preferences.LinkSettingView; +import org.floens.chan.ui.preferences.SettingsGroup; +import org.floens.chan.ui.preferences.SettingsController; + +public class AdvancedSettingsController extends SettingsController { + public AdvancedSettingsController(Context context) { + super(context); + } + + @Override + public void onCreate() { + super.onCreate(); + + navigationItem.title = string(R.string.settings_advanced_label); + + view = inflateRes(R.layout.settings_layout); + content = (LinearLayout) view.findViewById(R.id.scrollview_content); + + populatePreferences(); + + buildPreferences(); + } + + private void populatePreferences() { + SettingsGroup settings = new SettingsGroup(string(R.string.settings_advanced_label)); + settings.settingViews.add(new LinkSettingView(this, "Hallo", null, null)); + + groups.add(settings); + } +} diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/MainSettingsController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/MainSettingsController.java index dda367d5..81e3e15c 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/controller/MainSettingsController.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/MainSettingsController.java @@ -17,22 +17,37 @@ */ package org.floens.chan.ui.controller; -import android.app.AlertDialog; import android.content.Context; +import android.content.pm.PackageManager; import android.view.View; import android.widget.LinearLayout; +import android.widget.Toast; import org.floens.chan.R; -import org.floens.chan.core.preferences.ChanPreferences; -import org.floens.chan.ui.preferences.LinkPreference; -import org.floens.chan.ui.preferences.ListPreference; -import org.floens.chan.ui.preferences.PreferenceGroup; -import org.floens.chan.ui.preferences.PreferenceItem; -import org.floens.chan.ui.preferences.PreferencesController; - -public class MainSettingsController extends PreferencesController { - private ListPreference theme; - private LinkPreference link; +import org.floens.chan.core.settings.ChanSettings; +import org.floens.chan.ui.preferences.BooleanSettingView; +import org.floens.chan.ui.preferences.LinkSettingView; +import org.floens.chan.ui.preferences.ListSettingView; +import org.floens.chan.ui.preferences.SettingView; +import org.floens.chan.ui.preferences.SettingsController; +import org.floens.chan.ui.preferences.SettingsGroup; +import org.floens.chan.ui.preferences.StringSettingView; +import org.floens.chan.ui.toolbar.ToolbarMenu; +import org.floens.chan.ui.toolbar.ToolbarMenuItem; +import org.floens.chan.ui.view.FloatingMenuItem; +import org.floens.chan.utils.AndroidUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class MainSettingsController extends SettingsController implements ToolbarMenuItem.ToolbarMenuItemCallback { + private static final int ADVANCED_SETTINGS = 1; + private SettingView imageAutoLoadView; + private SettingView videoAutoLoadView; + + private int clickCount; + private SettingView developerView; public MainSettingsController(Context context) { super(context); @@ -42,9 +57,11 @@ public class MainSettingsController extends PreferencesController { public void onCreate() { super.onCreate(); - //TODO correct header colors, background, themeing - - navigationItem.title = context.getString(R.string.action_settings); + navigationItem.title = s(R.string.action_settings); + navigationItem.menu = new ToolbarMenu(context); + navigationItem.createOverflow(context, this, Arrays.asList( + new FloatingMenuItem(ADVANCED_SETTINGS, s(R.string.action_settings_advanced)) + )); view = inflateRes(R.layout.settings_layout); content = (LinearLayout) view.findViewById(R.id.scrollview_content); @@ -52,55 +69,134 @@ public class MainSettingsController extends PreferencesController { populatePreferences(); buildPreferences(); + + onPreferenceChange(imageAutoLoadView); + + if (!ChanSettings.developer.get()) { + developerView.view.getLayoutParams().height = 0; + } + } + + @Override + public void onMenuItemClicked(ToolbarMenuItem item) { + } + + @Override + public void onSubMenuItemClicked(ToolbarMenuItem parent, FloatingMenuItem item) { + if (((Integer) item.getId()) == ADVANCED_SETTINGS) { + navigationController.pushController(new AdvancedSettingsController(context)); + } } @Override - public void onPreferenceChange(PreferenceItem item) { + public void onPreferenceChange(SettingView item) { super.onPreferenceChange(item); - if (item == theme) { - link.setEnabled(((ListPreference)item).getPreference().get().equals("dark")); + if (item == imageAutoLoadView) { + videoAutoLoadView.setEnabled(ChanSettings.imageAutoLoad.get()); } } private void populatePreferences() { - PreferenceGroup settings = new PreferenceGroup("Settings"); + // General group + SettingsGroup general = new SettingsGroup(s(R.string.settings_group_general)); + general.add(new LinkSettingView(this, s(R.string.settings_board_edit), null, new View.OnClickListener() { + @Override + public void onClick(View v) { + + } + })); - ListPreference.Item[] themeItems = new ListPreference.Item[2]; - themeItems[0] = new ListPreference.Item<>("Light", "light"); - themeItems[1] = new ListPreference.Item<>("Dark", "dark"); - theme = new ListPreference(this, ChanPreferences.testTheme, "Theme", themeItems); - settings.preferenceItems.add(theme); + general.add(new LinkSettingView(this, s(R.string.settings_watch), null, new View.OnClickListener() { + @Override + public void onClick(View v) { -// BooleanPreference bool = new BooleanPreference(p, "A name", "akey", false); -// settings.preferenceItems.add(bool); + } + })); - link = new LinkPreference(this, "A link", new View.OnClickListener() { + general.add(new LinkSettingView(this, s(R.string.settings_pass), null, new View.OnClickListener() { + @Override public void onClick(View v) { - new AlertDialog.Builder(context).setMessage("click").setPositiveButton(R.string.ok, null).show(); + } - }); - settings.preferenceItems.add(link); - - groups.add(settings); - - /*PreferenceGroup posting = new PreferenceGroup("Posting"); - - ListPreference.Item[] postItems = new ListPreference.Item[4]; - postItems[0] = new ListPreference.Item<>("Top", "one"); - postItems[1] = new ListPreference.Item<>("Top", "two"); - postItems[2] = new ListPreference.Item<>("Top", "three"); - postItems[3] = new ListPreference.Item<>("Top", "four"); - posting.preferenceItems.add(new ListPreference(p, "Something", "something", postItems)); - posting.preferenceItems.add(new ListPreference(p, "Something", "something", postItems)); - posting.preferenceItems.add(new ListPreference(p, "Something", "something", postItems)); - posting.preferenceItems.add(new ListPreference(p, "Something", "something", postItems)); - posting.preferenceItems.add(new ListPreference(p, "Something", "something", postItems)); - posting.preferenceItems.add(new ListPreference(p, "Something", "something", postItems)); - posting.preferenceItems.add(new ListPreference(p, "Something", "something", postItems)); - posting.preferenceItems.add(new ListPreference(p, "Something", "something", postItems)); - posting.preferenceItems.add(new ListPreference(p, "Something", "something", postItems)); - - groups.add(posting);*/ + })); + + groups.add(general); + + // Browsing group + SettingsGroup browsing = new SettingsGroup(s(R.string.settings_group_browsing)); + + browsing.add(new ListSettingView(this, ChanSettings.theme, s(R.string.setting_theme), new ListSettingView.Item[]{ + new ListSettingView.Item<>(s(R.string.setting_theme_light), "light"), + new ListSettingView.Item<>(s(R.string.setting_theme_dark), "dark"), + new ListSettingView.Item<>(s(R.string.setting_theme_black), "black") + })); + + List fontSizes = new ArrayList<>(); + for (int size = 10; size <= 19; size++) { + String name = size + (String.valueOf(size).equals(ChanSettings.fontSize.getDefault()) ? " " + s(R.string.setting_font_size_default) : ""); + fontSizes.add(new ListSettingView.Item<>(name, String.valueOf(size))); + } + + browsing.add(new ListSettingView(this, ChanSettings.fontSize, s(R.string.setting_font_size), fontSizes.toArray(new ListSettingView.Item[fontSizes.size()]))); + + browsing.add(new BooleanSettingView(this, ChanSettings.openLinkConfirmation, s(R.string.setting_open_link_confirmation), null)); + browsing.add(new BooleanSettingView(this, ChanSettings.autoRefreshThread, s(R.string.setting_auto_refresh_thread), null)); + imageAutoLoadView = browsing.add(new BooleanSettingView(this, ChanSettings.imageAutoLoad, s(R.string.setting_image_auto_load), null)); + videoAutoLoadView = browsing.add(new BooleanSettingView(this, ChanSettings.videoAutoLoad, s(R.string.setting_video_auto_load), null)); + browsing.add(new BooleanSettingView(this, ChanSettings.videoOpenExternal, s(R.string.setting_video_open_external), s(R.string.setting_video_open_external_description))); + + groups.add(browsing); + + // Posting group + SettingsGroup posting = new SettingsGroup(s(R.string.settings_group_posting)); + posting.add(new StringSettingView(this, ChanSettings.postDefaultName, s(R.string.setting_post_default_name), s(R.string.setting_post_default_name))); + posting.add(new BooleanSettingView(this, ChanSettings.postPinThread, s(R.string.setting_post_pin), null)); + + groups.add(posting); + + // About group + SettingsGroup about = new SettingsGroup(s(R.string.settings_group_about)); + about.add(new LinkSettingView(this, s(R.string.settings_about_licenses), s(R.string.settings_about_licences_description), new View.OnClickListener() { + @Override + public void onClick(View v) { + + } + })); + + String version = ""; + try { + version = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName; + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + + about.add(new LinkSettingView(this, s(R.string.app_name), version, new View.OnClickListener() { + @Override + public void onClick(View v) { + if ((++clickCount) % 5 == 0) { + boolean developer = !ChanSettings.developer.get(); + + ChanSettings.developer.set(developer); + + Toast.makeText(context, (developer ? "Enabled" : "Disabled") + " developer options", Toast.LENGTH_LONG).show(); + + AndroidUtils.animateHeight(developerView.view, developer); + } + } + })); + + developerView = about.add(new LinkSettingView(this, s(R.string.settings_developer), null, new View.OnClickListener() { + @Override + public void onClick(View v) { + + } + })); + + groups.add(about); + } + + private String s(int id) { + return string(id); } } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/RootNavigationController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/RootNavigationController.java index 5ec7517b..ac6297f0 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/controller/RootNavigationController.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/RootNavigationController.java @@ -53,7 +53,7 @@ public class RootNavigationController extends NavigationController { AndroidUtils.waitForLayout(drawer, new AndroidUtils.OnMeasuredCallback() { @Override - public void onMeasured(View view, int width, int height) { + public void onMeasured(View view) { setDrawerWidth(); } }); diff --git a/Clover/app/src/main/java/org/floens/chan/ui/fragment/ImageViewFragment.java b/Clover/app/src/main/java/org/floens/chan/ui/fragment/ImageViewFragment.java index 7193c68a..e6062136 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/fragment/ImageViewFragment.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/fragment/ImageViewFragment.java @@ -36,7 +36,7 @@ import android.widget.VideoView; import org.floens.chan.R; import org.floens.chan.chan.ImageSearch; -import org.floens.chan.core.preferences.ChanPreferences; +import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.core.model.Post; import org.floens.chan.ui.activity.ImageViewActivity; import org.floens.chan.ui.adapter.ImageViewAdapter; @@ -114,7 +114,7 @@ public class ImageViewFragment extends Fragment implements ThumbnailImageViewCal imageView.setThumbnail(post.thumbnailUrl); - if (ChanPreferences.getImageAutoLoad() && !post.spoiler) { + if (ChanSettings.getImageAutoLoad() && !post.spoiler) { load(); } else { tapToLoad = true; @@ -187,7 +187,7 @@ public class ImageViewFragment extends Fragment implements ThumbnailImageViewCal activity.invalidateActionBar(); - if (isVideo && ChanPreferences.getVideoAutoPlay() && imageView != null) { + if (isVideo && ChanSettings.getVideoAutoPlay() && imageView != null) { if (!videoVisible) { startVideo(); } else { @@ -244,11 +244,11 @@ public class ImageViewFragment extends Fragment implements ThumbnailImageViewCal break; case R.id.action_image_save: case R.id.action_share: - if (ChanPreferences.getImageShareUrl()) { + if (ChanSettings.getImageShareUrl()) { shareImageUrl(post.imageUrl); } else { ImageSaver.getInstance().saveImage(context, post.imageUrl, - ChanPreferences.getImageSaveOriginalFilename() ? Long.toString(post.tim) : post.filename, post.ext, + ChanSettings.getImageSaveOriginalFilename() ? Long.toString(post.tim) : post.filename, post.ext, item.getItemId() == R.id.action_share); } break; @@ -273,7 +273,7 @@ public class ImageViewFragment extends Fragment implements ThumbnailImageViewCal } public void onVideoError(File video) { - if (ChanPreferences.getVideoErrorIgnore()) { + if (ChanSettings.getVideoErrorIgnore()) { Toast.makeText(context, R.string.image_open_failed, Toast.LENGTH_SHORT).show(); } else { showVideoWarning(); @@ -303,7 +303,7 @@ public class ImageViewFragment extends Fragment implements ThumbnailImageViewCal @Override public void onClick(DialogInterface dialog, int which) { if (dontShowAgain.isChecked()) { - ChanPreferences.setVideoErrorIgnore(true); + ChanSettings.setVideoErrorIgnore(true); } } }) diff --git a/Clover/app/src/main/java/org/floens/chan/ui/fragment/PostRepliesFragment.java b/Clover/app/src/main/java/org/floens/chan/ui/fragment/PostRepliesFragment.java index 811eedfd..71579f11 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/fragment/PostRepliesFragment.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/fragment/PostRepliesFragment.java @@ -30,7 +30,7 @@ import android.widget.ListView; import android.widget.TextView; import org.floens.chan.R; -import org.floens.chan.core.preferences.ChanPreferences; +import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.core.model.Post; import org.floens.chan.core.presenter.ThreadPresenter; import org.floens.chan.ui.helper.PostPopupHelper; @@ -82,7 +82,7 @@ public class PostRepliesFragment extends DialogFragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup unused, Bundle savedInstanceState) { View container; - if (ChanPreferences.getReplyButtonsBottom()) { + if (ChanSettings.getReplyButtonsBottom()) { container = inflater.inflate(R.layout.post_replies_bottombuttons, null); } else { container = inflater.inflate(R.layout.post_replies, null); 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 bad66450..9ff07d64 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 @@ -53,13 +53,13 @@ import com.android.volley.toolbox.StringRequest; import org.floens.chan.ChanApplication; import org.floens.chan.R; import org.floens.chan.chan.ChanUrls; -import org.floens.chan.core.preferences.ChanPreferences; +import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.core.manager.ReplyManager; import org.floens.chan.core.manager.ReplyManager.ReplyResponse; import org.floens.chan.core.model.Board; import org.floens.chan.core.model.Loadable; import org.floens.chan.core.model.Reply; -import org.floens.chan.ui.ViewFlipperAnimations; +import org.floens.chan.ui.animation.ViewFlipperAnimations; import org.floens.chan.ui.view.LoadView; import org.floens.chan.utils.AndroidUtils; import org.floens.chan.utils.ImageDecoder; @@ -164,7 +164,7 @@ public class ReplyFragment extends DialogFragment { Reply draft = ChanApplication.getReplyManager().getReplyDraft(); if (TextUtils.isEmpty(draft.name)) { - draft.name = ChanPreferences.getDefaultName(); + draft.name = ChanSettings.getDefaultName(); } nameView.setText(draft.name); @@ -275,7 +275,7 @@ public class ReplyFragment extends DialogFragment { }); captchaInput = (TextView) container.findViewById(R.id.reply_captcha); - if (ChanPreferences.getPassEnabled()) { + if (ChanSettings.getPassEnabled()) { ((TextView) container.findViewById(R.id.reply_captcha_text)).setText(R.string.pass_using); container.findViewById(R.id.reply_captcha_container).setVisibility(View.GONE); container.findViewById(R.id.reply_captcha).setVisibility(View.GONE); @@ -590,9 +590,9 @@ public class ReplyFragment extends DialogFragment { draft.resto = loadable.isThreadMode() ? loadable.no : -1; draft.board = loadable.board; - if (ChanPreferences.getPassEnabled()) { + if (ChanSettings.getPassEnabled()) { draft.usePass = true; - draft.passId = ChanPreferences.getPassId(); + draft.passId = ChanSettings.getPassId(); } Board b = ChanApplication.getBoardManager().getBoardByValue(loadable.board); @@ -630,7 +630,7 @@ public class ReplyFragment extends DialogFragment { Toast.makeText(context, R.string.reply_success, Toast.LENGTH_SHORT).show(); // Pin thread on successful post - if (ChanPreferences.getPinOnPost() && loadable.isThreadMode()) { + if (ChanSettings.getPinOnPost() && loadable.isThreadMode()) { ChanApplication.getWatchManager().addPin(loadable); } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/fragment/SettingsFragment.java b/Clover/app/src/main/java/org/floens/chan/ui/fragment/SettingsFragment.java index 4844a2b1..c4fe510c 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/fragment/SettingsFragment.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/fragment/SettingsFragment.java @@ -30,7 +30,7 @@ import android.widget.ListView; import android.widget.Toast; import org.floens.chan.R; -import org.floens.chan.core.preferences.ChanPreferences; +import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.ui.activity.AboutActivity; import org.floens.chan.ui.activity.BaseActivity; import org.floens.chan.ui.activity.SettingsActivity; @@ -68,8 +68,8 @@ public class SettingsFragment extends PreferenceFragment { if (++clickCount >= 5) { clickCount = 0; - boolean enabled = !ChanPreferences.getDeveloper(); - ChanPreferences.setDeveloper(enabled); + boolean enabled = !ChanSettings.getDeveloper(); + ChanSettings.setDeveloper(enabled); updateDeveloperPreference(); Toast.makeText(getActivity(), (enabled ? "Enabled " : "Disabled ") + "developer options", @@ -158,13 +158,13 @@ public class SettingsFragment extends PreferenceFragment { final Preference watchPreference = findPreference("watch_settings"); if (watchPreference != null) { - watchPreference.setSummary(ChanPreferences.getWatchEnabled() ? R.string.watch_summary_enabled + watchPreference.setSummary(ChanSettings.getWatchEnabled() ? R.string.watch_summary_enabled : R.string.watch_summary_disabled); } final Preference passPreference = findPreference("pass_settings"); if (passPreference != null) { - passPreference.setSummary(ChanPreferences.getPassEnabled() ? R.string.pass_summary_enabled + passPreference.setSummary(ChanSettings.getPassEnabled() ? R.string.pass_summary_enabled : R.string.pass_summary_disabled); } } @@ -174,7 +174,7 @@ public class SettingsFragment extends PreferenceFragment { } private void updateDeveloperPreference() { - if (ChanPreferences.getDeveloper()) { + if (ChanSettings.getDeveloper()) { ((PreferenceGroup) findPreference("group_about")).addPreference(developerPreference); } else { ((PreferenceGroup) findPreference("group_about")).removePreference(developerPreference); 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 18fa5d63..b7dfc283 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 @@ -44,7 +44,7 @@ import com.android.volley.ServerError; import com.android.volley.VolleyError; import org.floens.chan.R; -import org.floens.chan.core.preferences.ChanPreferences; +import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.core.loader.ChanLoader; import org.floens.chan.core.loader.EndOfLineException; import org.floens.chan.core.manager.ThreadManager; @@ -219,7 +219,7 @@ public class ThreadFragment extends Fragment implements ThreadManager.ThreadMana String filename; for (Post post : imagePosts) { - filename = (ChanPreferences.getImageSaveOriginalFilename() ? post.tim : post.filename) + "." + post.ext; + filename = (ChanSettings.getImageSaveOriginalFilename() ? post.tim : post.filename) + "." + post.ext; list.add(new ImageSaver.DownloadPair(post.imageUrl, filename)); } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java b/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java index 0e700d92..d4309db3 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/layout/ThreadLayout.java @@ -28,7 +28,7 @@ import android.widget.Toast; import com.android.volley.VolleyError; import org.floens.chan.R; -import org.floens.chan.core.preferences.ChanPreferences; +import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.core.model.ChanThread; import org.floens.chan.core.model.Loadable; import org.floens.chan.core.model.Post; @@ -135,7 +135,7 @@ public class ThreadLayout extends LoadView implements ThreadPresenter.ThreadPres @Override public void openLink(final String link) { - if (ChanPreferences.getOpenLinkConfirmation()) { + if (ChanSettings.getOpenLinkConfirmation()) { new AlertDialog.Builder(getContext()) .setNegativeButton(R.string.cancel, null) .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { diff --git a/Clover/app/src/main/java/org/floens/chan/ui/preferences/BooleanPreference.java b/Clover/app/src/main/java/org/floens/chan/ui/preferences/BooleanPreference.java deleted file mode 100644 index b14cedca..00000000 --- a/Clover/app/src/main/java/org/floens/chan/ui/preferences/BooleanPreference.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.floens.chan.ui.preferences; - -import android.support.v7.widget.SwitchCompat; -import android.view.View; -import android.widget.CompoundButton; - -import org.floens.chan.R; -import org.floens.chan.core.preferences.Preference; - -public class BooleanPreference extends PreferenceItem implements View.OnClickListener, CompoundButton.OnCheckedChangeListener { - private SwitchCompat switcher; - private Preference preference; - - public BooleanPreference(PreferencesController preferencesController, Preference preference, String name) { - super(preferencesController, name); - this.preference = preference; - } - - @Override - public void setView(View view) { - super.setView(view); - - view.setOnClickListener(this); - - switcher = (SwitchCompat) view.findViewById(R.id.switcher); - switcher.setOnCheckedChangeListener(this); - - switcher.setChecked(preference.get()); - } - - @Override - public void onClick(View v) { - switcher.toggle(); - } - - @Override - public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - preference.set(isChecked); - } -} diff --git a/Clover/app/src/main/java/org/floens/chan/ui/preferences/BooleanSettingView.java b/Clover/app/src/main/java/org/floens/chan/ui/preferences/BooleanSettingView.java new file mode 100644 index 00000000..0b6ca737 --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/ui/preferences/BooleanSettingView.java @@ -0,0 +1,64 @@ +package org.floens.chan.ui.preferences; + +import android.support.v7.widget.SwitchCompat; +import android.view.View; +import android.widget.CompoundButton; + +import org.floens.chan.R; +import org.floens.chan.core.settings.Setting; + +public class BooleanSettingView extends SettingView implements View.OnClickListener, CompoundButton.OnCheckedChangeListener { + private SwitchCompat switcher; + private Setting setting; + private String description; + private boolean building = true; + + public BooleanSettingView(SettingsController settingsController, Setting setting, String name, String description) { + super(settingsController, name); + this.setting = setting; + this.description = description; + } + + @Override + public void setView(View view) { + super.setView(view); + + view.setOnClickListener(this); + + switcher = (SwitchCompat) view.findViewById(R.id.switcher); + switcher.setOnCheckedChangeListener(this); + + switcher.setChecked(setting.get()); + + building = false; + } + + @Override + public String getBottomDescription() { + return description; + } + + @Override + public void setEnabled(boolean enabled) { + view.setEnabled(enabled); + view.findViewById(R.id.top).setEnabled(enabled); + View bottom = view.findViewById(R.id.bottom); + if (bottom != null) { + bottom.setEnabled(enabled); + } + switcher.setEnabled(enabled); + } + + @Override + public void onClick(View v) { + switcher.toggle(); + } + + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if (!building) { + setting.set(isChecked); + settingsController.onPreferenceChange(this); + } + } +} diff --git a/Clover/app/src/main/java/org/floens/chan/ui/preferences/LinkPreference.java b/Clover/app/src/main/java/org/floens/chan/ui/preferences/LinkPreference.java deleted file mode 100644 index 5ff48d5a..00000000 --- a/Clover/app/src/main/java/org/floens/chan/ui/preferences/LinkPreference.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.floens.chan.ui.preferences; - -import android.view.View; - -public class LinkPreference extends PreferenceItem { - private final View.OnClickListener clickListener; - - public LinkPreference(PreferencesController preferencesController, String name, View.OnClickListener clickListener) { - super(preferencesController, name); - this.clickListener = clickListener; - } - - @Override - public void setView(View view) { - super.setView(view); - view.setOnClickListener(clickListener); - } - - @Override - public void setEnabled(boolean enabled) { - - } -} diff --git a/Clover/app/src/main/java/org/floens/chan/ui/preferences/LinkSettingView.java b/Clover/app/src/main/java/org/floens/chan/ui/preferences/LinkSettingView.java new file mode 100644 index 00000000..0599d5de --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/ui/preferences/LinkSettingView.java @@ -0,0 +1,37 @@ +package org.floens.chan.ui.preferences; + +import android.view.View; + +import org.floens.chan.R; + +public class LinkSettingView extends SettingView { + private final View.OnClickListener clickListener; + private final String description; + + public LinkSettingView(SettingsController settingsController, String name, String description, View.OnClickListener clickListener) { + super(settingsController, name); + this.description = description; + this.clickListener = clickListener; + } + + @Override + public void setView(View view) { + super.setView(view); + view.setOnClickListener(clickListener); + } + + @Override + public String getBottomDescription() { + return description; + } + + @Override + public void setEnabled(boolean enabled) { + view.setEnabled(enabled); + view.findViewById(R.id.top).setEnabled(enabled); + View bottom = view.findViewById(R.id.bottom); + if (bottom != null) { + bottom.setEnabled(enabled); + } + } +} diff --git a/Clover/app/src/main/java/org/floens/chan/ui/preferences/ListPreference.java b/Clover/app/src/main/java/org/floens/chan/ui/preferences/ListSettingView.java similarity index 65% rename from Clover/app/src/main/java/org/floens/chan/ui/preferences/ListPreference.java rename to Clover/app/src/main/java/org/floens/chan/ui/preferences/ListSettingView.java index 166a3796..e4c85611 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/preferences/ListPreference.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/preferences/ListSettingView.java @@ -3,7 +3,8 @@ package org.floens.chan.ui.preferences; import android.view.Gravity; import android.view.View; -import org.floens.chan.core.preferences.Preference; +import org.floens.chan.R; +import org.floens.chan.core.settings.Setting; import org.floens.chan.ui.view.FloatingMenu; import org.floens.chan.ui.view.FloatingMenuItem; @@ -12,16 +13,16 @@ import java.util.List; import static org.floens.chan.utils.AndroidUtils.dp; -public class ListPreference extends PreferenceItem implements FloatingMenu.FloatingMenuCallback, View.OnClickListener { +public class ListSettingView extends SettingView implements FloatingMenu.FloatingMenuCallback, View.OnClickListener { public final Item[] items; - private Preference preference; + private Setting setting; private int selected; - public ListPreference(PreferencesController preferencesController, Preference preference, String name, Item[] items) { - super(preferencesController, name); - this.preference = preference; + public ListSettingView(SettingsController settingsController, Setting setting, String name, Item[] items) { + super(settingsController, name); + this.setting = setting; this.items = items; selectItem(); @@ -31,8 +32,8 @@ public class ListPreference extends PreferenceItem implements FloatingMenu.Float return items[selected].name; } - public Preference getPreference() { - return preference; + public Setting getSetting() { + return setting; } @Override @@ -41,6 +42,16 @@ public class ListPreference extends PreferenceItem implements FloatingMenu.Float view.setOnClickListener(this); } + @Override + public void setEnabled(boolean enabled) { + view.setEnabled(enabled); + view.findViewById(R.id.top).setEnabled(enabled); + View bottom = view.findViewById(R.id.bottom); + if (bottom != null) { + bottom.setEnabled(enabled); + } + } + @Override public void onClick(View v) { List menuItems = new ArrayList<>(2); @@ -60,13 +71,13 @@ public class ListPreference extends PreferenceItem implements FloatingMenu.Float @Override public void onFloatingMenuItemClicked(FloatingMenu menu, FloatingMenuItem item) { String selectedKey = (String) item.getId(); - preference.set(selectedKey); + setting.set(selectedKey); selectItem(); - preferencesController.onPreferenceChange(this); + settingsController.onPreferenceChange(this); } private void selectItem() { - String selectedKey = preference.get(); + String selectedKey = setting.get(); for (int i = 0; i < items.length; i++) { if (items[i].key.equals(selectedKey)) { selected = i; diff --git a/Clover/app/src/main/java/org/floens/chan/ui/preferences/PreferenceGroup.java b/Clover/app/src/main/java/org/floens/chan/ui/preferences/PreferenceGroup.java deleted file mode 100644 index c94c8bb0..00000000 --- a/Clover/app/src/main/java/org/floens/chan/ui/preferences/PreferenceGroup.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.floens.chan.ui.preferences; - -import java.util.ArrayList; -import java.util.List; - -public class PreferenceGroup { - public final String name; - - public PreferenceGroup(String name) { - this.name = name; - } - - public List preferenceItems = new ArrayList<>(); -} diff --git a/Clover/app/src/main/java/org/floens/chan/ui/preferences/PreferenceItem.java b/Clover/app/src/main/java/org/floens/chan/ui/preferences/SettingView.java similarity index 63% rename from Clover/app/src/main/java/org/floens/chan/ui/preferences/PreferenceItem.java rename to Clover/app/src/main/java/org/floens/chan/ui/preferences/SettingView.java index bcd1ae20..e04a3e67 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/preferences/PreferenceItem.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/preferences/SettingView.java @@ -2,13 +2,13 @@ package org.floens.chan.ui.preferences; import android.view.View; -public abstract class PreferenceItem { - public PreferencesController preferencesController; +public abstract class SettingView { + public SettingsController settingsController; public final String name; public View view; - public PreferenceItem(PreferencesController preferencesController, String name) { - this.preferencesController = preferencesController; + public SettingView(SettingsController settingsController, String name) { + this.settingsController = settingsController; this.name = name; } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/preferences/PreferencesController.java b/Clover/app/src/main/java/org/floens/chan/ui/preferences/SettingsController.java similarity index 57% rename from Clover/app/src/main/java/org/floens/chan/ui/preferences/PreferencesController.java rename to Clover/app/src/main/java/org/floens/chan/ui/preferences/SettingsController.java index 348a5446..597097b6 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/preferences/PreferencesController.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/preferences/SettingsController.java @@ -5,6 +5,7 @@ import android.content.res.Configuration; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.animation.Animation; import android.widget.LinearLayout; import android.widget.TextView; @@ -17,17 +18,14 @@ import java.util.List; import static org.floens.chan.utils.AndroidUtils.dp; -public class PreferencesController extends Controller implements AndroidUtils.OnMeasuredCallback { +public class SettingsController extends Controller implements AndroidUtils.OnMeasuredCallback { protected LinearLayout content; - protected List groups = new ArrayList<>(); + protected List groups = new ArrayList<>(); - public PreferencesController(Context context) { - super(context); - } + private boolean built = false; - @Override - public void onCreate() { - super.onCreate(); + public SettingsController(Context context) { + super(context); } @Override @@ -44,12 +42,12 @@ public class PreferencesController extends Controller implements AndroidUtils.On } @Override - public void onMeasured(View view, int width, int height) { + public void onMeasured(View view) { setMargins(); } - public void onPreferenceChange(PreferenceItem item) { - if (item instanceof ListPreference) { + public void onPreferenceChange(SettingView item) { + if ((item instanceof ListSettingView) || (item instanceof StringSettingView)) { setDescriptionText(item.view, item.getTopDescription(), item.getBottomDescription()); } } @@ -84,8 +82,8 @@ public class PreferencesController extends Controller implements AndroidUtils.On protected void buildPreferences() { LayoutInflater inf = LayoutInflater.from(context); boolean firstGroup = true; - for (PreferenceGroup group : groups) { - LinearLayout groupLayout = (LinearLayout) inf.inflate(R.layout.preference_group, content, false); + for (SettingsGroup group : groups) { + LinearLayout groupLayout = (LinearLayout) inf.inflate(R.layout.setting_group, content, false); ((TextView) groupLayout.findViewById(R.id.header)).setText(group.name); if (firstGroup) { @@ -95,42 +93,63 @@ public class PreferencesController extends Controller implements AndroidUtils.On content.addView(groupLayout); - for (int i = 0; i < group.preferenceItems.size(); i++) { - PreferenceItem preferenceItem = group.preferenceItems.get(i); + for (int i = 0; i < group.settingViews.size(); i++) { + SettingView settingView = group.settingViews.get(i); ViewGroup preferenceView = null; - String topValue = preferenceItem.getTopDescription(); - String bottomValue = preferenceItem.getBottomDescription(); + String topValue = settingView.getTopDescription(); + String bottomValue = settingView.getBottomDescription(); - if ((preferenceItem instanceof ListPreference) || (preferenceItem instanceof LinkPreference)) { - preferenceView = (ViewGroup) inf.inflate(R.layout.preference_link, groupLayout, false); - } else if (preferenceItem instanceof BooleanPreference) { - preferenceView = (ViewGroup) inf.inflate(R.layout.preference_boolean, groupLayout, false); + if ((settingView instanceof ListSettingView) || (settingView instanceof LinkSettingView) || (settingView instanceof StringSettingView)) { + preferenceView = (ViewGroup) inf.inflate(R.layout.setting_link, groupLayout, false); + } else if (settingView instanceof BooleanSettingView) { + preferenceView = (ViewGroup) inf.inflate(R.layout.setting_boolean, groupLayout, false); } setDescriptionText(preferenceView, topValue, bottomValue); groupLayout.addView(preferenceView); - preferenceItem.setView(preferenceView); + settingView.setView(preferenceView); - if (i < group.preferenceItems.size() - 1) { - inf.inflate(R.layout.preference_divider, groupLayout, true); + if (i < group.settingViews.size() - 1) { + inf.inflate(R.layout.setting_divider, groupLayout, true); } } } + + built = true; } private void setDescriptionText(View view, String topText, String bottomText) { ((TextView) view.findViewById(R.id.top)).setText(topText); - TextView bottom = ((TextView) view.findViewById(R.id.bottom)); + final TextView bottom = ((TextView) view.findViewById(R.id.bottom)); if (bottom != null) { - if (bottomText == null) { - ViewGroup parent = (ViewGroup) bottom.getParent(); - parent.removeView(bottom); + if (built) { + if (bottomText != null) { + bottom.setText(bottomText); + } + + AndroidUtils.animateHeight(bottom, bottomText != null); + + bottom.getAnimation().setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + bottom.setVisibility(View.VISIBLE); + } + + @Override + public void onAnimationEnd(Animation animation) { + } + + @Override + public void onAnimationRepeat(Animation animation) { + } + }); } else { bottom.setText(bottomText); + bottom.setVisibility(bottomText == null ? View.GONE : View.VISIBLE); } } } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/preferences/SettingsGroup.java b/Clover/app/src/main/java/org/floens/chan/ui/preferences/SettingsGroup.java new file mode 100644 index 00000000..fb13d04f --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/ui/preferences/SettingsGroup.java @@ -0,0 +1,18 @@ +package org.floens.chan.ui.preferences; + +import java.util.ArrayList; +import java.util.List; + +public class SettingsGroup { + public final String name; + public final List settingViews = new ArrayList<>(); + + public SettingsGroup(String name) { + this.name = name; + } + + public SettingView add(SettingView settingView) { + settingViews.add(settingView); + return settingView; + } +} diff --git a/Clover/app/src/main/java/org/floens/chan/ui/preferences/StringSettingView.java b/Clover/app/src/main/java/org/floens/chan/ui/preferences/StringSettingView.java new file mode 100644 index 00000000..40a65980 --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/ui/preferences/StringSettingView.java @@ -0,0 +1,64 @@ +package org.floens.chan.ui.preferences; + +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.view.View; +import android.view.WindowManager; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; +import android.widget.LinearLayout; + +import org.floens.chan.R; +import org.floens.chan.core.settings.Setting; + +import static org.floens.chan.utils.AndroidUtils.dp; + +public class StringSettingView extends SettingView implements View.OnClickListener { + private final Setting setting; + private final String dialogTitle; + + public StringSettingView(SettingsController settingsController, Setting setting, String name, String dialogTitle) { + super(settingsController, name); + this.setting = setting; + this.dialogTitle = dialogTitle; + } + + @Override + public void setView(View view) { + super.setView(view); + view.setOnClickListener(this); + } + + @Override + public String getBottomDescription() { + return setting.get().length() > 0 ? setting.get() : null; + } + + @Override + public void onClick(View v) { + LinearLayout container = new LinearLayout(v.getContext()); + container.setPadding(dp(24), dp(8), dp(24), 0); + + final EditText editText = new EditText(v.getContext()); + editText.setImeOptions(EditorInfo.IME_FLAG_NO_FULLSCREEN); + editText.setText(setting.get()); + editText.setSingleLine(true); + + container.addView(editText, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); + + AlertDialog dialog = new AlertDialog.Builder(v.getContext()) + .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface d, int which) { + setting.set(editText.getText().toString()); + settingsController.onPreferenceChange(StringSettingView.this); + } + }) + .setNegativeButton(R.string.cancel, null) + .setTitle(dialogTitle) + .setView(container) + .create(); + dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); + dialog.show(); + } +} diff --git a/Clover/app/src/main/java/org/floens/chan/ui/service/WatchNotifier.java b/Clover/app/src/main/java/org/floens/chan/ui/service/WatchNotifier.java index 41b60526..0f10e6ea 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/service/WatchNotifier.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/service/WatchNotifier.java @@ -28,7 +28,7 @@ import android.support.v4.app.NotificationCompat; import org.floens.chan.ChanApplication; import org.floens.chan.R; -import org.floens.chan.core.preferences.ChanPreferences; +import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.core.manager.WatchManager; import org.floens.chan.core.model.Pin; import org.floens.chan.core.model.Post; @@ -90,8 +90,8 @@ public class WatchNotifier extends Service { } private Notification createNotification() { - boolean notifyQuotesOnly = ChanPreferences.getWatchNotifyMode().equals("quotes"); - boolean soundQuotesOnly = ChanPreferences.getWatchSound().equals("quotes"); + boolean notifyQuotesOnly = ChanSettings.getWatchNotifyMode().equals("quotes"); + boolean soundQuotesOnly = ChanSettings.getWatchSound().equals("quotes"); List list = new ArrayList<>(); List listQuoting = new ArrayList<>(); @@ -229,7 +229,7 @@ public class WatchNotifier extends Service { } if (light) { - long watchLed = ChanPreferences.getWatchLed(); + long watchLed = ChanSettings.getWatchLed(); if (watchLed >= 0) { builder.setLights((int) watchLed, 1000, 1000); } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/toolbar/NavigationItem.java b/Clover/app/src/main/java/org/floens/chan/ui/toolbar/NavigationItem.java index 790699da..951fe2d6 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/toolbar/NavigationItem.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/toolbar/NavigationItem.java @@ -17,9 +17,13 @@ */ package org.floens.chan.ui.toolbar; +import android.content.Context; import android.widget.LinearLayout; import org.floens.chan.ui.view.FloatingMenu; +import org.floens.chan.ui.view.FloatingMenuItem; + +import java.util.List; public class NavigationItem { public String title = ""; @@ -27,4 +31,11 @@ public class NavigationItem { public boolean hasBack = true; public LinearLayout view; public FloatingMenu middleMenu; + + public FloatingMenu createOverflow(Context context, ToolbarMenuItem.ToolbarMenuItemCallback callback, List items) { + ToolbarMenuItem overflow = menu.createOverflow(callback); + FloatingMenu overflowMenu = new FloatingMenu(context, overflow.getView(), items); + overflow.setSubMenu(overflowMenu); + return overflowMenu; + } } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/toolbar/Toolbar.java b/Clover/app/src/main/java/org/floens/chan/ui/toolbar/Toolbar.java index d9a9fb55..b2731114 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/toolbar/Toolbar.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/toolbar/Toolbar.java @@ -79,7 +79,7 @@ public class Toolbar extends LinearLayout implements View.OnClickListener { if (item.menu != null) { AndroidUtils.waitForMeasure(this, new AndroidUtils.OnMeasuredCallback() { @Override - public void onMeasured(View view, int width, int height) { + public void onMeasured(View view) { setNavigationItemView(animate, pushing, item); } }); @@ -246,7 +246,7 @@ public class Toolbar extends LinearLayout implements View.OnClickListener { AndroidUtils.waitForMeasure(titleView, new AndroidUtils.OnMeasuredCallback() { @Override - public void onMeasured(View view, int width, int height) { + public void onMeasured(View view) { if (item.middleMenu != null) { item.middleMenu.setPopupWidth(Math.max(dp(150), titleView.getWidth())); } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/toolbar/ToolbarMenu.java b/Clover/app/src/main/java/org/floens/chan/ui/toolbar/ToolbarMenu.java index 529113fc..2817f24b 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/toolbar/ToolbarMenu.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/toolbar/ToolbarMenu.java @@ -51,18 +51,6 @@ public class ToolbarMenu extends LinearLayout { private void init() { setOrientation(HORIZONTAL); setGravity(Gravity.CENTER_VERTICAL); - -// overflowItem = new ToolbarMenuItem(getContext(), this, 100, R.drawable.ic_more_vert_white_24dp, 10 + 32); -// -// List subItems = new ArrayList<>(); -// subItems.add(new ToolbarMenuItemSubMenu.SubItem(1, "Sub 1")); -// subItems.add(new ToolbarMenuItemSubMenu.SubItem(2, "Sub 2")); -// subItems.add(new ToolbarMenuItemSubMenu.SubItem(3, "Sub 3")); -// -// ToolbarMenuItemSubMenu sub = new ToolbarMenuItemSubMenu(getContext(), overflowItem.getView(), subItems); -// overflowItem.setSubMenu(sub); -// -// addItem(overflowItem); } public ToolbarMenuItem addItem(ToolbarMenuItem item) { @@ -78,10 +66,8 @@ public class ToolbarMenu extends LinearLayout { public ToolbarMenuItem createOverflow(ToolbarMenuItem.ToolbarMenuItemCallback callback) { ToolbarMenuItem overflow = addItem(new ToolbarMenuItem(getContext(), callback, 100, R.drawable.ic_more)); ImageView overflowImage = overflow.getView(); - // 36dp overflowImage.setLayoutParams(new LinearLayout.LayoutParams(dp(36), dp(54))); - int p = dp(16); - overflowImage.setPadding(0, 0, p, 0); + overflowImage.setPadding(0, 0, dp(16), 0); return overflow; } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/toolbar/ToolbarMenuItem.java b/Clover/app/src/main/java/org/floens/chan/ui/toolbar/ToolbarMenuItem.java index a6f2fef4..073a5435 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/toolbar/ToolbarMenuItem.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/toolbar/ToolbarMenuItem.java @@ -72,13 +72,9 @@ public class ToolbarMenuItem implements View.OnClickListener, FloatingMenu.Float subMenu.setCallback(this); } - public void showSubMenu() { - subMenu.show(); - } - @Override public void onClick(View v) { - if (subMenu != null) { + if (subMenu != null && !subMenu.isShowing()) { subMenu.show(); } callback.onMenuItemClicked(this); diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/FloatingMenu.java b/Clover/app/src/main/java/org/floens/chan/ui/view/FloatingMenu.java index e1984948..deae2da1 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/view/FloatingMenu.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/view/FloatingMenu.java @@ -32,6 +32,7 @@ import android.widget.TextView; import org.floens.chan.R; import org.floens.chan.utils.AndroidUtils; +import org.floens.chan.utils.Logger; import java.util.ArrayList; import java.util.List; @@ -147,9 +148,13 @@ public class FloatingMenu { globalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { - if (popupWindow.isShowing()) { - // Recalculate anchor position - popupWindow.show(); + if (popupWindow == null) { + Logger.w("FloatingMenu", "popupWindow null in layout listener"); + } else { + if (popupWindow.isShowing()) { + // Recalculate anchor position + popupWindow.show(); + } } } }; @@ -170,6 +175,10 @@ public class FloatingMenu { popupWindow.setSelection(selectedPosition); } + public boolean isShowing() { + return popupWindow != null && popupWindow.isShowing(); + } + public interface FloatingMenuCallback { public void onFloatingMenuItemClicked(FloatingMenu menu, FloatingMenuItem item); } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/ThumbnailImageView.java b/Clover/app/src/main/java/org/floens/chan/ui/view/ThumbnailImageView.java index 5fe88f62..93a66723 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/view/ThumbnailImageView.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/view/ThumbnailImageView.java @@ -37,7 +37,7 @@ import com.koushikdutta.async.future.Future; import org.floens.chan.ChanApplication; import org.floens.chan.R; -import org.floens.chan.core.preferences.ChanPreferences; +import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.utils.AndroidUtils; import org.floens.chan.utils.FileCache; import org.floens.chan.utils.Logger; @@ -257,7 +257,7 @@ public class ThumbnailImageView extends LoadView implements View.OnClickListener } public void setVideoFile(final File file) { - if (ChanPreferences.getVideoExternal()) { + if (ChanSettings.getVideoExternal()) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(file), "video/*"); diff --git a/Clover/app/src/main/java/org/floens/chan/utils/AndroidUtils.java b/Clover/app/src/main/java/org/floens/chan/utils/AndroidUtils.java index cf6afef0..36d4c84b 100644 --- a/Clover/app/src/main/java/org/floens/chan/utils/AndroidUtils.java +++ b/Clover/app/src/main/java/org/floens/chan/utils/AndroidUtils.java @@ -39,6 +39,7 @@ import android.widget.Toast; import org.floens.chan.ChanApplication; import org.floens.chan.R; +import org.floens.chan.ui.animation.HeightAnimation; import java.util.ArrayList; import java.util.HashMap; @@ -166,7 +167,7 @@ public class AndroidUtils { } public interface OnMeasuredCallback { - void onMeasured(View view, int width, int height); + void onMeasured(View view); } /** @@ -187,7 +188,7 @@ public class AndroidUtils { int height = view.getHeight(); if (returnIfZero && width > 0 && height > 0) { - callback.onMeasured(view, width, height); + callback.onMeasured(view); } else { view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override @@ -198,7 +199,7 @@ public class AndroidUtils { } try { - callback.onMeasured(view, view.getWidth(), view.getHeight()); + callback.onMeasured(view); } catch (Exception e) { Log.i("AndroidUtils", "Exception in onMeasured", e); } @@ -234,4 +235,22 @@ public class AndroidUtils { return views; } + + public static void animateHeight(View view, boolean expand) { + if ((view.getHeight() > 0 && expand) || (view.getHeight() == 0 && !expand)) { + return; + } + + view.clearAnimation(); + HeightAnimation heightAnimation; + if (expand) { + view.measure( + View.MeasureSpec.makeMeasureSpec(view.getWidth(), View.MeasureSpec.EXACTLY), + View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); + heightAnimation = new HeightAnimation(view, 0, view.getMeasuredHeight(), 300); + } else { + heightAnimation = new HeightAnimation(view, view.getHeight(), 0, 300); + } + view.startAnimation(heightAnimation); + } } diff --git a/Clover/app/src/main/java/org/floens/chan/utils/ImageSaver.java b/Clover/app/src/main/java/org/floens/chan/utils/ImageSaver.java index b23876e5..704c0fbc 100644 --- a/Clover/app/src/main/java/org/floens/chan/utils/ImageSaver.java +++ b/Clover/app/src/main/java/org/floens/chan/utils/ImageSaver.java @@ -32,7 +32,7 @@ import com.koushikdutta.async.future.Future; import org.floens.chan.ChanApplication; import org.floens.chan.R; -import org.floens.chan.core.preferences.ChanPreferences; +import org.floens.chan.core.settings.ChanSettings; import java.io.File; import java.io.FileInputStream; @@ -55,7 +55,7 @@ public class ImageSaver { private BroadcastReceiver receiver; public void saveAll(final Context context, String folderName, final List list) { - final File subFolder = new File(ChanPreferences.getImageSaveDirectory() + File.separator + filterName(folderName)); + final File subFolder = new File(ChanSettings.getImageSaveDirectory() + File.separator + filterName(folderName)); String text = context.getString(R.string.download_confirm, Integer.toString(list.size()), subFolder.getAbsolutePath()); @@ -99,7 +99,7 @@ public class ImageSaver { new Thread(new Runnable() { @Override public void run() { - File saveDir = ChanPreferences.getImageSaveDirectory(); + File saveDir = ChanSettings.getImageSaveDirectory(); if (!saveDir.isDirectory() && !saveDir.mkdirs()) { showToast(context, context.getString(R.string.image_save_directory_error)); diff --git a/Clover/app/src/main/java/org/floens/chan/utils/ThemeHelper.java b/Clover/app/src/main/java/org/floens/chan/utils/ThemeHelper.java index fd235b2c..d91a7f99 100644 --- a/Clover/app/src/main/java/org/floens/chan/utils/ThemeHelper.java +++ b/Clover/app/src/main/java/org/floens/chan/utils/ThemeHelper.java @@ -22,7 +22,7 @@ import android.content.Context; import android.content.res.TypedArray; import org.floens.chan.R; -import org.floens.chan.core.preferences.ChanPreferences; +import org.floens.chan.core.settings.ChanSettings; public class ThemeHelper { public enum Theme { @@ -67,7 +67,7 @@ public class ThemeHelper { } public Theme getTheme() { - String themeName = ChanPreferences.getTheme(); + String themeName = ChanSettings.getTheme(); Theme theme = null; switch (themeName) { @@ -98,7 +98,7 @@ public class ThemeHelper { spoilerColor = ta.getColor(R.styleable.PostView_spoiler_color, 0); inlineQuoteColor = ta.getColor(R.styleable.PostView_inline_quote_color, 0); codeTagSize = ta.getDimensionPixelSize(R.styleable.PostView_code_tag_size, 0); - fontSize = ChanPreferences.getFontSize(); + fontSize = ChanSettings.getFontSize(); ta.recycle(); } diff --git a/Clover/app/src/main/res/drawable/preference_description_bottom.xml b/Clover/app/src/main/res/drawable/preference_description_bottom.xml new file mode 100644 index 00000000..856fffa2 --- /dev/null +++ b/Clover/app/src/main/res/drawable/preference_description_bottom.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/Clover/app/src/main/res/drawable/preference_description_top.xml b/Clover/app/src/main/res/drawable/preference_description_top.xml new file mode 100644 index 00000000..1944ff95 --- /dev/null +++ b/Clover/app/src/main/res/drawable/preference_description_top.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/Clover/app/src/main/res/layout/preference_boolean.xml b/Clover/app/src/main/res/layout/setting_boolean.xml similarity index 93% rename from Clover/app/src/main/res/layout/preference_boolean.xml rename to Clover/app/src/main/res/layout/setting_boolean.xml index b88c6fda..74f482f9 100644 --- a/Clover/app/src/main/res/layout/preference_boolean.xml +++ b/Clover/app/src/main/res/layout/setting_boolean.xml @@ -15,7 +15,7 @@ android:layout_weight="1" android:orientation="vertical"> - + diff --git a/Clover/app/src/main/res/layout/preference_description.xml b/Clover/app/src/main/res/layout/setting_description.xml similarity index 84% rename from Clover/app/src/main/res/layout/preference_description.xml rename to Clover/app/src/main/res/layout/setting_description.xml index fa01af11..072897b6 100644 --- a/Clover/app/src/main/res/layout/preference_description.xml +++ b/Clover/app/src/main/res/layout/setting_description.xml @@ -8,7 +8,7 @@ android:paddingLeft="16dp" android:paddingRight="16dp" android:singleLine="true" - android:textColor="#ff000000" + android:textColor="@drawable/preference_description_top" android:textSize="16sp" /> diff --git a/Clover/app/src/main/res/layout/preference_divider.xml b/Clover/app/src/main/res/layout/setting_divider.xml similarity index 100% rename from Clover/app/src/main/res/layout/preference_divider.xml rename to Clover/app/src/main/res/layout/setting_divider.xml diff --git a/Clover/app/src/main/res/layout/preference_group.xml b/Clover/app/src/main/res/layout/setting_group.xml similarity index 98% rename from Clover/app/src/main/res/layout/preference_group.xml rename to Clover/app/src/main/res/layout/setting_group.xml index d2cfc65e..0416e7b7 100644 --- a/Clover/app/src/main/res/layout/preference_group.xml +++ b/Clover/app/src/main/res/layout/setting_group.xml @@ -22,4 +22,4 @@ android:textSize="16sp" android:textColor="#89000000" /> - \ No newline at end of file + diff --git a/Clover/app/src/main/res/layout/preference_link.xml b/Clover/app/src/main/res/layout/setting_link.xml similarity index 87% rename from Clover/app/src/main/res/layout/preference_link.xml rename to Clover/app/src/main/res/layout/setting_link.xml index 4345bb5d..6bb5f6b4 100644 --- a/Clover/app/src/main/res/layout/preference_link.xml +++ b/Clover/app/src/main/res/layout/setting_link.xml @@ -8,6 +8,6 @@ android:paddingTop="16dp" android:paddingBottom="16dp"> - + diff --git a/Clover/app/src/main/res/layout/settings_layout.xml b/Clover/app/src/main/res/layout/settings_layout.xml index 42aba26d..d8df1c86 100644 --- a/Clover/app/src/main/res/layout/settings_layout.xml +++ b/Clover/app/src/main/res/layout/settings_layout.xml @@ -23,7 +23,7 @@ along with this program. If not, see . diff --git a/Clover/app/src/main/res/values/strings.xml b/Clover/app/src/main/res/values/strings.xml index dc0816aa..08d67dac 100644 --- a/Clover/app/src/main/res/values/strings.xml +++ b/Clover/app/src/main/res/values/strings.xml @@ -152,6 +152,35 @@ along with this program. If not, see . Choose + General + Edit boards + Thread watcher settings + 4chan pass settings + + Browsing + Theme + Light + Dark + Black + Font size + (default) + Ask before opening links + Auto refresh threads + Auto load images + Auto load videos + Open videos external + Open videos in an external media player + + Posting + Default post name + Pin thread on post + + About + Open Source Licenses + Legal information about licenses + Developer settings + + Edit boards Add or remove boards Thread watcher