Merge pull request #1736 from kiwix/feature/macgills/1717-buggy-bookmarks

#1717 Adding/Removing bookmarks is prety much buggy - observe data so…
This commit is contained in:
Seán Mac Gillicuddy 2020-02-04 10:18:20 +00:00 committed by GitHub
commit 0c595020fa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 68 additions and 55 deletions

View File

@ -19,10 +19,12 @@ package org.kiwix.kiwixmobile.core.dao
import io.objectbox.Box import io.objectbox.Box
import io.objectbox.kotlin.query import io.objectbox.kotlin.query
import io.reactivex.Flowable
import io.reactivex.schedulers.Schedulers
import org.kiwix.kiwixmobile.core.bookmark.BookmarkItem import org.kiwix.kiwixmobile.core.bookmark.BookmarkItem
import org.kiwix.kiwixmobile.core.data.local.entity.Bookmark
import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity
import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity_ import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity_
import org.kiwix.kiwixmobile.core.data.local.entity.Bookmark
import org.kiwix.kiwixmobile.core.reader.ZimFileReader import org.kiwix.kiwixmobile.core.reader.ZimFileReader
import javax.inject.Inject import javax.inject.Inject
@ -49,6 +51,16 @@ class NewBookmarksDao @Inject constructor(val box: Box<BookmarkEntity>) {
.toList() .toList()
.distinct() .distinct()
fun bookmarkUrlsForCurrentBook(zimFileReader: ZimFileReader?): Flowable<List<String>> =
box.asFlowable(
box.query {
equal(BookmarkEntity_.zimId, zimFileReader?.id ?: "")
.or()
.equal(BookmarkEntity_.zimName, zimFileReader?.name ?: "")
order(BookmarkEntity_.bookmarkTitle)
}).map { it.map(BookmarkEntity::bookmarkUrl) }
.subscribeOn(Schedulers.io())
fun saveBookmark(bookmarkItem: BookmarkItem) { fun saveBookmark(bookmarkItem: BookmarkItem) {
box.put(BookmarkEntity(bookmarkItem)) box.put(BookmarkEntity(bookmarkItem))
} }

View File

@ -30,6 +30,7 @@ import org.kiwix.kiwixmobile.core.bookmark.BookmarksActivity
import org.kiwix.kiwixmobile.core.bookmark.BookmarksModule import org.kiwix.kiwixmobile.core.bookmark.BookmarksModule
import org.kiwix.kiwixmobile.core.dao.FetchDownloadDao import org.kiwix.kiwixmobile.core.dao.FetchDownloadDao
import org.kiwix.kiwixmobile.core.dao.NewBookDao import org.kiwix.kiwixmobile.core.dao.NewBookDao
import org.kiwix.kiwixmobile.core.dao.NewBookmarksDao
import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao
import org.kiwix.kiwixmobile.core.dao.NewRecentSearchDao import org.kiwix.kiwixmobile.core.dao.NewRecentSearchDao
import org.kiwix.kiwixmobile.core.data.DataModule import org.kiwix.kiwixmobile.core.data.DataModule
@ -95,6 +96,7 @@ interface CoreComponent {
fun newBookDao(): NewBookDao fun newBookDao(): NewBookDao
fun newLanguagesDao(): NewLanguagesDao fun newLanguagesDao(): NewLanguagesDao
fun recentSearchDao(): NewRecentSearchDao fun recentSearchDao(): NewRecentSearchDao
fun newBookmarksDao(): NewBookmarksDao
fun connectivityManager(): ConnectivityManager fun connectivityManager(): ConnectivityManager
fun context(): Context fun context(): Context
fun downloader(): Downloader fun downloader(): Downloader

View File

@ -73,7 +73,10 @@ import com.google.android.material.appbar.AppBarLayout;
import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.navigation.NavigationView; import com.google.android.material.navigation.NavigationView;
import com.google.android.material.snackbar.Snackbar; import com.google.android.material.snackbar.Snackbar;
import io.reactivex.Flowable;
import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.processors.BehaviorProcessor;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
@ -93,12 +96,14 @@ import org.kiwix.kiwixmobile.core.StorageObserver;
import org.kiwix.kiwixmobile.core.base.BaseActivity; import org.kiwix.kiwixmobile.core.base.BaseActivity;
import org.kiwix.kiwixmobile.core.bookmark.BookmarkItem; import org.kiwix.kiwixmobile.core.bookmark.BookmarkItem;
import org.kiwix.kiwixmobile.core.bookmark.BookmarksActivity; import org.kiwix.kiwixmobile.core.bookmark.BookmarksActivity;
import org.kiwix.kiwixmobile.core.dao.NewBookmarksDao;
import org.kiwix.kiwixmobile.core.extensions.ContextExtensionsKt; import org.kiwix.kiwixmobile.core.extensions.ContextExtensionsKt;
import org.kiwix.kiwixmobile.core.history.HistoryActivity; import org.kiwix.kiwixmobile.core.history.HistoryActivity;
import org.kiwix.kiwixmobile.core.history.HistoryListItem; import org.kiwix.kiwixmobile.core.history.HistoryListItem;
import org.kiwix.kiwixmobile.core.reader.ZimFileReader; import org.kiwix.kiwixmobile.core.reader.ZimFileReader;
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer; import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer;
import org.kiwix.kiwixmobile.core.search.SearchActivity; import org.kiwix.kiwixmobile.core.search.SearchActivity;
import org.kiwix.kiwixmobile.core.search.viewmodel.effects.SearchInPreviousScreen;
import org.kiwix.kiwixmobile.core.utils.DimenUtils; import org.kiwix.kiwixmobile.core.utils.DimenUtils;
import org.kiwix.kiwixmobile.core.utils.LanguageUtils; import org.kiwix.kiwixmobile.core.utils.LanguageUtils;
import org.kiwix.kiwixmobile.core.utils.NetworkUtils; import org.kiwix.kiwixmobile.core.utils.NetworkUtils;
@ -112,7 +117,6 @@ import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.os.Build.VERSION_CODES; import static android.os.Build.VERSION_CODES;
import static org.kiwix.kiwixmobile.core.main.TableDrawerAdapter.DocumentSection; import static org.kiwix.kiwixmobile.core.main.TableDrawerAdapter.DocumentSection;
import static org.kiwix.kiwixmobile.core.main.TableDrawerAdapter.TableClickListener; import static org.kiwix.kiwixmobile.core.main.TableDrawerAdapter.TableClickListener;
import static org.kiwix.kiwixmobile.core.search.viewmodel.effects.SearchInPreviousScreen.EXTRA_SEARCH_IN_TEXT;
import static org.kiwix.kiwixmobile.core.utils.AnimationUtils.rotate; import static org.kiwix.kiwixmobile.core.utils.AnimationUtils.rotate;
import static org.kiwix.kiwixmobile.core.utils.Constants.BOOKMARK_CHOSEN_REQUEST; import static org.kiwix.kiwixmobile.core.utils.Constants.BOOKMARK_CHOSEN_REQUEST;
import static org.kiwix.kiwixmobile.core.utils.Constants.EXTRA_CHOSE_X_FILE; import static org.kiwix.kiwixmobile.core.utils.Constants.EXTRA_CHOSE_X_FILE;
@ -144,8 +148,8 @@ public abstract class CoreMainActivity extends BaseActivity
MainMenu.MenuClickListener { MainMenu.MenuClickListener {
public static final String HOME_URL = "file:///android_asset/home.html"; public static final String HOME_URL = "file:///android_asset/home.html";
private final ArrayList<String> bookmarks = new ArrayList<>();
protected final List<KiwixWebView> webViewList = new ArrayList<>(); protected final List<KiwixWebView> webViewList = new ArrayList<>();
private final BehaviorProcessor<String> webUrlsProcessor = BehaviorProcessor.create();
@BindView(R2.id.activity_main_root) @BindView(R2.id.activity_main_root)
ConstraintLayout root; ConstraintLayout root;
@BindView(R2.id.toolbar) @BindView(R2.id.toolbar)
@ -199,6 +203,8 @@ public abstract class CoreMainActivity extends BaseActivity
protected NightModeConfig nightModeConfig; protected NightModeConfig nightModeConfig;
@Inject @Inject
protected MainMenu.Factory menuFactory; protected MainMenu.Factory menuFactory;
@Inject
protected NewBookmarksDao newBookmarksDao;
private CountDownTimer hideBackToTopTimer = new CountDownTimer(1200, 1200) { private CountDownTimer hideBackToTopTimer = new CountDownTimer(1200, 1200) {
@Override @Override
@ -261,6 +267,8 @@ public abstract class CoreMainActivity extends BaseActivity
closeTab(viewHolder.getAdapterPosition()); closeTab(viewHolder.getAdapterPosition());
} }
}; };
private Disposable bookmarkingDisposable;
private Boolean isBookmarked;
@Override @Override
public void onActionModeStarted(ActionMode mode) { public void onActionModeStarted(ActionMode mode) {
@ -729,6 +737,7 @@ public abstract class CoreMainActivity extends BaseActivity
@Override @Override
protected void onDestroy() { protected void onDestroy() {
safeDispose();
presenter.detachView(); presenter.detachView();
if (downloadBookButton != null) { if (downloadBookButton != null) {
downloadBookButton.setOnClickListener(null); downloadBookButton.setOnClickListener(null);
@ -827,7 +836,7 @@ public abstract class CoreMainActivity extends BaseActivity
tabsAdapter.setSelected(currentWebViewIndex); tabsAdapter.setSelected(currentWebViewIndex);
updateBottomToolbarVisibility(); updateBottomToolbarVisibility();
loadPrefs(); loadPrefs();
refreshBookmarkSymbol(); updateUrlProcessor();
updateTableOfContents(); updateTableOfContents();
updateTitle(); updateTitle();
@ -1082,18 +1091,38 @@ public abstract class CoreMainActivity extends BaseActivity
e.printStackTrace(); e.printStackTrace();
} }
zimReaderContainer.setZimFile(file); zimReaderContainer.setZimFile(file);
if (zimReaderContainer.getZimFileReader() != null) { final ZimFileReader zimFileReader = zimReaderContainer.getZimFileReader();
if (zimFileReader != null) {
if (mainMenu != null) { if (mainMenu != null) {
mainMenu.onFileOpened(zimReaderContainer.getZimFileReader(), !urlIsInvalid()); mainMenu.onFileOpened(zimFileReader, !urlIsInvalid());
} }
openMainPage(); openMainPage();
presenter.loadCurrentZimBookmarksUrl(); safeDispose();
bookmarkingDisposable = Flowable.combineLatest(
newBookmarksDao.bookmarkUrlsForCurrentBook(zimFileReader),
webUrlsProcessor,
(bookmarkUrls, currentUrl) -> bookmarkUrls.contains(currentUrl)
).observeOn(AndroidSchedulers.mainThread())
.subscribe(isBookmarked -> {
this.isBookmarked = isBookmarked;
bottomToolbarBookmark.setImageResource(
isBookmarked ? R.drawable.ic_bookmark_24dp : R.drawable.ic_bookmark_border_24dp);
},
Throwable::printStackTrace
);
updateUrlProcessor();
} else { } else {
ContextExtensionsKt.toast(this, R.string.error_file_invalid, Toast.LENGTH_LONG); ContextExtensionsKt.toast(this, R.string.error_file_invalid, Toast.LENGTH_LONG);
showHomePage(); showHomePage();
} }
} }
private void safeDispose() {
if (bookmarkingDisposable != null) {
bookmarkingDisposable.dispose();
}
}
private boolean isNotPreviouslyOpenZim(String canonicalPath) { private boolean isNotPreviouslyOpenZim(String canonicalPath) {
return canonicalPath != null && !canonicalPath.equals(zimReaderContainer.getZimCanonicalPath()); return canonicalPath != null && !canonicalPath.equals(zimReaderContainer.getZimCanonicalPath());
} }
@ -1167,36 +1196,26 @@ public abstract class CoreMainActivity extends BaseActivity
@OnClick(R2.id.bottom_toolbar_bookmark) @OnClick(R2.id.bottom_toolbar_bookmark)
public void toggleBookmark() { public void toggleBookmark() {
//Check maybe need refresh
String articleUrl = getCurrentWebView().getUrl(); String articleUrl = getCurrentWebView().getUrl();
boolean isBookmark = false; if (articleUrl != null) {
if (articleUrl != null && !bookmarks.contains(articleUrl)) { if (isBookmarked) {
presenter.deleteBookmark(articleUrl);
Snackbar.make(snackbarRoot, R.string.bookmark_removed, Snackbar.LENGTH_LONG)
.show();
}
} else {
final ZimFileReader zimFileReader = zimReaderContainer.getZimFileReader(); final ZimFileReader zimFileReader = zimReaderContainer.getZimFileReader();
if (zimFileReader != null) { if (zimFileReader != null) {
presenter.saveBookmark( presenter.saveBookmark(
new BookmarkItem(getCurrentWebView().getTitle(), articleUrl, new BookmarkItem(getCurrentWebView().getTitle(), articleUrl,
zimReaderContainer.getZimFileReader())); zimReaderContainer.getZimFileReader()));
Snackbar.make(snackbarRoot, R.string.bookmark_added, Snackbar.LENGTH_LONG)
.setAction(getString(R.string.open), v -> goToBookmarks())
.setActionTextColor(getResources().getColor(R.color.white))
.show();
} else { } else {
Toast.makeText(this, R.string.unable_to_add_to_bookmarks, Toast.LENGTH_SHORT).show(); Toast.makeText(this, R.string.unable_to_add_to_bookmarks, Toast.LENGTH_SHORT).show();
} }
isBookmark = true;
} else if (articleUrl != null) {
presenter.deleteBookmark(articleUrl);
isBookmark = false;
}
popBookmarkSnackbar(isBookmark);
presenter.loadCurrentZimBookmarksUrl();
}
private void popBookmarkSnackbar(boolean isBookmark) {
if (isBookmark) {
Snackbar.make(snackbarRoot, R.string.bookmark_added, Snackbar.LENGTH_LONG)
.setAction(getString(R.string.open), v -> goToBookmarks())
.setActionTextColor(getResources().getColor(R.color.white))
.show();
} else {
Snackbar.make(snackbarRoot, R.string.bookmark_removed, Snackbar.LENGTH_LONG)
.show();
} }
} }
@ -1211,7 +1230,6 @@ public abstract class CoreMainActivity extends BaseActivity
selectTab(currentWebViewIndex); selectTab(currentWebViewIndex);
setUpWebViewWithTextToSpeech(); setUpWebViewWithTextToSpeech();
} }
presenter.loadCurrentZimBookmarksUrl();
updateBottomToolbarVisibility(); updateBottomToolbarVisibility();
presenter.loadBooks(); presenter.loadBooks();
@ -1299,13 +1317,6 @@ public abstract class CoreMainActivity extends BaseActivity
} }
} }
@Override
public void refreshBookmarksUrl(List<String> urls) {
bookmarks.clear();
bookmarks.addAll(urls);
refreshBookmarkSymbol();
}
private void contentsDrawerHint() { private void contentsDrawerHint() {
drawerLayout.postDelayed(() -> drawerLayout.openDrawer(GravityCompat.END), 500); drawerLayout.postDelayed(() -> drawerLayout.openDrawer(GravityCompat.END), 500);
@ -1386,7 +1397,8 @@ public abstract class CoreMainActivity extends BaseActivity
if (resultCode == RESULT_OK) { if (resultCode == RESULT_OK) {
String title = String title =
data.getStringExtra(TAG_FILE_SEARCHED).replace("<b>", "").replace("</b>", ""); data.getStringExtra(TAG_FILE_SEARCHED).replace("<b>", "").replace("</b>", "");
boolean isSearchInText = data.getBooleanExtra(EXTRA_SEARCH_IN_TEXT, false); boolean isSearchInText =
data.getBooleanExtra(SearchInPreviousScreen.EXTRA_SEARCH_IN_TEXT, false);
if (isSearchInText) { if (isSearchInText) {
//if the search is localized trigger find in page UI. //if the search is localized trigger find in page UI.
KiwixWebView webView = getCurrentWebView(); KiwixWebView webView = getCurrentWebView();
@ -1463,12 +1475,10 @@ public abstract class CoreMainActivity extends BaseActivity
return getCurrentWebView().getUrl() == null; return getCurrentWebView().getUrl() == null;
} }
private void refreshBookmarkSymbol() { private void updateUrlProcessor() {
if (checkNull(bottomToolbarBookmark)) { final String url = getCurrentWebView().getUrl();
bottomToolbarBookmark.setImageResource( if (url != null) {
bookmarks.contains(getCurrentWebView().getUrl()) ? R.drawable.ic_bookmark_24dp webUrlsProcessor.offer(url);
: R.drawable.ic_bookmark_border_24dp
);
} }
} }
@ -1548,7 +1558,7 @@ public abstract class CoreMainActivity extends BaseActivity
public void webViewUrlFinishedLoading() { public void webViewUrlFinishedLoading() {
updateTableOfContents(); updateTableOfContents();
tabsAdapter.notifyDataSetChanged(); tabsAdapter.notifyDataSetChanged();
refreshBookmarkSymbol(); updateUrlProcessor();
updateBottomToolbarArrowsAlpha(); updateBottomToolbarArrowsAlpha();
String url = getCurrentWebView().getUrl(); String url = getCurrentWebView().getUrl();
final ZimFileReader zimFileReader = zimReaderContainer.getZimFileReader(); final ZimFileReader zimFileReader = zimReaderContainer.getZimFileReader();

View File

@ -32,8 +32,6 @@ public class MainContract {
interface View extends BaseContract.View<Presenter> { interface View extends BaseContract.View<Presenter> {
void addBooks(List<BooksOnDiskListItem> books); void addBooks(List<BooksOnDiskListItem> books);
void refreshBookmarksUrl(List<String> urls);
} }
public interface Presenter extends BaseContract.Presenter<View> { public interface Presenter extends BaseContract.Presenter<View> {
@ -43,8 +41,6 @@ public class MainContract {
void saveHistory(HistoryListItem.HistoryItem history); void saveHistory(HistoryListItem.HistoryItem history);
void loadCurrentZimBookmarksUrl();
void saveBookmark(BookmarkItem bookmark); void saveBookmark(BookmarkItem bookmark);
void deleteBookmark(String bookmarkUrl); void deleteBookmark(String bookmarkUrl);

View File

@ -109,13 +109,6 @@ public class MainPresenter extends BasePresenter<MainContract.View>
}); });
} }
@Override
public void loadCurrentZimBookmarksUrl() {
compositeDisposable.add(dataSource.getCurrentZimBookmarksUrl()
.subscribe(view::refreshBookmarksUrl,
e -> Log.e(TAG, "Unable to load current ZIM urls", e)));
}
@Override @Override
public void saveBookmark(BookmarkItem bookmark) { public void saveBookmark(BookmarkItem bookmark) {
dataSource.saveBookmark(bookmark) dataSource.saveBookmark(bookmark)