diff options
| author | Andrew Dolgov <fox@fakecake.org> | 2025-05-17 10:35:09 +0300 |
|---|---|---|
| committer | Andrew Dolgov <fox@fakecake.org> | 2025-05-17 10:35:40 +0300 |
| commit | 4715cc93f9e4b0dde090288aac6fa7abf834636c (patch) | |
| tree | adc6ed538cb4ce2d569f0510ab6df8ef100b4e1f | |
| parent | 334379d21bf9ac24bed68665bcc06b1c49d8f109 (diff) | |
switch to viewmodel for feeds/cats
8 files changed, 311 insertions, 276 deletions
diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/ApiLoader.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/ApiLoader.java deleted file mode 100755 index 5cba0ed1..00000000 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/ApiLoader.java +++ /dev/null @@ -1,84 +0,0 @@ -package org.fox.ttrss; - -import android.content.Context; - -import androidx.loader.content.AsyncTaskLoader; - -import com.google.gson.JsonElement; - -import org.fox.ttrss.ApiCommon.ApiError; - -import java.util.HashMap; - -public class ApiLoader extends AsyncTaskLoader<JsonElement> implements ApiCommon.ApiCaller { - private final String TAG = this.getClass().getSimpleName(); - - private final int m_responseCode = 0; - protected String m_responseMessage; - private int m_apiStatusCode = 0; - - private final Context m_context; - private String m_lastErrorMessage; - private ApiError m_lastError; - private final HashMap<String,String> m_params; - private JsonElement m_data; - - ApiLoader(Context context, HashMap<String, String> params) { - super(context); - - m_context = context; - m_lastError = ApiError.UNKNOWN_ERROR; - m_params = params; - } - - @Override - protected void onStartLoading() { - if (m_data != null) { - deliverResult(m_data); - } else { - forceLoad(); - } - } - - @Override - public void deliverResult(JsonElement data) { - m_data = data; - - super.deliverResult(data); - } - - public int getErrorMessage() { - return ApiCommon.getErrorMessage(m_lastError); - } - - ApiError getLastError() { - return m_lastError; - } - - String getLastErrorMessage() { - return m_lastErrorMessage; - } - - @Override - public JsonElement loadInBackground() { - return ApiCommon.performRequest(m_context, m_params, this); - } - - @Override - public void setStatusCode(int statusCode) { - m_apiStatusCode = statusCode; - } - - @Override - public void setLastError(ApiError lastError) { - m_lastError = lastError; - } - - @Override - public void setLastErrorMessage(String message) { - m_lastErrorMessage = message; - } - - @Override - public void notifyProgress(int progress) { } -} diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/Application.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/Application.java index 75542e3c..11e32bcf 100755 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/Application.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/Application.java @@ -11,9 +11,6 @@ import java.util.HashMap; import java.util.LinkedHashMap; public class Application extends android.app.Application { - public static final int LOADER_HEADLINES = 0; - public static final int LOADER_FEEDS = 1; - public static final int LOADER_CATS = 2; private static Application m_singleton; diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/ArticleModel.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/ArticleModel.java index f4deb372..2a6b4b3e 100644 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/ArticleModel.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/ArticleModel.java @@ -47,7 +47,7 @@ public class ArticleModel extends AndroidViewModel implements ApiCommon.ApiCalle private int m_resizeWidth; private boolean m_append; private boolean m_lazyLoadEnabled = true; - private boolean m_loadingInProgress; + private MutableLiveData<Boolean> m_isLoading = new MutableLiveData<>(Boolean.valueOf(false)); private ExecutorService m_executor; private Handler m_mainHandler = new Handler(Looper.getMainLooper()); private MutableLiveData<Long> m_lastUpdate = new MutableLiveData<>(Long.valueOf(0)); @@ -91,7 +91,7 @@ public class ArticleModel extends AndroidViewModel implements ApiCommon.ApiCalle m_feed = feed; loadInBackground(); - } else if (feed != m_feed || m_lazyLoadEnabled && !m_loadingInProgress) { + } else if (feed != m_feed || m_lazyLoadEnabled || !m_isLoading.getValue()) { m_append = true; m_feed = feed; @@ -106,7 +106,7 @@ public class ArticleModel extends AndroidViewModel implements ApiCommon.ApiCalle ArticleList articlesWork = new ArticleList(m_articles.getValue()); - m_loadingInProgress = true; + m_isLoading.postValue(true); final int skip = getSkip(m_append, articlesWork); final boolean allowForceUpdate = org.fox.ttrss.Application.getInstance().getApiLevel() >= 9 && @@ -212,7 +212,7 @@ public class ArticleModel extends AndroidViewModel implements ApiCommon.ApiCalle } m_offset += m_amountLoaded; - m_loadingInProgress = false; + m_isLoading.postValue(false); Log.d(TAG, this + " loaded headlines=" + m_amountLoaded + " resultingLocalSize=" + articlesWork.size()); } @@ -227,7 +227,7 @@ public class ArticleModel extends AndroidViewModel implements ApiCommon.ApiCalle }); }); - m_loadingInProgress = false; + m_isLoading.postValue(false); } @@ -299,7 +299,7 @@ public class ArticleModel extends AndroidViewModel implements ApiCommon.ApiCalle return m_offset; } - public boolean lazyLoadEnabled() { + public boolean isLazyLoadEnabled() { return m_lazyLoadEnabled; } @@ -316,7 +316,11 @@ public class ArticleModel extends AndroidViewModel implements ApiCommon.ApiCalle } public boolean isLoading() { - return m_loadingInProgress; + return m_isLoading.getValue(); + } + + public LiveData<Boolean> getIsLoading() { + return m_isLoading; } public LiveData<Integer> getLoadingProgress() { diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/FeedsFragment.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/FeedsFragment.java index 513eaeb7..6fe2144a 100755 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/FeedsFragment.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/FeedsFragment.java @@ -21,6 +21,7 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProvider; import androidx.loader.app.LoaderManager; import androidx.loader.content.Loader; import androidx.preference.PreferenceManager; @@ -51,8 +52,7 @@ import java.util.List; import java.util.stream.Collectors; import java.util.stream.IntStream; -public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeListener, - LoaderManager.LoaderCallbacks<JsonElement> { +public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeListener { private final String TAG = this.getClass().getSimpleName(); protected SharedPreferences m_prefs; protected MasterActivity m_activity; @@ -71,88 +71,6 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL m_enableParentBtn = enableParentBtn; } - @NonNull - @Override - public Loader<JsonElement> onCreateLoader(int id, Bundle args) { - - if (m_swipeLayout != null) - m_swipeLayout.setRefreshing(true); - - HashMap<String,String> params = new HashMap<>(); - params.put("op", "getFeeds"); - params.put("sid", m_activity.getSessionId()); - params.put("include_nested", "true"); - params.put("cat_id", String.valueOf(m_rootFeed.id)); - - return new ApiLoader(getContext(), params); - } - - @Override - public void onLoadFinished(@NonNull Loader<JsonElement> loader, JsonElement result) { - if (m_swipeLayout != null) m_swipeLayout.setRefreshing(false); - - if (result != null) { - try { - JsonArray content = result.getAsJsonArray(); - if (content != null) { - - Type listType = new TypeToken<List<Feed>>() {}.getType(); - List<Feed> feedsJson = new Gson().fromJson(content, listType); - List<Feed> feeds = new ArrayList<>(); - - if (m_activity.getUnreadOnly() && m_rootFeed.id != Feed.CAT_SPECIAL) - feedsJson = feedsJson.stream() - .filter(f -> f.unread > 0) - .collect(Collectors.toList()); - - sortFeeds(feedsJson, m_rootFeed); - - if (m_enableParentBtn) { - feeds.add(0, new Feed(Feed.TYPE_GOBACK)); - - if (m_rootFeed.id >= 0 && !feedsJson.isEmpty()) { - Feed feed = new Feed(m_rootFeed.id, m_rootFeed.title, true); - - feed.unread = feedsJson.stream().map(a -> a.unread).reduce(0, Integer::sum); - feed.always_open_headlines = true; - - feeds.add(1, feed); - } - } - - feeds.addAll(feedsJson); - - feeds.add(new Feed(Feed.TYPE_DIVIDER)); - feeds.add(new Feed(Feed.TYPE_TOGGLE_UNREAD, getString(R.string.unread_only), true)); - - m_adapter.submitList(feeds); - - return; - } - - } catch (Exception e) { - m_activity.toast(e.getMessage()); - } - } - - ApiLoader apiLoader = (ApiLoader) loader; - - if (apiLoader.getLastError() != null && apiLoader.getLastError() != ApiCommon.ApiError.SUCCESS) { - if (apiLoader.getLastError() == ApiCommon.ApiError.LOGIN_FAILED) { - m_activity.login(true); - } else { - if (apiLoader.getLastErrorMessage() != null) { - m_activity.toast(getString(apiLoader.getErrorMessage()) + "\n" + apiLoader.getLastErrorMessage()); - } else { - m_activity.toast(apiLoader.getErrorMessage()); - } - } - } - } - - @Override - public void onLoaderReset(Loader<JsonElement> loader) { } - @SuppressLint("DefaultLocale") static class FeedUnreadComparator implements Comparator<Feed> { @@ -165,7 +83,6 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL } } - @SuppressLint("DefaultLocale") static class FeedTitleComparator implements Comparator<Feed> { @@ -230,39 +147,48 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item .getMenuInfo(); - final Feed feed = m_adapter.getCurrentList().get(info.position); - - Log.d(TAG, "context for feed=" + feed.id); - - int itemId = item.getItemId(); - if (itemId == R.id.browse_headlines) { - Feed tmpFeed = new Feed(feed); + // all onContextItemSelected are invoked in sequence so we might get a context menu for headlines, etc + // TODO context menu ids defined here should be unique to feedsfragment + try { + if (info != null) { + final Feed feed = m_adapter.getCurrentList().get(info.position); - if (!neverOpenHeadlines(feed)) - tmpFeed.always_open_headlines = true; + Log.d(TAG, "context for feed=" + feed.id); - m_activity.onFeedSelected(tmpFeed); - return true; - } else if (itemId == R.id.browse_feeds) { - m_activity.onFeedSelected(feed); - return true; - } else if (itemId == R.id.unsubscribe_feed) { - MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(getContext()) - .setMessage(getString(R.string.unsubscribe_from_prompt, feed.title)) - .setPositiveButton(R.string.unsubscribe, - (dialog, which) -> m_activity.unsubscribeFeed(feed)) - .setNegativeButton(R.string.dialog_cancel, - (dialog, which) -> { + int itemId = item.getItemId(); + if (itemId == R.id.browse_headlines) { + Feed tmpFeed = new Feed(feed); - }); + if (!neverOpenHeadlines(feed)) + tmpFeed.always_open_headlines = true; - Dialog dlg = builder.create(); - dlg.show(); + m_activity.onFeedSelected(tmpFeed); + return true; + } else if (itemId == R.id.browse_feeds) { + m_activity.onFeedSelected(feed); + return true; + } else if (itemId == R.id.unsubscribe_feed) { + MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(getContext()) + .setMessage(getString(R.string.unsubscribe_from_prompt, feed.title)) + .setPositiveButton(R.string.unsubscribe, + (dialog, which) -> m_activity.unsubscribeFeed(feed)) + .setNegativeButton(R.string.dialog_cancel, + (dialog, which) -> { + + }); + + Dialog dlg = builder.create(); + dlg.show(); + + return true; + } else if (itemId == R.id.catchup_feed) { + m_activity.catchupDialog(feed); + return true; + } + } - return true; - } else if (itemId == R.id.catchup_feed) { - m_activity.catchupDialog(feed); - return true; + } catch (IndexOutOfBoundsException e) { + e.printStackTrace(); } Log.d(TAG, "onContextItemSelected, unhandled id=" + item.getItemId()); @@ -360,9 +286,73 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL }); } + FeedsModel model = new ViewModelProvider(this).get(FeedsModel.class); + + model.getUpdatesData().observe(getActivity(), lastUpdate -> { + Log.d(TAG, "observed update=" + lastUpdate); + }); + + model.getIsLoading().observe(getActivity(), isLoading -> { + Log.d(TAG, "observed isLoading=" + isLoading); + + if (isAdded() && m_swipeLayout != null) + m_swipeLayout.setRefreshing(isLoading); + }); + + model.getFeeds().observe(getActivity(), feeds -> { + Log.d(TAG, "observed feeds=" + feeds); + + if (isAdded()) { + onFeedsLoaded(feeds); + + if (model.getLastError() != null && model.getLastError() != ApiCommon.ApiError.SUCCESS) { + if (model.getLastError() == ApiCommon.ApiError.LOGIN_FAILED) { + m_activity.login(true); + } else { + if (model.getLastErrorMessage() != null) { + m_activity.toast(getString(model.getErrorMessage()) + "\n" + model.getLastErrorMessage()); + } else { + m_activity.toast(model.getErrorMessage()); + } + } + } + } + }); + return view; } + protected void onFeedsLoaded(List<Feed> loadedFeeds) { + List<Feed> feedsWork = new ArrayList<>(); + + if (m_activity.getUnreadOnly() && m_rootFeed.id != Feed.CAT_SPECIAL) + loadedFeeds = loadedFeeds.stream() + .filter(f -> f.unread > 0) + .collect(Collectors.toList()); + + sortFeeds(loadedFeeds, m_rootFeed); + + if (m_enableParentBtn) { + feedsWork.add(0, new Feed(Feed.TYPE_GOBACK)); + + if (m_rootFeed.id >= 0 && !loadedFeeds.isEmpty()) { + Feed feed = new Feed(m_rootFeed.id, m_rootFeed.title, true); + + feed.unread = loadedFeeds.stream().map(a -> a.unread).reduce(0, Integer::sum); + feed.always_open_headlines = true; + + feedsWork.add(1, feed); + } + } + + feedsWork.addAll(loadedFeeds); + + feedsWork.add(new Feed(Feed.TYPE_DIVIDER)); + feedsWork.add(new Feed(Feed.TYPE_TOGGLE_UNREAD, getString(R.string.unread_only), true)); + + m_adapter.submitList(feedsWork); + } + @Override public void onDestroy() { super.onDestroy(); @@ -395,11 +385,8 @@ public class FeedsFragment extends Fragment implements OnSharedPreferenceChangeL if (!isAdded()) return; - if (m_swipeLayout != null) { - m_swipeLayout.setRefreshing(true); - } - - LoaderManager.getInstance(this).restartLoader(Application.LOADER_FEEDS, null, this).forceLoad(); + FeedsModel model = new ViewModelProvider(this).get(FeedsModel.class); + model.startLoading(m_rootFeed, false); } private class FeedViewHolder extends RecyclerView.ViewHolder { diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/FeedsModel.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/FeedsModel.java new file mode 100644 index 00000000..bd6ca21f --- /dev/null +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/FeedsModel.java @@ -0,0 +1,160 @@ +package org.fox.ttrss; + +import android.app.Application; +import android.os.Handler; +import android.os.Looper; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.lifecycle.AndroidViewModel; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.reflect.TypeToken; + +import org.fox.ttrss.types.ArticleList; +import org.fox.ttrss.types.Feed; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class FeedsModel extends AndroidViewModel implements ApiCommon.ApiCaller { + private final String TAG = this.getClass().getSimpleName(); + private MutableLiveData<List<Feed>> m_feeds = new MutableLiveData<>(new ArrayList<>()); + private MutableLiveData<Integer> m_loadingProgress = new MutableLiveData<>(Integer.valueOf(0)); + private MutableLiveData<Long> m_lastUpdate = new MutableLiveData<>(Long.valueOf(0)); + private MutableLiveData<Boolean> m_isLoading = new MutableLiveData<>(Boolean.valueOf(false)); + + private Feed m_feed; + + private ExecutorService m_executor; + private Handler m_mainHandler = new Handler(Looper.getMainLooper()); + + private final int m_responseCode = 0; + protected String m_responseMessage; + private int m_apiStatusCode = 0; + private String m_lastErrorMessage; + private ApiCommon.ApiError m_lastError; + private boolean m_rootMode; + + public FeedsModel(@NonNull Application application) { + super(application); + + // do we need concurrency or not? + m_executor = Executors.newSingleThreadExecutor(); + + Log.d(TAG, this + " created"); + } + + @Override + public void setStatusCode(int statusCode) { + m_apiStatusCode = statusCode; + } + + @Override + public void setLastError(ApiCommon.ApiError lastError) { + m_lastError = lastError; + } + + @Override + public void setLastErrorMessage(String message) { + m_lastErrorMessage = message; + } + + public void startLoading(Feed feed, boolean rootMode) { + Log.d(TAG, "startLoading feed id=" + feed.id + " cat=" + feed.is_cat); + + m_feed = feed; + m_rootMode = rootMode; + + loadInBackground(); + } + + @Override + public void notifyProgress(int progress) { + m_loadingProgress.postValue(progress); + } + + protected HashMap<String,String> constructParams() { + HashMap<String,String> params = new HashMap<>(); + + if (m_rootMode) { + params.put("op", "getCategories"); + + // this confusingly named option means "return top level categories only" + params.put("enable_nested", "true"); + } else { + params.put("op", "getFeeds"); + params.put("cat_id", String.valueOf(m_feed.id)); + params.put("include_nested", "true"); + } + + params.put("sid", ((org.fox.ttrss.Application)getApplication()).getSessionId()); + + return params; + } + + private void loadInBackground() { + Log.d(TAG, this + " loadInBackground"); + + m_isLoading.postValue(true); + + HashMap<String,String> params = constructParams(); + + m_executor.execute(() -> { + JsonElement result = ApiCommon.performRequest(getApplication(), params, this); + + Log.d(TAG, "got result=" + result); + + try { + JsonArray content = result.getAsJsonArray(); + if (content != null) { + + Type listType = new TypeToken<List<Feed>>() { + }.getType(); + List<Feed> feeds = new Gson().fromJson(content, listType); + + m_feeds.postValue(feeds); + } + } catch (Exception e) { + e.printStackTrace(); + } + + m_isLoading.postValue(false); + }); + } + + public LiveData<Integer> getLoadingProgress() { + return m_loadingProgress; + } + + public LiveData<Long> getUpdatesData() { + return m_lastUpdate; + } + + public LiveData<Boolean> getIsLoading() { return m_isLoading; } + + public LiveData<List<Feed>> getFeeds() { + return m_feeds; + } + + public int getErrorMessage() { + return ApiCommon.getErrorMessage(m_lastError); + } + + ApiCommon.ApiError getLastError() { + return m_lastError; + } + + String getLastErrorMessage() { + return m_lastErrorMessage; + } + +}
\ No newline at end of file diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/HeadlinesFragment.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/HeadlinesFragment.java index 099afc60..dba0ac47 100755 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/HeadlinesFragment.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/HeadlinesFragment.java @@ -217,12 +217,12 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment { } } + // all onContextItemSelected are invoked in sequence so we might get a context menu for headlines, etc public boolean onContextItemSelected(MenuItem item) { AdapterContextMenuInfo info = (AdapterContextMenuInfo) item .getMenuInfo(); if (info != null) { - try { Article article = Application.getArticles().get(info.position); @@ -233,6 +233,7 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment { } } + Log.d(TAG, "onContextItemSelected, unhandled id=" + item.getItemId()); return super.onContextItemSelected(item); } @@ -459,7 +460,7 @@ public class HeadlinesFragment extends androidx.fragment.app.Fragment { ArticleModel model = Application.getArticlesModel(); - if (dy > 0 && !m_isLazyLoading && !model.isLoading() && model.lazyLoadEnabled() && + if (dy > 0 && !m_isLazyLoading && !model.isLoading() && model.isLazyLoadEnabled() && lastVisibleItem >= Application.getArticles().size() - 5) { Log.d(TAG, "attempting to lazy load more articles..."); diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/MasterActivity.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/MasterActivity.java index 643f859c..bdbac8ff 100755 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/MasterActivity.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/MasterActivity.java @@ -165,6 +165,10 @@ public class MasterActivity extends OnlineActivity implements HeadlinesEventList fc.initialize(new Feed(-1, getString(R.string.cat_special), true), false); ft.replace(R.id.feeds_fragment, fc, FRAG_FEEDS); + /* FeedsFragment ff = new FeedsFragment(); + ff.initialize(new Feed(12, "Technology", true), true); + ft.replace(R.id.feeds_fragment, ff, FRAG_FEEDS); */ + // allow overriding feed to open on startup in non-shortcut mode, default to // open_on_startup prefs setting and not-category diff --git a/org.fox.ttrss/src/main/java/org/fox/ttrss/RootCategoriesFragment.java b/org.fox.ttrss/src/main/java/org/fox/ttrss/RootCategoriesFragment.java index b61a2736..55c23226 100755 --- a/org.fox.ttrss/src/main/java/org/fox/ttrss/RootCategoriesFragment.java +++ b/org.fox.ttrss/src/main/java/org/fox/ttrss/RootCategoriesFragment.java @@ -4,6 +4,7 @@ import android.annotation.SuppressLint; import android.os.Bundle; import androidx.annotation.NonNull; +import androidx.lifecycle.ViewModelProvider; import androidx.loader.content.Loader; import com.google.gson.Gson; @@ -23,19 +24,6 @@ import java.util.stream.Collectors; public class RootCategoriesFragment extends FeedsFragment { private final String TAG = this.getClass().getSimpleName(); - @Override - @NonNull - public Loader<JsonElement> onCreateLoader(int id, Bundle args) { - HashMap<String, String> params = new HashMap<>(); - params.put("op", "getCategories"); - params.put("sid", m_activity.getSessionId()); - - // this confusingly named option means "return top level categories only" - params.put("enable_nested", "true"); - - return new ApiLoader(getContext(), params); - } - @SuppressLint("DefaultLocale") static class CatOrderComparator implements Comparator<Feed> { @@ -74,65 +62,43 @@ public class RootCategoriesFragment extends FeedsFragment { } @Override - public void onLoadFinished(@NonNull Loader<JsonElement> loader, JsonElement result) { - if (m_swipeLayout != null) m_swipeLayout.setRefreshing(false); - - if (result != null) { - try { - JsonArray content = result.getAsJsonArray(); - if (content != null) { - - Type listType = new TypeToken<List<Feed>>() {}.getType(); - List<Feed> feedsJson = new Gson().fromJson(content, listType); + public void refresh() { + if (!isAdded()) + return; - List<Feed> feeds = new ArrayList<>(); - - sortFeeds(feedsJson, m_rootFeed); + FeedsModel model = new ViewModelProvider(this).get(FeedsModel.class); + model.startLoading(m_rootFeed, true); + } - // virtual cats implemented in getCategories since api level 1 - if (m_activity.getApiLevel() == 0) { - feeds.add(0, new Feed(-2, getString(R.string.cat_labels), true)); - feeds.add(1, new Feed(-1, getString(R.string.cat_special), true)); - feeds.add(new Feed(0, getString(R.string.cat_uncategorized), true)); - } + @Override + protected void onFeedsLoaded(List<Feed> loadedFeeds) { + List<Feed> feedsWork = new ArrayList<>(); - if (m_activity.getUnreadOnly()) - feedsJson = feedsJson.stream() - .filter(f -> f.id == Feed.CAT_SPECIAL || f.unread > 0) - .collect(Collectors.toList()); + sortFeeds(loadedFeeds, m_rootFeed); - feedsJson = feedsJson.stream() - .peek(f -> f.is_cat = true) - .collect(Collectors.toList()); + // virtual cats implemented in getCategories since api level 1 + if (m_activity.getApiLevel() == 0) { + feedsWork.add(0, new Feed(-2, getString(R.string.cat_labels), true)); + feedsWork.add(1, new Feed(-1, getString(R.string.cat_special), true)); + feedsWork.add(new Feed(0, getString(R.string.cat_uncategorized), true)); + } - feeds.addAll(feedsJson); + if (m_activity.getUnreadOnly()) + loadedFeeds = loadedFeeds.stream() + .filter(f -> f.id == Feed.CAT_SPECIAL || f.unread > 0) + .collect(Collectors.toList()); - feeds.add(new Feed(Feed.TYPE_DIVIDER)); - feeds.add(new Feed(Feed.TYPE_TOGGLE_UNREAD, getString(R.string.unread_only), true)); + loadedFeeds = loadedFeeds.stream() + .peek(f -> f.is_cat = true) + .collect(Collectors.toList()); - m_adapter.submitList(feeds); + feedsWork.addAll(loadedFeeds); - return; - } + feedsWork.add(new Feed(Feed.TYPE_DIVIDER)); + feedsWork.add(new Feed(Feed.TYPE_TOGGLE_UNREAD, getString(R.string.unread_only), true)); - } catch (Exception e) { - m_activity.toast(e.getMessage()); - } - } + m_adapter.submitList(feedsWork); - ApiLoader apiLoader = (ApiLoader) loader; - - if (apiLoader.getLastError() != null && apiLoader.getLastError() != ApiCommon.ApiError.SUCCESS) { - if (apiLoader.getLastError() == ApiCommon.ApiError.LOGIN_FAILED) { - m_activity.login(true); - } else { - if (apiLoader.getLastErrorMessage() != null) { - m_activity.toast(getString(apiLoader.getErrorMessage()) + "\n" + apiLoader.getLastErrorMessage()); - } else { - m_activity.toast(apiLoader.getErrorMessage()); - } - } - } } } |