From 404720292a9c186da6decce6fa5dc72d3033dccc Mon Sep 17 00:00:00 2001 From: Floens Date: Thu, 12 Mar 2015 00:37:45 +0100 Subject: [PATCH] Some watch & pass settings --- .../chan/controller/NavigationController.java | 9 ++ .../chan/core/settings/ChanSettings.java | 70 ++++---- .../ui/controller/MainSettingsController.java | 27 +++- .../ui/controller/PassSettingsController.java | 153 ++++++++++++++++++ .../controller/WatchSettingsController.java | 65 +++++--- .../chan/ui/preferences/SettingView.java | 1 + .../ui/preferences/SettingsController.java | 18 ++- .../chan/ui/toolbar/NavigationItem.java | 2 + .../org/floens/chan/ui/toolbar/Toolbar.java | 5 + .../floens/chan/ui/view/CrossfadeView.java | 87 ++++++++++ .../org/floens/chan/utils/AndroidUtils.java | 47 +----- .../org/floens/chan/utils/AnimationUtils.java | 56 +++++++ .../app/src/main/res/layout/settings_pass.xml | 84 ++++++++++ .../src/main/res/layout/settings_watch.xml | 24 +++ .../app/src/main/res/layout/toolbar_menu.xml | 2 + Clover/app/src/main/res/values/strings.xml | 22 ++- 16 files changed, 573 insertions(+), 99 deletions(-) create mode 100644 Clover/app/src/main/java/org/floens/chan/ui/controller/PassSettingsController.java create mode 100644 Clover/app/src/main/java/org/floens/chan/ui/view/CrossfadeView.java create mode 100644 Clover/app/src/main/res/layout/settings_pass.xml create mode 100644 Clover/app/src/main/res/layout/settings_watch.xml 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 e9b3a156..1d506e68 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 @@ -104,6 +104,15 @@ public abstract class NavigationController extends Controller implements Control return true; } + public Controller getPreviousSibling(Controller controller) { + int index = controllerList.indexOf(controller); + if (index > 0) { + return controllerList.get(index - 1); + } else { + return null; + } + } + @Override public void onControllerTransitionCompleted() { if (controllerTransition instanceof PushControllerTransition) { diff --git a/Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java b/Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java index ae33fc53..56a0ff94 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java +++ b/Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java @@ -26,34 +26,39 @@ import org.floens.chan.utils.AndroidUtils; import java.io.File; 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; - - public static StringSetting saveLocation; - public static BooleanSetting saveOriginalFilename; - public static BooleanSetting shareUrl; - public static BooleanSetting networkHttps; - public static BooleanSetting forcePhoneLayout; - public static BooleanSetting anonymize; - public static BooleanSetting anonymizeIds; - public static BooleanSetting repliesButtonsBottom; - - public static BooleanSetting watchCountdown; - public static BooleanSetting watchBackground; - public static StringSetting watchBackgroundTimeout; - public static StringSetting watchNotifyMode; - public static StringSetting watchSound; - public static StringSetting watchLed; + public static final StringSetting theme; + public static final StringSetting fontSize; + public static final BooleanSetting openLinkConfirmation; + public static final BooleanSetting autoRefreshThread; + public static final BooleanSetting imageAutoLoad; + public static final BooleanSetting videoAutoLoad; + public static final BooleanSetting videoOpenExternal; + + public static final StringSetting postDefaultName; + public static final BooleanSetting postPinThread; + + public static final BooleanSetting developer; + + public static final StringSetting saveLocation; + public static final BooleanSetting saveOriginalFilename; + public static final BooleanSetting shareUrl; + public static final BooleanSetting networkHttps; + public static final BooleanSetting forcePhoneLayout; + public static final BooleanSetting anonymize; + public static final BooleanSetting anonymizeIds; + public static final BooleanSetting repliesButtonsBottom; + + public static final BooleanSetting watchEnabled; + public static final BooleanSetting watchCountdown; + public static final BooleanSetting watchBackground; + public static final StringSetting watchBackgroundTimeout; + public static final StringSetting watchNotifyMode; + public static final StringSetting watchSound; + public static final StringSetting watchLed; + + public static final StringSetting passToken; + public static final StringSetting passPin; + public static final StringSetting passId; static { SharedPreferences p = AndroidUtils.getPreferences(); @@ -80,18 +85,27 @@ public class ChanSettings { anonymizeIds = new BooleanSetting(p, "preference_anonymize_ids", false); repliesButtonsBottom = new BooleanSetting(p, "preference_buttons_bottom", false); + watchEnabled = new BooleanSetting(p, "preference_watch_enabled", false); watchCountdown = new BooleanSetting(p, "preference_watch_countdown", false); watchBackground = new BooleanSetting(p, "preference_watch_background_enabled", false); watchBackgroundTimeout = new StringSetting(p, "preference_watch_background_timeout", "60"); watchNotifyMode = new StringSetting(p, "preference_watch_notify_mode", "all"); watchSound = new StringSetting(p, "preference_watch_sound", "all"); watchLed = new StringSetting(p, "preference_watch_led", "ffffffff"); + + passToken = new StringSetting(p, "preference_pass_token", ""); + passPin = new StringSetting(p, "preference_pass_pin", ""); + passId = new StringSetting(p, "preference_pass_id", ""); } private static SharedPreferences p() { return AndroidUtils.getPreferences(); } + public static boolean passLoggedIn() { + return passId.get().length() > 0; + } + public static boolean getOpenLinkConfirmation() { return p().getBoolean("preference_open_link_confirmation", true); } 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 379fe548..2211a4a5 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 @@ -35,17 +35,19 @@ 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 org.floens.chan.utils.AnimationUtils; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -public class MainSettingsController extends SettingsController implements ToolbarMenuItem.ToolbarMenuItemCallback { +public class MainSettingsController extends SettingsController implements ToolbarMenuItem.ToolbarMenuItemCallback, WatchSettingsController.WatchSettingControllerListener, PassSettingsController.PassSettingControllerListener { private static final int ADVANCED_SETTINGS = 1; private SettingView imageAutoLoadView; private SettingView videoAutoLoadView; + private LinkSettingView watchLink; + private LinkSettingView passLink; private int clickCount; private SettingView developerView; @@ -68,6 +70,9 @@ public class MainSettingsController extends SettingsController implements Toolba populatePreferences(); + onWatchEnabledChanged(ChanSettings.watchEnabled.get()); + onPassEnabledChanged(ChanSettings.passLoggedIn()); + buildPreferences(); onPreferenceChange(imageAutoLoadView); @@ -97,6 +102,16 @@ public class MainSettingsController extends SettingsController implements Toolba } } + @Override + public void onWatchEnabledChanged(boolean enabled) { + watchLink.setDescription(s(enabled ? R.string.setting_watch_summary_enabled : R.string.setting_watch_summary_disabled)); + } + + @Override + public void onPassEnabledChanged(boolean enabled) { + passLink.setDescription(s(enabled ? R.string.setting_pass_summary_enabled : R.string.setting_pass_summary_disabled)); + } + private void populatePreferences() { // General group SettingsGroup general = new SettingsGroup(s(R.string.settings_group_general)); @@ -107,17 +122,17 @@ public class MainSettingsController extends SettingsController implements Toolba } })); - general.add(new LinkSettingView(this, s(R.string.settings_watch), null, new View.OnClickListener() { + watchLink = (LinkSettingView) general.add(new LinkSettingView(this, s(R.string.settings_watch), null, new View.OnClickListener() { @Override public void onClick(View v) { navigationController.pushController(new WatchSettingsController(context)); } })); - general.add(new LinkSettingView(this, s(R.string.settings_pass), null, new View.OnClickListener() { + passLink = (LinkSettingView) general.add(new LinkSettingView(this, s(R.string.settings_pass), null, new View.OnClickListener() { @Override public void onClick(View v) { - + navigationController.pushController(new PassSettingsController(context)); } })); @@ -181,7 +196,7 @@ public class MainSettingsController extends SettingsController implements Toolba Toast.makeText(context, (developer ? "Enabled" : "Disabled") + " developer options", Toast.LENGTH_LONG).show(); - AndroidUtils.animateHeight(developerView.view, developer); + AnimationUtils.animateHeight(developerView.view, developer); } } })); diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/PassSettingsController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/PassSettingsController.java new file mode 100644 index 00000000..ba6ea305 --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/PassSettingsController.java @@ -0,0 +1,153 @@ +package org.floens.chan.ui.controller; + +import android.app.AlertDialog; +import android.content.Context; +import android.text.Html; +import android.text.method.LinkMovementMethod; +import android.view.View; +import android.webkit.WebSettings; +import android.webkit.WebView; +import android.widget.Button; +import android.widget.EditText; +import android.widget.LinearLayout; +import android.widget.TextView; + +import org.floens.chan.ChanApplication; +import org.floens.chan.R; +import org.floens.chan.controller.Controller; +import org.floens.chan.core.manager.ReplyManager; +import org.floens.chan.core.model.Pass; +import org.floens.chan.core.settings.ChanSettings; +import org.floens.chan.ui.view.CrossfadeView; +import org.floens.chan.utils.AndroidUtils; +import org.floens.chan.utils.AnimationUtils; + +public class PassSettingsController extends Controller implements View.OnClickListener { + private LinearLayout container; + private CrossfadeView crossfadeView; + private TextView errors; + private Button button; + private TextView bottomDescription; + private EditText inputToken; + private EditText inputPin; + private TextView authenticated; + + public PassSettingsController(Context context) { + super(context); + } + + @Override + public void onCreate() { + super.onCreate(); + + navigationItem.title = string(R.string.settings_screen_pass); + + view = inflateRes(R.layout.settings_pass); + container = (LinearLayout) view.findViewById(R.id.container); + crossfadeView = (CrossfadeView) view.findViewById(R.id.crossfade); + errors = (TextView) view.findViewById(R.id.errors); + button = (Button) view.findViewById(R.id.button); + bottomDescription = (TextView) view.findViewById(R.id.bottom_description); + inputToken = (EditText) view.findViewById(R.id.input_token); + inputPin = (EditText) view.findViewById(R.id.input_pin); + authenticated = (TextView) view.findViewById(R.id.authenticated); + + AnimationUtils.setHeight(errors, false, false); + + final boolean loggedIn = loggedIn(); + button.setText(loggedIn ? R.string.setting_pass_logout : R.string.setting_pass_login); + button.setOnClickListener(this); + + bottomDescription.setText(Html.fromHtml(string(R.string.setting_pass_bottom_description))); + bottomDescription.setMovementMethod(LinkMovementMethod.getInstance()); + + inputToken.setText(ChanSettings.passToken.get()); + inputPin.setText(ChanSettings.passPin.get()); + + AndroidUtils.waitForLayout(view, new AndroidUtils.OnMeasuredCallback() { + @Override + public void onMeasured(View view) { + crossfadeView.getLayoutParams().height = crossfadeView.getHeight(); + crossfadeView.requestLayout(); + crossfadeView.toggle(!loggedIn, false); + } + }); + } + + @Override + public void onClick(View v) { + if (v == button) { + if (loggedIn()) { + ChanSettings.passId.set(""); + crossfadeView.toggle(true, true); + button.setText(R.string.setting_pass_login); + hideError(); + ((PassSettingControllerListener) navigationController.getPreviousSibling(PassSettingsController.this)).onPassEnabledChanged(false); + } else { + auth(); + } + } + } + + private void auth() { + AndroidUtils.hideKeyboard(view); + inputToken.setEnabled(false); + inputPin.setEnabled(false); + button.setEnabled(false); + button.setText(R.string.setting_pass_logging_in); + hideError(); + + ChanSettings.passToken.set(inputToken.getText().toString()); + ChanSettings.passPin.set(inputPin.getText().toString()); + + ChanApplication.getReplyManager().sendPass(new Pass(ChanSettings.passToken.get(), ChanSettings.passPin.get()), new ReplyManager.PassListener() { + @Override + public void onResponse(ReplyManager.PassResponse response) { + if (response.isError) { + if (response.unknownError) { + WebView webView = new WebView(context); + WebSettings settings = webView.getSettings(); + settings.setSupportZoom(true); + webView.loadData(response.responseData, "text/html", null); + + new AlertDialog.Builder(context) + .setView(webView) + .setNeutralButton(R.string.ok, null) + .show(); + } else { + showError(response.message); + } + button.setText(R.string.setting_pass_login); + } else { + crossfadeView.toggle(false, true); + button.setText(R.string.setting_pass_logout); + ChanSettings.passId.set(response.passId); + authenticated.setText(response.message); + ((PassSettingControllerListener) navigationController.getPreviousSibling(PassSettingsController.this)).onPassEnabledChanged(true); + } + + button.setEnabled(true); + inputToken.setEnabled(true); + inputPin.setEnabled(true); + } + }); + } + + private void showError(String error) { + errors.setText(error); + AnimationUtils.setHeight(errors, true, true, container.getWidth()); + } + + private void hideError() { + errors.setText(null); + AnimationUtils.setHeight(errors, false, true, container.getHeight()); + } + + private boolean loggedIn() { + return ChanSettings.passId.get().length() > 0; + } + + public interface PassSettingControllerListener { + public void onPassEnabledChanged(boolean enabled); + } +} diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/WatchSettingsController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/WatchSettingsController.java index 27580a9f..1fd36e74 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/controller/WatchSettingsController.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/WatchSettingsController.java @@ -1,7 +1,8 @@ package org.floens.chan.ui.controller; import android.content.Context; -import android.view.View; +import android.support.v7.widget.SwitchCompat; +import android.widget.CompoundButton; import android.widget.LinearLayout; import org.floens.chan.R; @@ -11,33 +12,58 @@ 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.utils.AndroidUtils; +import org.floens.chan.ui.view.CrossfadeView; -public class WatchSettingsController extends SettingsController { - public WatchSettingsController(Context context) { - super(context); - } +public class WatchSettingsController extends SettingsController implements CompoundButton.OnCheckedChangeListener { + private CrossfadeView crossfadeView; private SettingView enableBackground; + private SettingView backgroundTimeout; private SettingView notifyMode; private SettingView soundMode; private SettingView ledMode; + public WatchSettingsController(Context context) { + super(context); + } + @Override public void onCreate() { super.onCreate(); - navigationItem.title = string(R.string.settings_screen_advanced); + boolean enabled = ChanSettings.watchEnabled.get(); + + navigationItem.title = string(R.string.settings_screen_watch); - view = inflateRes(R.layout.settings_layout); + view = inflateRes(R.layout.settings_watch); content = (LinearLayout) view.findViewById(R.id.scrollview_content); + crossfadeView = (CrossfadeView) view.findViewById(R.id.crossfade); + + crossfadeView.toggle(enabled, false); + + SwitchCompat globalSwitch = new SwitchCompat(context); + globalSwitch.setChecked(enabled); + globalSwitch.setOnCheckedChangeListener(this); + navigationItem.rightView = globalSwitch; populatePreferences(); buildPreferences(); - setEnabledHeights(); + if (!ChanSettings.watchBackground.get()) { + setSettingViewVisibility(backgroundTimeout, false, false); + setSettingViewVisibility(notifyMode, false, false); + setSettingViewVisibility(soundMode, false, false); + setSettingViewVisibility(ledMode, false, false); + } + } + + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + ChanSettings.watchEnabled.set(isChecked); + ((WatchSettingControllerListener) navigationController.getPreviousSibling(this)).onWatchEnabledChanged(isChecked); + crossfadeView.toggle(isChecked, true); } @Override @@ -46,19 +72,10 @@ public class WatchSettingsController extends SettingsController { if (item == enableBackground) { boolean enabled = ChanSettings.watchBackground.get(); - AndroidUtils.animateHeight(backgroundTimeout.view, enabled); - AndroidUtils.animateHeight(notifyMode.view, enabled); - AndroidUtils.animateHeight(soundMode.view, enabled); - AndroidUtils.animateHeight(ledMode.view, enabled); - } - } - - private void setEnabledHeights() { - if (!ChanSettings.watchBackground.get()) { - backgroundTimeout.view.setVisibility(View.GONE); - notifyMode.view.setVisibility(View.GONE); - soundMode.view.setVisibility(View.GONE); - ledMode.view.setVisibility(View.GONE); + setSettingViewVisibility(backgroundTimeout, enabled, true); + setSettingViewVisibility(notifyMode, enabled, true); + setSettingViewVisibility(soundMode, enabled, true); + setSettingViewVisibility(ledMode, enabled, true); } } @@ -88,4 +105,8 @@ public class WatchSettingsController extends SettingsController { groups.add(settings); } + + public interface WatchSettingControllerListener { + public void onWatchEnabledChanged(boolean enabled); + } } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/preferences/SettingView.java b/Clover/app/src/main/java/org/floens/chan/ui/preferences/SettingView.java index e04a3e67..785c27b4 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/preferences/SettingView.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/preferences/SettingView.java @@ -6,6 +6,7 @@ public abstract class SettingView { public SettingsController settingsController; public final String name; public View view; + public View divider; public SettingView(SettingsController settingsController, String name) { this.settingsController = settingsController; diff --git a/Clover/app/src/main/java/org/floens/chan/ui/preferences/SettingsController.java b/Clover/app/src/main/java/org/floens/chan/ui/preferences/SettingsController.java index 4dcdaa6e..ae64b686 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/preferences/SettingsController.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/preferences/SettingsController.java @@ -11,6 +11,7 @@ import android.widget.TextView; import org.floens.chan.R; import org.floens.chan.controller.Controller; import org.floens.chan.utils.AndroidUtils; +import org.floens.chan.utils.AnimationUtils; import java.util.ArrayList; import java.util.List; @@ -78,6 +79,18 @@ public class SettingsController extends Controller implements AndroidUtils.OnMea } } + protected void setSettingViewVisibility(SettingView settingView, boolean visible, boolean animated) { + if (animated) { + AnimationUtils.animateHeight(settingView.view, visible); + } else { + settingView.view.setVisibility(visible ? View.VISIBLE : View.GONE); + } + + if (settingView.divider != null) { + settingView.divider.setVisibility(visible ? View.VISIBLE : View.GONE); + } + } + protected void buildPreferences() { LayoutInflater inf = LayoutInflater.from(context); boolean firstGroup = true; @@ -112,7 +125,8 @@ public class SettingsController extends Controller implements AndroidUtils.OnMea settingView.setView(preferenceView); if (i < group.settingViews.size() - 1) { - inf.inflate(R.layout.setting_divider, groupLayout, true); + settingView.divider = inf.inflate(R.layout.setting_divider, groupLayout, false); + groupLayout.addView(settingView.divider); } } } @@ -130,7 +144,7 @@ public class SettingsController extends Controller implements AndroidUtils.OnMea bottom.setText(bottomText); } - AndroidUtils.animateHeight(bottom, bottomText != null); + AnimationUtils.animateHeight(bottom, bottomText != null); } else { bottom.setText(bottomText); bottom.setVisibility(bottomText == null ? View.GONE : View.VISIBLE); 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 951fe2d6..ef909ba3 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 @@ -18,6 +18,7 @@ package org.floens.chan.ui.toolbar; import android.content.Context; +import android.view.View; import android.widget.LinearLayout; import org.floens.chan.ui.view.FloatingMenu; @@ -31,6 +32,7 @@ public class NavigationItem { public boolean hasBack = true; public LinearLayout view; public FloatingMenu middleMenu; + public View rightView; public FloatingMenu createOverflow(Context context, ToolbarMenuItem.ToolbarMenuItemCallback callback, List items) { ToolbarMenuItem overflow = menu.createOverflow(callback); 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 b2731114..691e0ff6 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 @@ -244,6 +244,11 @@ public class Toolbar extends LinearLayout implements View.OnClickListener { wrapper.addView(item.menu, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT)); } + if (item.rightView != null) { + item.rightView.setPadding(0, 0, dp(16), 0); + wrapper.addView(item.rightView, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT)); + } + AndroidUtils.waitForMeasure(titleView, new AndroidUtils.OnMeasuredCallback() { @Override public void onMeasured(View view) { diff --git a/Clover/app/src/main/java/org/floens/chan/ui/view/CrossfadeView.java b/Clover/app/src/main/java/org/floens/chan/ui/view/CrossfadeView.java new file mode 100644 index 00000000..e1465362 --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/ui/view/CrossfadeView.java @@ -0,0 +1,87 @@ +package org.floens.chan.ui.view; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.FrameLayout; + +public class CrossfadeView extends FrameLayout { + private int fadeDuration = 200; + + private View viewOne; + private View viewTwo; + private boolean inited = false; + private boolean viewOneSelected = true; + + public CrossfadeView(Context context) { + super(context); + } + + public CrossfadeView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public CrossfadeView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + viewOne = getChildAt(0); + viewTwo = getChildAt(1); + } + + public void toggle(boolean viewOneSelected, boolean animated) { + if (!inited || this.viewOneSelected != viewOneSelected) { + this.viewOneSelected = viewOneSelected; + doToggle(animated); + } + } + + public void toggle(boolean animated) { + viewOneSelected = !viewOneSelected; + doToggle(animated); + } + + private void doToggle(boolean animated) { + inited = true; + if (animated) { + if (viewOneSelected) { + viewOne.setVisibility(View.VISIBLE); + viewOne.animate().alpha(1f).setDuration(fadeDuration).setListener(null); + viewTwo.animate().alpha(0f).setDuration(fadeDuration).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + viewOne.setVisibility(View.VISIBLE); + viewTwo.setVisibility(View.GONE); + } + }); + } else { + viewTwo.setVisibility(View.VISIBLE); + viewTwo.animate().alpha(1f).setDuration(fadeDuration).setListener(null); + viewOne.animate().alpha(0f).setDuration(fadeDuration).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + viewOne.setVisibility(View.GONE); + viewTwo.setVisibility(View.VISIBLE); + } + }); + } + } else { + if (viewOneSelected) { + viewOne.setVisibility(View.VISIBLE); + viewOne.setAlpha(1f); + viewTwo.setVisibility(View.GONE); + viewTwo.setAlpha(0f); + } else { + viewOne.setVisibility(View.GONE); + viewOne.setAlpha(0f); + viewTwo.setVisibility(View.VISIBLE); + viewTwo.setAlpha(1f); + } + } + } +} 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 7310f9f2..e32532c0 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 @@ -34,13 +34,11 @@ import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; -import android.view.animation.Animation; import android.view.inputmethod.InputMethodManager; 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; @@ -143,13 +141,17 @@ public class AndroidUtils { dialog.setOnShowListener(new DialogInterface.OnShowListener() { @Override public void onShow(DialogInterface dialog) { - InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService( - Context.INPUT_METHOD_SERVICE); + InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService( Context.INPUT_METHOD_SERVICE); imm.showSoftInput(view, 0); } }); } + public static void hideKeyboard(View view) { + InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); + } + public static String getReadableFileSize(int bytes, boolean si) { int unit = si ? 1000 : 1024; if (bytes < unit) @@ -184,11 +186,11 @@ public class AndroidUtils { waitForMeasure(false, view, callback); } - private static void waitForMeasure(boolean returnIfZero, final View view, final OnMeasuredCallback callback) { + private static void waitForMeasure(boolean returnIfNotZero, final View view, final OnMeasuredCallback callback) { int width = view.getWidth(); int height = view.getHeight(); - if (returnIfZero && width > 0 && height > 0) { + if (returnIfNotZero && width > 0 && height > 0) { callback.onMeasured(view); } else { view.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @@ -237,37 +239,4 @@ public class AndroidUtils { return views; } - public static void animateHeight(final View view, boolean expand) { - if (view.getAnimation() == null && ((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); - view.getAnimation().setAnimationListener(new Animation.AnimationListener() { - @Override - public void onAnimationStart(Animation animation) { - view.setVisibility(View.VISIBLE); - } - - @Override - public void onAnimationEnd(Animation animation) { - - } - - @Override - public void onAnimationRepeat(Animation animation) { - - } - }); - } } diff --git a/Clover/app/src/main/java/org/floens/chan/utils/AnimationUtils.java b/Clover/app/src/main/java/org/floens/chan/utils/AnimationUtils.java index 879bcd73..41d49fe1 100644 --- a/Clover/app/src/main/java/org/floens/chan/utils/AnimationUtils.java +++ b/Clover/app/src/main/java/org/floens/chan/utils/AnimationUtils.java @@ -20,8 +20,12 @@ package org.floens.chan.utils; import android.graphics.Matrix; import android.graphics.Point; import android.graphics.Rect; +import android.view.View; +import android.view.animation.Animation; import android.widget.ImageView; +import org.floens.chan.ui.animation.HeightAnimation; + public class AnimationUtils { /** * On your start view call startView.getGlobalVisibleRect(startBounds) @@ -65,4 +69,56 @@ public class AnimationUtils { bounds.right = (bounds.left + (int) (imageView.getDrawable().getIntrinsicWidth() * f[Matrix.MSCALE_X])); bounds.bottom = (bounds.top + (int) (imageView.getDrawable().getIntrinsicHeight() * f[Matrix.MSCALE_Y])); } + + public static void setHeight(View view, boolean expand, boolean animated) { + setHeight(view, expand, animated, -1); + } + + public static void setHeight(View view, boolean expand, boolean animated, int knownWidth) { + if (animated) { + animateHeight(view, expand, knownWidth); + } else { + view.setVisibility(expand ? View.VISIBLE : View.GONE); + } + } + + public static void animateHeight(final View view, boolean expand) { + animateHeight(view, expand, -1); + } + + public static void animateHeight(final View view, boolean expand, int knownWidth) { + if (view.getAnimation() == null && ((view.getHeight() > 0 && expand) || (view.getHeight() == 0 && !expand))) { + return; + } + + view.clearAnimation(); + HeightAnimation heightAnimation; + if (expand) { + int width = knownWidth < 0 ? view.getWidth() : knownWidth; + + view.measure( + View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY), + View.MeasureSpec.UNSPECIFIED); + heightAnimation = new HeightAnimation(view, 0, view.getMeasuredHeight(), 300); + } else { + heightAnimation = new HeightAnimation(view, view.getHeight(), 0, 300); + } + view.startAnimation(heightAnimation); + view.getAnimation().setAnimationListener(new Animation.AnimationListener() { + @Override + public void onAnimationStart(Animation animation) { + view.setVisibility(View.VISIBLE); + } + + @Override + public void onAnimationEnd(Animation animation) { + + } + + @Override + public void onAnimationRepeat(Animation animation) { + + } + }); + } } diff --git a/Clover/app/src/main/res/layout/settings_pass.xml b/Clover/app/src/main/res/layout/settings_pass.xml new file mode 100644 index 00000000..771d7627 --- /dev/null +++ b/Clover/app/src/main/res/layout/settings_pass.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + +