diff --git a/Clover/app/src/main/java/org/floens/chan/core/presenter/SitesSetupPresenter.java b/Clover/app/src/main/java/org/floens/chan/core/presenter/SitesSetupPresenter.java index c229db81..87fff628 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/presenter/SitesSetupPresenter.java +++ b/Clover/app/src/main/java/org/floens/chan/core/presenter/SitesSetupPresenter.java @@ -50,7 +50,17 @@ public class SitesSetupPresenter { this.callback.setAddedSites(sites); - this.callback.setNextAllowed(!sites.isEmpty(), false); + this.callback.setNextAllowed(!sites.isEmpty()); + + if (sites.isEmpty()) { + callback.presentIntro(); + } + } + + public void onIntroDismissed() { + if (sites.isEmpty()) { + callback.showHint(); + } } public void bindAddDialog(AddCallback addCallback) { @@ -74,6 +84,7 @@ public class SitesSetupPresenter { @Override public void onSiteAdded(Site site) { siteAdded(site); + addCallback.dismissDialog(); } @Override @@ -96,7 +107,7 @@ public class SitesSetupPresenter { callback.setAddedSites(sites); - callback.setNextAllowed(!sites.isEmpty(), true); + callback.setNextAllowed(!sites.isEmpty()); } public void onSiteCellSettingsClicked(Site site) { @@ -104,16 +115,22 @@ public class SitesSetupPresenter { } public interface Callback { + void presentIntro(); + + void showHint(); + void showAddDialog(); void setAddedSites(List sites); - void setNextAllowed(boolean nextAllowed, boolean animate); + void setNextAllowed(boolean nextAllowed); void openSiteConfiguration(Site site); } public interface AddCallback { void showAddError(String error); + + void dismissDialog(); } } diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/SiteManager.java b/Clover/app/src/main/java/org/floens/chan/core/site/SiteManager.java index 90dbba9b..245c61bc 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/SiteManager.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/SiteManager.java @@ -46,6 +46,10 @@ public class SiteManager { this.resolver = resolver; } + public boolean areSitesSetup() { + return !Sites.allSites().isEmpty(); + } + public void addSite(String url, SiteAddCallback callback) { Site existing = resolver.findSiteForUrl(url); if (existing != null) { diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/StartActivity.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/StartActivity.java index 10fa7253..2922a0dc 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/activity/StartActivity.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/activity/StartActivity.java @@ -45,12 +45,13 @@ import org.floens.chan.core.model.orm.Loadable; import org.floens.chan.core.model.orm.Pin; import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.core.site.Site; +import org.floens.chan.core.site.SiteManager; import org.floens.chan.core.site.SiteResolver; import org.floens.chan.core.site.Sites; import org.floens.chan.ui.controller.BrowseController; import org.floens.chan.ui.controller.DoubleNavigationController; import org.floens.chan.ui.controller.DrawerController; -import org.floens.chan.ui.controller.SetupController; +import org.floens.chan.ui.controller.SitesSetupController; import org.floens.chan.ui.controller.SplitNavigationController; import org.floens.chan.ui.controller.StyledToolbarNavigationController; import org.floens.chan.ui.controller.ThreadSlideController; @@ -98,6 +99,9 @@ public class StartActivity extends AppCompatActivity implements NfcAdapter.Creat @Inject SiteResolver siteResolver; + @Inject + SiteManager siteManager; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -146,11 +150,14 @@ public class StartActivity extends AppCompatActivity implements NfcAdapter.Creat // Not from a state or from an url, launch the setup controller if no boards are setup up yet, // otherwise load the default saved board. if (!handled) { - /*if (boardManager.getSavedBoards().isEmpty()) { - setupWithNoBoards(); - } else { - browseController.loadWithDefaultBoard(); - }*/ + restoreFresh(); + } + } + + private void restoreFresh() { + if (!siteManager.areSitesSetup()) { + mainNavigationController.pushController(new SitesSetupController(this), false); + } else { browseController.loadWithDefaultBoard(); } } @@ -209,10 +216,6 @@ public class StartActivity extends AppCompatActivity implements NfcAdapter.Creat return handled; } - private void setupWithNoBoards() { - mainNavigationController.presentController(new SetupController(this), false); - } - private Pair resolveChanState(ChanState state) { DatabaseLoadableManager loadableManager = databaseManager.getDatabaseLoadableManager(); diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/IntroController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/IntroController.java index 0e4be484..17bb663c 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/controller/IntroController.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/IntroController.java @@ -23,7 +23,6 @@ import android.widget.Button; import org.floens.chan.R; import org.floens.chan.controller.Controller; -import org.floens.chan.core.presenter.SetupPresenter; public class IntroController extends Controller implements View.OnClickListener { private Button start; @@ -45,8 +44,8 @@ public class IntroController extends Controller implements View.OnClickListener @Override public void onClick(View v) { if (v == start) { - SetupPresenter presenter = ((SetupController) navigationController).getPresenter(); - presenter.startClicked(); + ((SitesSetupController) presentedByController).onIntroDismissed(); + stopPresenting(); } } } 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 2b47d28e..fc7417a8 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 @@ -77,7 +77,7 @@ public class MainSettingsController extends SettingsController implements Toolba private ChanSettings.LayoutMode previousLayoutMode; - private PopupWindow advancedSettingsHint; + private HintPopup advancedSettingsHint; @Inject DatabaseManager databaseManager; diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/SitesSetupController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/SitesSetupController.java index e454a440..639206e8 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/controller/SitesSetupController.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/SitesSetupController.java @@ -36,6 +36,7 @@ import org.floens.chan.R; import org.floens.chan.core.presenter.SitesSetupPresenter; import org.floens.chan.core.site.Site; import org.floens.chan.core.site.SiteIcon; +import org.floens.chan.ui.helper.HintPopup; import org.floens.chan.ui.layout.SiteAddLayout; import org.floens.chan.ui.toolbar.ToolbarMenu; import org.floens.chan.ui.toolbar.ToolbarMenuItem; @@ -132,6 +133,22 @@ public class SitesSetupController extends StyledToolbarNavigationController impl } } + @Override + public void presentIntro() { + presentController(new IntroController(context), false); + } + + public void onIntroDismissed() { + presenter.onIntroDismissed(); + } + + @Override + public void showHint() { + String s = context.getString(R.string.setup_sites_add_hint); + HintPopup popup = new HintPopup(context, addButton, s, 0, 0, true); + popup.show(); + } + @Override public void showAddDialog() { @SuppressLint("InflateParams") final SiteAddLayout dialogView = @@ -145,7 +162,11 @@ public class SitesSetupController extends StyledToolbarNavigationController impl .setTitle(R.string.setup_sites_add_title) .setPositiveButton(R.string.add, null) .setNegativeButton(R.string.cancel, null) - .show(); + .create(); + + dialogView.setDialog(dialog); + + dialog.show(); Button positiveButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE); positiveButton.setOnClickListener((v) -> { @@ -168,10 +189,13 @@ public class SitesSetupController extends StyledToolbarNavigationController impl } @Override - public void setNextAllowed(boolean nextAllowed, boolean animate) { + public void setNextAllowed(boolean nextAllowed) { if (doneMenuItem != null) { doneMenuItem.getView().animate().alpha(nextAllowed ? 1f : 0f).start(); } + if (!nextAllowed) { + navigationItem.swipeable = false; + } } private void onSiteCellSettingsClicked(Site site) { diff --git a/Clover/app/src/main/java/org/floens/chan/ui/helper/HintPopup.java b/Clover/app/src/main/java/org/floens/chan/ui/helper/HintPopup.java index 628134d9..11691a93 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/helper/HintPopup.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/helper/HintPopup.java @@ -17,6 +17,7 @@ */ package org.floens.chan.ui.helper; +import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; @@ -28,51 +29,79 @@ import android.widget.PopupWindow; import android.widget.TextView; import org.floens.chan.R; +import org.floens.chan.utils.AndroidUtils; import static org.floens.chan.utils.AndroidUtils.dp; import static org.floens.chan.utils.AndroidUtils.getString; public class HintPopup { - public static PopupWindow show(Context context, View anchor, int text) { + public static HintPopup show(Context context, View anchor, int text) { return show(context, anchor, getString(text)); } - public static PopupWindow show(final Context context, final View anchor, final String text) { + public static HintPopup show(final Context context, final View anchor, final String text) { return show(context, anchor, text, 0, 0); } - public static PopupWindow show(final Context context, final View anchor, final String text, final int offsetX, final int offsetY) { - final LinearLayout popupView = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.popup_hint, null); + public static HintPopup show(final Context context, final View anchor, final String text, final int offsetX, final int offsetY) { + HintPopup hintPopup = new HintPopup(context, anchor, text, offsetX, offsetY, false); + hintPopup.show(); + return hintPopup; + } + + private TextView textView; + private PopupWindow popupWindow; + private LinearLayout popupView; + private final View anchor; + private String text; + private final int offsetX; + private final int offsetY; + private final boolean top; + private boolean dismissed; + + public HintPopup(Context context, final View anchor, final String text, final int offsetX, final int offsetY, final boolean top) { + this.anchor = anchor; + this.text = text; + this.offsetX = offsetX; + this.offsetY = offsetY; + this.top = top; + + createView(context); + } - TextView textView = (TextView) popupView.findViewById(R.id.text); + @SuppressLint("InflateParams") + private void createView(Context context) { + popupView = (LinearLayout) LayoutInflater.from(context) + .inflate(top ? R.layout.popup_hint_top : R.layout.popup_hint, null); + + textView = popupView.findViewById(R.id.text); textView.setText(text); - final PopupWindow popupWindow = new PopupWindow(popupView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + popupWindow = new PopupWindow(popupView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); popupWindow.setOutsideTouchable(true); popupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); - popupView.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - popupWindow.dismiss(); - } + popupView.setOnClickListener(v -> { +// popupWindow.dismiss(); }); + } - popupView.postDelayed(new Runnable() { - @Override - public void run() { + public void show() { + AndroidUtils.runOnUiThread(() -> { + if (!dismissed) { popupView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); - popupWindow.showAsDropDown(anchor, -popupView.getMeasuredWidth() + anchor.getWidth() + offsetX, -dp(25) + offsetY); + // TODO: cleanup + int xoff = -popupView.getMeasuredWidth() + anchor.getWidth() + offsetX - dp(2); + int yoff = -dp(25) + offsetY + (top ? -anchor.getHeight() - dp(30) : 0); + popupWindow.showAsDropDown(anchor, xoff, yoff); } - }, 100); + }, 400); - popupView.postDelayed(new Runnable() { - @Override - public void run() { - popupWindow.dismiss(); - } - }, 5000); + // popupView.postDelayed(popupWindow::dismiss, 5000); + } - return popupWindow; + public void dismiss() { + popupWindow.dismiss(); + dismissed = true; } } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/helper/VersionHandler.java b/Clover/app/src/main/java/org/floens/chan/ui/helper/VersionHandler.java index 4c17b1c3..6cf7027f 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/helper/VersionHandler.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/helper/VersionHandler.java @@ -92,13 +92,11 @@ public class VersionHandler implements UpdateManager.UpdateCallback { public void run() { int previous = ChanSettings.previousVersion.get(); if (previous < CURRENT_VERSION) { - if (previous < 1) { - cleanupOutdatedIonFolder(context); - } - - // Add more previous version checks here + handleUpdate(previous); - showMessage(CURRENT_VERSION); + if (previous != 0) { + showMessage(CURRENT_VERSION); + } ChanSettings.previousVersion.set(CURRENT_VERSION); @@ -111,6 +109,14 @@ public class VersionHandler implements UpdateManager.UpdateCallback { } } + private void handleUpdate(int previous) { + if (previous < 1) { + cleanupOutdatedIonFolder(context); + } + + // Add more previous version checks here + } + public boolean isUpdatingAvailable() { return updateManager.isUpdatingAvailable(); } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/layout/SiteAddLayout.java b/Clover/app/src/main/java/org/floens/chan/ui/layout/SiteAddLayout.java index 685f6c6f..dd7ccc5e 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/layout/SiteAddLayout.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/layout/SiteAddLayout.java @@ -1,5 +1,6 @@ package org.floens.chan.ui.layout; +import android.app.Dialog; import android.content.Context; import android.support.constraint.ConstraintLayout; import android.support.design.widget.TextInputLayout; @@ -12,6 +13,8 @@ import org.floens.chan.core.presenter.SitesSetupPresenter; public class SiteAddLayout extends ConstraintLayout implements SitesSetupPresenter.AddCallback { private EditText url; private TextInputLayout urlContainer; + + private Dialog dialog; private SitesSetupPresenter presenter; public SiteAddLayout(Context context) { @@ -34,6 +37,10 @@ public class SiteAddLayout extends ConstraintLayout implements SitesSetupPresent url = findViewById(R.id.url); } + public void setDialog(Dialog dialog) { + this.dialog = dialog; + } + public void setPresenter(SitesSetupPresenter presenter) { this.presenter = presenter; } @@ -58,4 +65,9 @@ public class SiteAddLayout extends ConstraintLayout implements SitesSetupPresent public void showAddError(String error) { urlContainer.setError(error); } + + @Override + public void dismissDialog() { + dialog.dismiss(); + } } diff --git a/Clover/app/src/main/res/layout/controller_intro.xml b/Clover/app/src/main/res/layout/controller_intro.xml index 6414c619..d1fa92ab 100644 --- a/Clover/app/src/main/res/layout/controller_intro.xml +++ b/Clover/app/src/main/res/layout/controller_intro.xml @@ -19,6 +19,7 @@ along with this program. If not, see . xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" + android:background="?backcolor" android:orientation="vertical"> + + + + + + + + + + + diff --git a/Clover/app/src/main/res/values/strings.xml b/Clover/app/src/main/res/values/strings.xml index 41af8b97..f941b510 100644 --- a/Clover/app/src/main/res/values/strings.xml +++ b/Clover/app/src/main/res/values/strings.xml @@ -169,6 +169,7 @@ Re-enable this permission in the app settings if you permanently disabled it."Get started Your sites + Add sites Add site Site url http://