diff --git a/Clover/app/src/main/java/org/floens/chan/core/database/DatabaseBoardManager.java b/Clover/app/src/main/java/org/floens/chan/core/database/DatabaseBoardManager.java index 4eb0c909..81260597 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/database/DatabaseBoardManager.java +++ b/Clover/app/src/main/java/org/floens/chan/core/database/DatabaseBoardManager.java @@ -89,7 +89,7 @@ public class DatabaseBoardManager { }; } - public Callable createAll(final Site site, final List boards) { + public Callable createAll(final Site site, final List boards) { return () -> { long start = Time.startTiming(); @@ -146,7 +146,7 @@ public class DatabaseBoardManager { Time.endTiming("createAll boards " + toCreate.size() + ", " + toUpdate.size(), start); - return null; + return !toCreate.isEmpty() || !toUpdate.isEmpty(); }; } diff --git a/Clover/app/src/main/java/org/floens/chan/core/presenter/BoardSetupPresenter.java b/Clover/app/src/main/java/org/floens/chan/core/presenter/BoardSetupPresenter.java index b6c1e74c..4b12d241 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/presenter/BoardSetupPresenter.java +++ b/Clover/app/src/main/java/org/floens/chan/core/presenter/BoardSetupPresenter.java @@ -20,6 +20,7 @@ package org.floens.chan.core.presenter; import org.floens.chan.core.manager.BoardManager; import org.floens.chan.core.model.orm.Board; +import org.floens.chan.core.repository.BoardRepository; import org.floens.chan.core.site.Site; import org.floens.chan.ui.helper.BoardHelper; import org.floens.chan.utils.BackgroundUtils; @@ -29,12 +30,14 @@ import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; +import java.util.Observable; +import java.util.Observer; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import javax.inject.Inject; -public class BoardSetupPresenter { +public class BoardSetupPresenter implements Observer { private BoardManager boardManager; private Callback callback; @@ -44,12 +47,16 @@ public class BoardSetupPresenter { private List savedBoards; + private BoardRepository.SitesBoards allBoardsObservable; + private Executor executor = Executors.newSingleThreadExecutor(); private BackgroundUtils.Cancelable suggestionCall; private List suggestions = new ArrayList<>(); private List selectedSuggestions = new LinkedList<>(); + private String suggestionsQuery = null; + @Inject public BoardSetupPresenter(BoardManager boardManager) { this.boardManager = boardManager; @@ -61,10 +68,25 @@ public class BoardSetupPresenter { savedBoards = boardManager.getSiteSavedBoards(site); callback.setSavedBoards(savedBoards); + + allBoardsObservable = boardManager.getAllBoardsObservable(); + allBoardsObservable.addObserver(this); } public void destroy() { boardManager.updateBoardOrders(savedBoards); + + allBoardsObservable.deleteObserver(this); + } + + @Override + public void update(Observable o, Object arg) { + if (o == allBoardsObservable) { + if (addCallback != null) { + // Update the boards shown in the query. + queryBoardsWithQueryAndShowInAddDialog(); + } + } } public void addClicked() { @@ -74,13 +96,14 @@ public class BoardSetupPresenter { public void bindAddDialog(AddCallback addCallback) { this.addCallback = addCallback; - searchEntered(null); + queryBoardsWithQueryAndShowInAddDialog(); } public void unbindAddDialog() { this.addCallback = null; suggestions.clear(); selectedSuggestions.clear(); + suggestionsQuery = null; } public void onSelectAllClicked() { @@ -88,7 +111,7 @@ public class BoardSetupPresenter { suggestion.checked = true; selectedSuggestions.add(suggestion.getCode()); } - addCallback.updateSuggestions(); + addCallback.suggestionsWereChanged(); } public void onSuggestionClicked(BoardSuggestion suggestion) { @@ -165,12 +188,17 @@ public class BoardSetupPresenter { } public void searchEntered(String userQuery) { + suggestionsQuery = userQuery; + queryBoardsWithQueryAndShowInAddDialog(); + } + + private void queryBoardsWithQueryAndShowInAddDialog() { if (suggestionCall != null) { suggestionCall.cancel(); } - final String query = userQuery == null ? null : - userQuery.replace("/", "").replace("\\", ""); + final String query = suggestionsQuery == null ? null : + suggestionsQuery.replace("/", "").replace("\\", ""); suggestionCall = BackgroundUtils.runWithExecutor(executor, () -> { List suggestions = new ArrayList<>(); if (site.boardsType().canList) { @@ -210,7 +238,7 @@ public class BoardSetupPresenter { updateSuggestions(result); if (addCallback != null) { - addCallback.updateSuggestions(); + addCallback.suggestionsWereChanged(); } }); } @@ -240,7 +268,7 @@ public class BoardSetupPresenter { } public interface AddCallback { - void updateSuggestions(); + void suggestionsWereChanged(); } public static class BoardSuggestion { diff --git a/Clover/app/src/main/java/org/floens/chan/core/presenter/SetupPresenter.java b/Clover/app/src/main/java/org/floens/chan/core/presenter/SetupPresenter.java deleted file mode 100644 index 26ea662d..00000000 --- a/Clover/app/src/main/java/org/floens/chan/core/presenter/SetupPresenter.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Clover - 4chan browser https://github.com/Floens/Clover/ - * Copyright (C) 2014 Floens - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.floens.chan.core.presenter; - -public class SetupPresenter { - private Callback callback; - - public void create(Callback callback) { - this.callback = callback; - - callback.moveToIntro(); - } - - public void startClicked() { - callback.moveToSiteSetup(); - } - - public interface Callback { - void moveToIntro(); - - void moveToSiteSetup(); - } -} 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 abc6e6b7..a3005c60 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 @@ -59,10 +59,8 @@ public class SitesSetupPresenter implements Observer { updateSitesInUi(); - this.callback.setNextAllowed(!sitesShown.isEmpty()); - - if (sitesShown.isEmpty()) { - callback.presentIntro(); + if (sites.getAll().isEmpty()) { + callback.showHint(); } } @@ -90,12 +88,6 @@ public class SitesSetupPresenter implements Observer { updateSitesInUi(); } - public void onIntroDismissed() { - if (sitesShown.isEmpty()) { - callback.showHint(); - } - } - public void bindAddDialog(AddCallback addCallback) { this.addCallback = addCallback; } @@ -104,10 +96,6 @@ public class SitesSetupPresenter implements Observer { this.addCallback = null; } - public boolean mayExit() { - return sitesShown.size() > 0; - } - public void onShowDialogClicked() { callback.showAddDialog(); } @@ -131,16 +119,11 @@ public class SitesSetupPresenter implements Observer { }); } - public void onDoneClicked() { - } - private void siteAdded(Site site) { sitesShown.add(site); saveOrder(); updateSitesInUi(); - - callback.setNextAllowed(!sitesShown.isEmpty()); } public void onSiteCellSettingsClicked(Site site) { @@ -172,14 +155,10 @@ public class SitesSetupPresenter implements Observer { public interface Callback { void setSites(List sites); - void presentIntro(); - void showHint(); void showAddDialog(); - void setNextAllowed(boolean nextAllowed); - void openSiteConfiguration(Site site); } 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 58661015..491c7d5c 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 @@ -102,6 +102,10 @@ public class ThreadPresenter implements ChanThreadLoader.ChanLoaderCallback, Pos this.threadPresenterCallback = threadPresenterCallback; } + public void showNoContent() { + threadPresenterCallback.showEmpty(); + } + public void bindLoadable(Loadable loadable) { if (!loadable.equals(this.loadable)) { if (chanLoader != null) { @@ -751,6 +755,8 @@ public class ThreadPresenter implements ChanThreadLoader.ChanLoaderCallback, Pos void showLoading(); + void showEmpty(); + void showPostInfo(String info); void showPostLinkables(Post post); diff --git a/Clover/app/src/main/java/org/floens/chan/core/repository/BoardRepository.java b/Clover/app/src/main/java/org/floens/chan/core/repository/BoardRepository.java index 7b5d405c..58a47a33 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/repository/BoardRepository.java +++ b/Clover/app/src/main/java/org/floens/chan/core/repository/BoardRepository.java @@ -23,6 +23,7 @@ import org.floens.chan.core.database.DatabaseBoardManager; import org.floens.chan.core.database.DatabaseManager; import org.floens.chan.core.model.orm.Board; import org.floens.chan.core.site.Site; +import org.floens.chan.utils.Logger; import org.floens.chan.utils.Time; import java.util.ArrayList; @@ -35,6 +36,8 @@ import javax.inject.Singleton; @Singleton public class BoardRepository implements Observer { + private static final String TAG = "BoardRepository"; + private final DatabaseManager databaseManager; private final DatabaseBoardManager databaseBoardManager; @@ -68,7 +71,11 @@ public class BoardRepository implements Observer { } public void updateAvailableBoardsForSite(Site site, List availableBoards) { - databaseManager.runTask(databaseBoardManager.createAll(site, availableBoards)); + boolean changed = databaseManager.runTask(databaseBoardManager.createAll(site, availableBoards)); + Logger.d(TAG, "updateAvailableBoardsForSite changed = " + changed); + if (changed) { + updateObservablesAsync(); + } } public Board getFromCode(Site site, String code) { 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 726e9949..b8418cd1 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 @@ -50,7 +50,6 @@ import org.floens.chan.core.site.SiteService; 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.SitesSetupController; import org.floens.chan.ui.controller.SplitNavigationController; import org.floens.chan.ui.controller.StyledToolbarNavigationController; import org.floens.chan.ui.controller.ThreadSlideController; @@ -158,15 +157,7 @@ public class StartActivity extends AppCompatActivity implements NfcAdapter.Creat private void restoreFresh() { if (!siteService.areSitesSetup()) { - SitesSetupController setupController = new SitesSetupController(this); - - if (drawerController.childControllers.get(0) instanceof DoubleNavigationController) { - DoubleNavigationController doubleNavigationController = - (DoubleNavigationController) drawerController.childControllers.get(0); - doubleNavigationController.pushController(setupController, false); - } else { - mainNavigationController.pushController(setupController, false); - } + browseController.showSitesNotSetup(); } else { browseController.loadWithDefaultBoard(); } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/BrowseController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/BrowseController.java index 318088b2..7e9e6799 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/controller/BrowseController.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/BrowseController.java @@ -35,6 +35,7 @@ import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.core.site.Site; import org.floens.chan.ui.adapter.PostsFilter; import org.floens.chan.ui.helper.BoardHelper; +import org.floens.chan.ui.helper.HintPopup; import org.floens.chan.ui.layout.BrowseBoardsFloatingMenu; import org.floens.chan.ui.layout.ThreadLayout; import org.floens.chan.ui.toolbar.NavigationItem; @@ -92,6 +93,15 @@ public class BrowseController extends ThreadController implements presenter.destroy(); } + @Override + public void showSitesNotSetup() { + super.showSitesNotSetup(); + + HintPopup hint = HintPopup.show(context, getToolbar(), R.string.thread_empty_setup_hint); + hint.alignLeft(); + hint.wiggle(); + } + public void setBoard(Board board) { presenter.setBoard(board); } @@ -109,30 +119,6 @@ public class BrowseController extends ThreadController implements // Toolbar menu navigation.hasBack = false; - /*search = menu.addItem(new ToolbarMenuItem(context, this, SEARCH_ID, R.drawable.ic_search_white_24dp)); - refresh = menu.addItem(new ToolbarMenuItem(context, this, REFRESH_ID, R.drawable.ic_refresh_white_24dp)); - - // Toolbar overflow - overflow = menu.createOverflow(this); - - List items = new ArrayList<>(); - if (!ChanSettings.enableReplyFab.get()) { - items.add(new FloatingMenuItem(REPLY_ID, R.string.action_reply)); - } - viewModeMenuItem = new FloatingMenuItem(VIEW_MODE_ID, postViewMode == ChanSettings.PostViewMode.LIST ? - R.string.action_switch_catalog : R.string.action_switch_board); - items.add(viewModeMenuItem); - - archive = new FloatingMenuItem(ARCHIVE_ID, R.string.thread_view_archive); - items.add(archive); - archive.setEnabled(false); - - items.add(new FloatingMenuItem(ORDER_ID, R.string.action_order)); - items.add(new FloatingMenuItem(OPEN_BROWSER_ID, R.string.action_open_browser)); - items.add(new FloatingMenuItem(SHARE_ID, R.string.action_share)); - - overflow.setSubMenu(new FloatingMenu(context, overflow.getView(), items));*/ - NavigationItem.MenuOverflowBuilder overflowBuilder = navigation.buildMenu() .withItem(R.drawable.ic_search_white_24dp, this::searchClicked) .withItem(R.drawable.ic_refresh_white_24dp, this::reloadClicked) 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 deleted file mode 100644 index 17bb663c..00000000 --- a/Clover/app/src/main/java/org/floens/chan/ui/controller/IntroController.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Clover - 4chan browser https://github.com/Floens/Clover/ - * Copyright (C) 2014 Floens - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.floens.chan.ui.controller; - -import android.content.Context; -import android.view.View; -import android.widget.Button; - -import org.floens.chan.R; -import org.floens.chan.controller.Controller; - -public class IntroController extends Controller implements View.OnClickListener { - private Button start; - - public IntroController(Context context) { - super(context); - } - - @Override - public void onCreate() { - super.onCreate(); - - view = inflateRes(R.layout.controller_intro); - - start = view.findViewById(R.id.start); - start.setOnClickListener(this); - } - - @Override - public void onClick(View v) { - if (v == start) { - ((SitesSetupController) presentedByController).onIntroDismissed(); - stopPresenting(); - } - } -} diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/SetupController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/SetupController.java deleted file mode 100644 index 59639c76..00000000 --- a/Clover/app/src/main/java/org/floens/chan/ui/controller/SetupController.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Clover - 4chan browser https://github.com/Floens/Clover/ - * Copyright (C) 2014 Floens - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.floens.chan.ui.controller; - -import android.content.Context; -import android.view.animation.DecelerateInterpolator; - -import org.floens.chan.R; -import org.floens.chan.controller.Controller; -import org.floens.chan.controller.transition.FadeInTransition; -import org.floens.chan.core.presenter.SetupPresenter; -import org.floens.chan.ui.theme.ThemeHelper; -import org.floens.chan.ui.toolbar.Toolbar; - -public class SetupController extends ToolbarNavigationController implements SetupPresenter.Callback { - private SetupPresenter presenter; - - public SetupController(Context context) { - super(context); - } - - @Override - public void onCreate() { - super.onCreate(); - - view = inflateRes(R.layout.controller_navigation_setup); - container = view.findViewById(R.id.container); - toolbar = view.findViewById(R.id.toolbar); - toolbar.setArrowMenuIconShown(false); - toolbar.setBackgroundColor(ThemeHelper.getInstance().getTheme().primaryColor.color); - toolbar.setCallback(new Toolbar.SimpleToolbarCallback() { - @Override - public void onMenuOrBackClicked(boolean isArrow) { - } - }); - toolbar.setAlpha(0f); - requireSpaceForToolbar = false; - - presenter = new SetupPresenter(); - presenter.create(this); - } - - public SetupPresenter getPresenter() { - return presenter; - } - - @Override - public void moveToIntro() { - replaceController(new IntroController(context), false); - } - - @Override - public void moveToSiteSetup() { - SitesSetupController sitesSetupController = new SitesSetupController(context); - sitesSetupController.showDoneCheckmark(); - replaceController(sitesSetupController, true); - } - - private void replaceController(Controller to, boolean showToolbar) { - if (blockingInput || toolbar.isTransitioning()) return; - - boolean animated = getTop() != null; - - transition(getTop(), to, true, animated ? new FadeInTransition() : null); - - toolbar.animate().alpha(showToolbar ? 1f : 0f) - .setInterpolator(new DecelerateInterpolator(2f)).start(); - } -} 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 d59391e6..9f7ac4b3 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 @@ -68,6 +68,8 @@ public class SitesSetupController extends StyledToolbarNavigationController impl private RecyclerView sitesRecyclerview; private FloatingActionButton addButton; + private HintPopup addBoardsHint; + private SitesAdapter sitesAdapter; private ItemTouchHelper itemTouchHelper; private List sites = new ArrayList<>(); @@ -143,16 +145,6 @@ public class SitesSetupController extends StyledToolbarNavigationController impl presenter.destroy(); } - public void showDoneCheckmark() { - navigation.swipeable = false; - - navigation.buildMenu() - .withItem(R.drawable.ic_done_white_24dp, (item) -> presenter.onDoneClicked()) - .build(); - -// doneMenuItem.getView().setAlpha(0f); - } - @Override public void onClick(View v) { if (v == addButton) { @@ -160,28 +152,11 @@ public class SitesSetupController extends StyledToolbarNavigationController impl } } - @Override - public boolean onBack() { - if (presenter.mayExit()) { - return super.onBack(); - } else { - return true; - } - } - - @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.wiggle(); popup.show(); } @@ -226,16 +201,6 @@ public class SitesSetupController extends StyledToolbarNavigationController impl crossfadeView.toggle(!sites.isEmpty(), true); } - @Override - public void setNextAllowed(boolean nextAllowed) { -// if (doneMenuItem != null) { -// doneMenuItem.getView().animate().alpha(nextAllowed ? 1f : 0f).start(); -// } - if (!nextAllowed) { - navigation.swipeable = false; - } - } - private void onSiteCellSettingsClicked(Site site) { presenter.onSiteCellSettingsClicked(site); } @@ -267,6 +232,14 @@ public class SitesSetupController extends StyledToolbarNavigationController impl String boardsString = context.getResources().getQuantityString(R.plurals.board, boards, boards); String descriptionText = context.getString(R.string.setup_sites_site_description, boardsString); holder.description.setText(descriptionText); + + if (boards == 0) { + if (addBoardsHint != null) { + addBoardsHint.dismiss(); + } + addBoardsHint = HintPopup.show(context, holder.settings, R.string.setup_sites_add_boards_hint); + addBoardsHint.wiggle(); + } } @Override diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/ThreadController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/ThreadController.java index 33cc8b69..d4709675 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/controller/ThreadController.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/ThreadController.java @@ -103,6 +103,10 @@ public abstract class ThreadController extends Controller implements EventBus.getDefault().unregister(this); } + public void showSitesNotSetup() { + threadLayout.getPresenter().showNoContent(); + } + public abstract void openPin(Pin pin); /* diff --git a/Clover/app/src/main/java/org/floens/chan/ui/drawable/DropdownArrowDrawable.java b/Clover/app/src/main/java/org/floens/chan/ui/drawable/DropdownArrowDrawable.java index c3acf5f8..44acdfab 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/drawable/DropdownArrowDrawable.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/drawable/DropdownArrowDrawable.java @@ -23,6 +23,7 @@ import android.graphics.Paint; import android.graphics.Path; import android.graphics.PixelFormat; import android.graphics.drawable.Drawable; +import android.support.annotation.NonNull; public class DropdownArrowDrawable extends Drawable { private Paint paint = new Paint(); @@ -45,7 +46,7 @@ public class DropdownArrowDrawable extends Drawable { } @Override - public void draw(Canvas canvas) { + public void draw(@NonNull Canvas canvas) { path.rewind(); path.moveTo(0, height / 4); path.lineTo(width, height / 4); @@ -84,7 +85,9 @@ public class DropdownArrowDrawable extends Drawable { } int color = pressed ? pressedColor : this.color; if (color != paint.getColor()) { + int prevAlpha = paint.getAlpha(); paint.setColor(color); + paint.setAlpha(prevAlpha); invalidateSelf(); return true; } else { @@ -100,6 +103,7 @@ public class DropdownArrowDrawable extends Drawable { @Override public void setAlpha(int alpha) { paint.setAlpha(alpha); + invalidateSelf(); } @Override 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 11691a93..cc50b55e 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,10 +17,12 @@ */ package org.floens.chan.ui.helper; +import android.animation.TimeInterpolator; import android.annotation.SuppressLint; import android.content.Context; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; +import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -51,15 +53,18 @@ public class HintPopup { private TextView textView; private PopupWindow popupWindow; - private LinearLayout popupView; + private ViewGroup popupView; private final View anchor; private String text; private final int offsetX; private final int offsetY; private final boolean top; private boolean dismissed; + private boolean rightAligned = true; + private boolean wiggle = false; - public HintPopup(Context context, final View anchor, final String text, final int offsetX, final int offsetY, final boolean top) { + 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; @@ -71,7 +76,7 @@ public class HintPopup { @SuppressLint("InflateParams") private void createView(Context context) { - popupView = (LinearLayout) LayoutInflater.from(context) + popupView = (ViewGroup) LayoutInflater.from(context) .inflate(top ? R.layout.popup_hint_top : R.layout.popup_hint, null); textView = popupView.findViewById(R.id.text); @@ -91,15 +96,46 @@ public class HintPopup { if (!dismissed) { popupView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); // TODO: cleanup - int xoff = -popupView.getMeasuredWidth() + anchor.getWidth() + offsetX - dp(2); + int xoff; + if (rightAligned) { + xoff = -popupView.getMeasuredWidth() + anchor.getWidth() + offsetX - dp(2); + } else { + xoff = -popupView.getMeasuredWidth() + offsetX - dp(2); + } int yoff = -dp(25) + offsetY + (top ? -anchor.getHeight() - dp(30) : 0); popupWindow.showAsDropDown(anchor, xoff, yoff); + + if (wiggle) { + TimeInterpolator wiggleInterpolator = input -> + (float) Math.sin(60 * input * 2.0 * Math.PI); + + popupView.animate() + .translationY(dp(2)) + .setInterpolator(wiggleInterpolator) + .setDuration(60000) + .start(); + } + + if (!rightAligned) { + View arrow = popupView.findViewById(R.id.arrow); + LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) arrow.getLayoutParams(); + lp.gravity = Gravity.LEFT; + arrow.setLayoutParams(lp); + } } }, 400); // popupView.postDelayed(popupWindow::dismiss, 5000); } + public void alignLeft() { + rightAligned = false; + } + + public void wiggle() { + wiggle = true; + } + public void dismiss() { popupWindow.dismiss(); dismissed = true; diff --git a/Clover/app/src/main/java/org/floens/chan/ui/layout/BoardAddLayout.java b/Clover/app/src/main/java/org/floens/chan/ui/layout/BoardAddLayout.java index 1e455344..fc03ca77 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/layout/BoardAddLayout.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/layout/BoardAddLayout.java @@ -110,7 +110,7 @@ public class BoardAddLayout extends LinearLayout implements SearchLayout.SearchL } @Override - public void updateSuggestions() { + public void suggestionsWereChanged() { suggestionsAdapter.notifyDataSetChanged(); } 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 d032e313..08fe0020 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 @@ -35,6 +35,7 @@ public class SiteAddLayout extends LinearLayout implements SitesSetupPresenter.A urlContainer = findViewById(R.id.url_container); url = findViewById(R.id.url); + url.setHint(R.string.setup_sites_url_hint); } public void setDialog(Dialog dialog) { 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 70442eed..e8065498 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 @@ -70,7 +70,8 @@ import static org.floens.chan.utils.AndroidUtils.fixSnackbarText; import static org.floens.chan.utils.AndroidUtils.getString; /** - * Wrapper around ThreadListLayout, so that it cleanly manages between a load bar and the list view. + * Wrapper around ThreadListLayout, so that it cleanly manages between a loading state + * and the recycler view. */ public class ThreadLayout extends CoordinatorLayout implements ThreadPresenter.ThreadPresenterCallback, @@ -78,9 +79,10 @@ public class ThreadLayout extends CoordinatorLayout implements View.OnClickListener, ThreadListLayout.ThreadListLayoutCallback { private enum Visible { + EMPTY, LOADING, THREAD, - ERROR; + ERROR } @Inject @@ -138,6 +140,9 @@ public class ThreadLayout extends CoordinatorLayout implements errorText = errorLayout.findViewById(R.id.text); errorRetryButton = errorLayout.findViewById(R.id.button); + // Inflate empty layout + + // View setup threadListLayout.setCallbacks(presenter, presenter, presenter, presenter, this); postPopupHelper = new PostPopupHelper(getContext(), presenter, this); @@ -251,6 +256,11 @@ public class ThreadLayout extends CoordinatorLayout implements switchVisible(Visible.LOADING); } + @Override + public void showEmpty() { + switchVisible(Visible.EMPTY); + } + public void showPostInfo(String info) { new AlertDialog.Builder(getContext()) .setTitle(R.string.post_info_title) @@ -538,6 +548,9 @@ public class ThreadLayout extends CoordinatorLayout implements this.visible = visible; switch (visible) { + case EMPTY: + loadView.setView(inflateEmptyView()); + break; case LOADING: View view = loadView.setView(null); // TODO: cleanup @@ -559,6 +572,11 @@ public class ThreadLayout extends CoordinatorLayout implements } } + @SuppressLint("InflateParams") + private View inflateEmptyView() { + return LayoutInflater.from(getContext()).inflate(R.layout.layout_empty_setup, null); + } + @Override public void presentRepliesController(Controller controller) { callback.presentRepliesController(controller); diff --git a/Clover/app/src/main/java/org/floens/chan/ui/toolbar/ToolbarContainer.java b/Clover/app/src/main/java/org/floens/chan/ui/toolbar/ToolbarContainer.java index 00171c45..3829f0c3 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/toolbar/ToolbarContainer.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/toolbar/ToolbarContainer.java @@ -27,7 +27,8 @@ import android.content.Context; import android.graphics.drawable.Drawable; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.text.TextUtils; +import android.text.Editable; +import android.text.TextWatcher; import android.util.AttributeSet; import android.view.Gravity; import android.view.LayoutInflater; @@ -48,6 +49,7 @@ import org.floens.chan.utils.AndroidUtils; import java.util.HashMap; import java.util.Map; +import static android.text.TextUtils.isEmpty; import static org.floens.chan.utils.AndroidUtils.dp; import static org.floens.chan.utils.AndroidUtils.getAttrColor; import static org.floens.chan.utils.AndroidUtils.removeFromParentView; @@ -153,7 +155,7 @@ public class ToolbarContainer extends FrameLayout { titleView.setText(item.title); } - if (!TextUtils.isEmpty(item.subtitle)) { + if (!isEmpty(item.subtitle)) { TextView subtitleView = view.findViewById(R.id.subtitle); if (subtitleView != null) { subtitleView.setText(item.subtitle); @@ -459,16 +461,33 @@ public class ToolbarContainer extends FrameLayout { int arrowColor = getAttrColor(getContext(), R.attr.dropdown_light_color); int arrowPressedColor = getAttrColor( getContext(), R.attr.dropdown_light_pressed_color); - Drawable drawable = new DropdownArrowDrawable( + final Drawable arrowDrawable = new DropdownArrowDrawable( dp(12), dp(12), true, arrowColor, arrowPressedColor); titleView.setCompoundDrawablesWithIntrinsicBounds( - null, null, drawable, null); + null, null, arrowDrawable, null); titleView.setOnClickListener(v -> item.middleMenu.show(titleView)); + + // Hide the dropdown arrow if there is no text. + titleView.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + + @Override + public void afterTextChanged(Editable s) { + arrowDrawable.setAlpha(isEmpty(s) ? 0 : 255); + } + }); + arrowDrawable.setAlpha(isEmpty(item.title) ? 0 : 255); } // Possible subtitle. TextView subtitleView = menu.findViewById(R.id.subtitle); - if (!TextUtils.isEmpty(item.subtitle)) { + if (!isEmpty(item.subtitle)) { ViewGroup.LayoutParams titleParams = titleView.getLayoutParams(); titleParams.height = ViewGroup.LayoutParams.WRAP_CONTENT; titleView.setLayoutParams(titleParams); diff --git a/Clover/app/src/main/res/drawable-xxhdpi/logo.png b/Clover/app/src/main/res/drawable-xxhdpi/logo.png deleted file mode 100644 index 15514f64..00000000 Binary files a/Clover/app/src/main/res/drawable-xxhdpi/logo.png and /dev/null differ diff --git a/Clover/app/src/main/res/layout/controller_intro.xml b/Clover/app/src/main/res/layout/controller_intro.xml deleted file mode 100644 index d1fa92ab..00000000 --- a/Clover/app/src/main/res/layout/controller_intro.xml +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - - - - - - -