mirror of https://github.com/readrops/Readrops.git
synchronize read/unread changes
This commit is contained in:
parent
3119d44264
commit
062e5a6050
|
@ -49,7 +49,6 @@ import com.readrops.app.viewmodels.MainViewModel;
|
|||
import com.readrops.app.views.MainItemListAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -143,7 +142,7 @@ public class MainActivity extends AppCompatActivity implements SwipeRefreshLayou
|
|||
private void handleDrawerClick(IDrawerItem drawerItem) {
|
||||
if (drawerItem instanceof PrimaryDrawerItem) {
|
||||
drawer.closeDrawer();
|
||||
int id = (int)drawerItem.getIdentifier();
|
||||
int id = (int) drawerItem.getIdentifier();
|
||||
|
||||
switch (id) {
|
||||
case DrawerManager.ARTICLES_ITEM_ID:
|
||||
|
@ -206,7 +205,8 @@ public class MainActivity extends AppCompatActivity implements SwipeRefreshLayou
|
|||
intent.putExtra(ItemActivity.IMAGE_URL, itemWithFeed.getItem().getImageLink());
|
||||
startActivityForResult(intent, ITEM_REQUEST);
|
||||
|
||||
viewModel.setItemReadState(itemWithFeed.getItem().getId(), true)
|
||||
viewModel.setItemReadState(itemWithFeed.getItem().getId(), true,
|
||||
!itemWithFeed.getItem().isReadChanged())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnError(throwable -> Toast.makeText(getApplicationContext(),
|
||||
|
@ -316,7 +316,8 @@ public class MainActivity extends AppCompatActivity implements SwipeRefreshLayou
|
|||
if (i == ItemTouchHelper.LEFT) { // set item read state
|
||||
ItemWithFeed itemWithFeed = adapter.getItemWithFeed(viewHolder.getAdapterPosition());
|
||||
|
||||
viewModel.setItemReadState(itemWithFeed.getItem().getId(), !itemWithFeed.getItem().isRead())
|
||||
viewModel.setItemReadState(itemWithFeed.getItem().getId(), !itemWithFeed.getItem().isRead(),
|
||||
!itemWithFeed.getItem().isReadChanged())
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe();
|
||||
|
@ -370,7 +371,7 @@ public class MainActivity extends AppCompatActivity implements SwipeRefreshLayou
|
|||
|
||||
allItemsSelected = false;
|
||||
} else {
|
||||
viewModel.setItemsReadState(getIdsFromPositions(adapter.getSelection()), read)
|
||||
viewModel.setItemsReadState(adapter.getSelectedItems(), read)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnError(throwable -> Toast.makeText(getApplicationContext(),
|
||||
|
@ -420,7 +421,7 @@ public class MainActivity extends AppCompatActivity implements SwipeRefreshLayou
|
|||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||
if (requestCode == ADD_FEED_REQUEST && resultCode == RESULT_OK) {
|
||||
if (requestCode == ADD_FEED_REQUEST && resultCode == RESULT_OK) {
|
||||
ArrayList<Feed> feeds = data.getParcelableArrayListExtra("feedIds");
|
||||
|
||||
if (feeds != null && feeds.size() > 0) {
|
||||
|
@ -442,17 +443,21 @@ public class MainActivity extends AppCompatActivity implements SwipeRefreshLayou
|
|||
.subscribe(new Observer<Feed>() {
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
syncProgressLayout.setVisibility(View.VISIBLE);
|
||||
syncProgressBar.setProgress(0);
|
||||
if (isAccountLocal()) {
|
||||
syncProgressLayout.setVisibility(View.VISIBLE);
|
||||
syncProgressBar.setProgress(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(Feed feed) {
|
||||
syncProgress.setText(getString(R.string.updating_feed, feed.getName()));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
syncProgressBar.setProgress((feedCount * 100) / feedNb, true);
|
||||
} else
|
||||
syncProgressBar.setProgress((feedCount * 100) / feedNb);
|
||||
if (isAccountLocal()) {
|
||||
syncProgress.setText(getString(R.string.updating_feed, feed.getName()));
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
syncProgressBar.setProgress((feedCount * 100) / feedNb, true);
|
||||
} else
|
||||
syncProgressBar.setProgress((feedCount * 100) / feedNb);
|
||||
}
|
||||
|
||||
feedCount++;
|
||||
}
|
||||
|
@ -467,12 +472,15 @@ public class MainActivity extends AppCompatActivity implements SwipeRefreshLayou
|
|||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
|
||||
syncProgressBar.setProgress(100, true);
|
||||
else
|
||||
syncProgressBar.setProgress(100);
|
||||
if (isAccountLocal()) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
|
||||
syncProgressBar.setProgress(100, true);
|
||||
else
|
||||
syncProgressBar.setProgress(100);
|
||||
|
||||
syncProgressLayout.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
syncProgressLayout.setVisibility(View.GONE);
|
||||
refreshLayout.setRefreshing(false);
|
||||
|
||||
scrollToTop = true;
|
||||
|
@ -483,6 +491,10 @@ public class MainActivity extends AppCompatActivity implements SwipeRefreshLayou
|
|||
});
|
||||
}
|
||||
|
||||
private boolean isAccountLocal() {
|
||||
return account.getAccountType() == Account.AccountType.LOCAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
getMenuInflater().inflate(R.menu.item_list_menu, menu);
|
||||
|
@ -540,16 +552,6 @@ public class MainActivity extends AppCompatActivity implements SwipeRefreshLayou
|
|||
.show();
|
||||
}
|
||||
|
||||
private List<Integer> getIdsFromPositions(LinkedHashSet<Integer> positions) {
|
||||
List<Integer> ids = new ArrayList<>();
|
||||
|
||||
for (int position : positions) {
|
||||
ids.add((int)adapter.getItemId(position));
|
||||
}
|
||||
|
||||
return ids;
|
||||
}
|
||||
|
||||
public enum ListSortType {
|
||||
NEWEST_TO_OLDEST,
|
||||
OLDEST_TO_NEWEST
|
||||
|
|
|
@ -8,6 +8,7 @@ import org.joda.time.LocalDateTime;
|
|||
|
||||
import static com.readrops.app.database.entities.Account.AccountType.FEEDLY;
|
||||
import static com.readrops.app.database.entities.Account.AccountType.FRESHRSS;
|
||||
import static com.readrops.app.database.entities.Account.AccountType.LOCAL;
|
||||
import static com.readrops.app.database.entities.Account.AccountType.NEXTCLOUD_NEWS;
|
||||
|
||||
public class Converters {
|
||||
|
@ -24,7 +25,9 @@ public class Converters {
|
|||
|
||||
@TypeConverter
|
||||
public Account.AccountType fromAccountTypeCode(int code) {
|
||||
if (code == NEXTCLOUD_NEWS.getCode())
|
||||
if (code == LOCAL.getCode())
|
||||
return LOCAL;
|
||||
else if (code == NEXTCLOUD_NEWS.getCode())
|
||||
return NEXTCLOUD_NEWS;
|
||||
else if (code == FEEDLY.getCode())
|
||||
return FEEDLY;
|
||||
|
|
|
@ -34,7 +34,9 @@ public abstract class Database extends RoomDatabase {
|
|||
|
||||
public static Database getInstance(Context context) {
|
||||
if (database == null)
|
||||
database = Room.databaseBuilder(context, Database.class, "readrops-db").addCallback(roomCallback).build();
|
||||
database = Room.databaseBuilder(context, Database.class, "readrops-db")
|
||||
.addCallback(roomCallback)
|
||||
.build();
|
||||
|
||||
return database;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import com.readrops.app.viewmodels.MainViewModel;
|
|||
public class ItemsListQueryBuilder {
|
||||
|
||||
private String [] columns = {"Item.id", "title", "clean_description", "image_link", "pub_date", "read",
|
||||
"read_it_later", "Feed.name", "text_color", "background_color", "icon_url", "read_time",
|
||||
"read_changed", "read_it_later", "Feed.name", "text_color", "background_color", "icon_url", "read_time",
|
||||
"Feed.id as feedId", "Folder.id as folder_id", "Folder.name as folder_name"};
|
||||
|
||||
private String SELECT_ALL_JOIN = "Item Inner Join Feed, Folder on Item.feed_id = Feed.id And Folder.id = Feed.folder_id";
|
||||
|
|
|
@ -36,16 +36,18 @@ public interface ItemDao {
|
|||
|
||||
/**
|
||||
* Set an item read or unread
|
||||
* @param itemId id of the item to update
|
||||
* @param readState 1 for read, 0 for unread
|
||||
*
|
||||
* @param itemId id of the item to update
|
||||
* @param readState 1 for read, 0 for unread
|
||||
* @param readChanged
|
||||
*/
|
||||
@Query("Update Item set read = :readState Where id = :itemId")
|
||||
void setReadState(int itemId, int readState);
|
||||
@Query("Update Item Set read_changed = :readChanged, read = :readState Where id = :itemId")
|
||||
void setReadState(int itemId, int readState, int readChanged);
|
||||
|
||||
@Query("Update Item set read = :readState")
|
||||
@Query("Update Item set read_changed = 1, read = :readState")
|
||||
void setAllItemsReadState(int readState);
|
||||
|
||||
@Query("Update Item set read = :readState Where feed_id = :feedId")
|
||||
@Query("Update Item set read_changed = 1, read = :readState Where feed_id = :feedId")
|
||||
void setAllItemsReadState(int feedId, int readState);
|
||||
|
||||
@Query("Update Item set read_it_later = 1 Where id = :itemId")
|
||||
|
@ -54,6 +56,18 @@ public interface ItemDao {
|
|||
@Query("Select count(*) From Item Where feed_id = :feedId And read = 0")
|
||||
int getUnreadCount(int feedId);
|
||||
|
||||
@Query("Select title, Item.description, content, link, pub_date, image_link, author, read, text_color, background_color, read_time, Feed.name, Feed.id as feedId, siteUrl, Folder.id as folder_id, Folder.name as folder_name from Item Inner Join Feed, Folder on Item.feed_id = Feed.id And Item.id = :id And Folder.id = Feed.folder_id")
|
||||
@Query("Select title, Item.description, content, link, pub_date, image_link, author, read, text_color, " +
|
||||
"background_color, read_time, Feed.name, Feed.id as feedId, siteUrl, Folder.id as folder_id, " +
|
||||
"Folder.name as folder_name from Item Inner Join Feed, Folder on Item.feed_id = Feed.id And Item.id = :id " +
|
||||
"And Folder.id = Feed.folder_id")
|
||||
LiveData<ItemWithFeed> getItemById(int id);
|
||||
|
||||
@Query("Select remoteId From Item Where read_changed = 1 And read = 1")
|
||||
List<Integer> getReadChanges();
|
||||
|
||||
@Query("Select remoteId From Item Where read_changed = 1 And read = 0")
|
||||
List<Integer> getUnreadChanges();
|
||||
|
||||
@Query("Update Item set read_changed = 0")
|
||||
void resetReadChanges();
|
||||
}
|
||||
|
|
|
@ -106,9 +106,10 @@ public class Account {
|
|||
}
|
||||
|
||||
public enum AccountType {
|
||||
NEXTCLOUD_NEWS(0),
|
||||
FEEDLY(1),
|
||||
FRESHRSS(2);
|
||||
LOCAL(0),
|
||||
NEXTCLOUD_NEWS(1),
|
||||
FEEDLY(2),
|
||||
FRESHRSS(3);
|
||||
|
||||
private int code;
|
||||
|
||||
|
|
|
@ -58,6 +58,9 @@ public class Item implements Comparable<Item> {
|
|||
|
||||
private boolean read;
|
||||
|
||||
@ColumnInfo(name = "read_changed")
|
||||
private boolean readChanged;
|
||||
|
||||
@ColumnInfo(name = "read_it_later")
|
||||
private boolean readItLater;
|
||||
|
||||
|
@ -178,6 +181,14 @@ public class Item implements Comparable<Item> {
|
|||
this.read = read;
|
||||
}
|
||||
|
||||
public boolean isReadChanged() {
|
||||
return readChanged;
|
||||
}
|
||||
|
||||
public void setReadChanged(boolean readChanged) {
|
||||
this.readChanged = readChanged;
|
||||
}
|
||||
|
||||
public boolean isReadItLater() {
|
||||
return readItLater;
|
||||
}
|
||||
|
|
|
@ -56,9 +56,14 @@ public class NextNewsRepository extends ARepository {
|
|||
syncType = NextNewsAPI.SyncType.INITIAL_SYNC;
|
||||
|
||||
SyncData syncData = new SyncData();
|
||||
syncData.setLastModified(account.getLastModified() / 1000L);
|
||||
|
||||
Credentials credentials = new Credentials("Lucas", LibUtils.NEXTCLOUD_PASSWORD, account.getUrl());
|
||||
if (syncType == NextNewsAPI.SyncType.CLASSIC_SYNC) {
|
||||
syncData.setLastModified(account.getLastModified() / 1000L);
|
||||
syncData.setReadItems(database.itemDao().getReadChanges());
|
||||
syncData.setUnreadItems(database.itemDao().getUnreadChanges());
|
||||
}
|
||||
|
||||
Credentials credentials = new Credentials("", LibUtils.NEXTCLOUD_PASSWORD, account.getUrl());
|
||||
SyncResult syncResult = newsAPI.sync(credentials, syncType, syncData);
|
||||
|
||||
if (!syncResult.isError()) {
|
||||
|
@ -74,6 +79,7 @@ public class NextNewsRepository extends ARepository {
|
|||
timings.dumpToLog();
|
||||
|
||||
database.accountDao().updateLastModified(account.getId(), lastModified);
|
||||
database.itemDao().resetReadChanges();
|
||||
|
||||
emitter.onComplete();
|
||||
} else
|
||||
|
|
|
@ -134,18 +134,19 @@ public class MainViewModel extends AndroidViewModel {
|
|||
return db.accountDao().selectAll();
|
||||
}
|
||||
|
||||
public Completable setItemReadState(int itemId, boolean read) {
|
||||
public Completable setItemReadState(int itemId, boolean read, boolean readChanged) {
|
||||
return Completable.create(emitter -> {
|
||||
db.itemDao().setReadState(itemId, read ? 1 : 0);
|
||||
db.itemDao().setReadState(itemId, read ? 1 : 0, readChanged ? 1 : 0);
|
||||
emitter.onComplete();
|
||||
});
|
||||
}
|
||||
|
||||
public Completable setItemsReadState(List<Integer> ids, boolean read) {
|
||||
public Completable setItemsReadState(List<ItemWithFeed> items, boolean read) {
|
||||
List<Completable> completableList = new ArrayList<>();
|
||||
|
||||
for (int id : ids) {
|
||||
completableList.add(setItemReadState(id, read));
|
||||
for (ItemWithFeed itemWithFeed : items) {
|
||||
completableList.add(setItemReadState(itemWithFeed.getItem().getId(), read,
|
||||
!itemWithFeed.getItem().isReadChanged()));
|
||||
}
|
||||
|
||||
return Completable.concat(completableList);
|
||||
|
|
|
@ -35,6 +35,7 @@ import com.readrops.app.utils.DateUtils;
|
|||
import com.readrops.app.utils.GlideRequests;
|
||||
import com.readrops.app.utils.Utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
|
@ -202,6 +203,16 @@ public class MainItemListAdapter extends PagedListAdapter<ItemWithFeed, MainItem
|
|||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public List<ItemWithFeed> getSelectedItems() {
|
||||
List<ItemWithFeed> items = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < selection.size(); i++) {
|
||||
items.add(getItem(i));
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
public ItemWithFeed getItemWithFeed(int i) {
|
||||
return getItem(i);
|
||||
}
|
||||
|
|
|
@ -2,11 +2,10 @@ package com.readrops.readropslibrary.services;
|
|||
|
||||
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFeeds;
|
||||
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFolders;
|
||||
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsItemIds;
|
||||
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsItems;
|
||||
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsUser;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import okhttp3.ResponseBody;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.http.Body;
|
||||
|
@ -35,5 +34,5 @@ public interface NextNewsService {
|
|||
Call<NextNewsItems> getNewItems(@Query("lastModified") long lastModified, @Query("type") int type);
|
||||
|
||||
@PUT("items/{stateType}/multiple")
|
||||
Call<ResponseBody> setArticlesState(@Path("stateType") String stateType, @Body List<Integer> items);
|
||||
Call<ResponseBody> setArticlesState(@Path("stateType") String stateType, @Body NextNewsItemIds items);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import androidx.annotation.Nullable;
|
|||
import com.readrops.readropslibrary.services.NextNewsService;
|
||||
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFeeds;
|
||||
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFolders;
|
||||
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsItemIds;
|
||||
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsItems;
|
||||
import com.readrops.readropslibrary.utils.HttpManager;
|
||||
|
||||
|
@ -105,10 +106,10 @@ public class NextNewsAPI {
|
|||
|
||||
private void putModifiedItems(SyncData data, SyncResult syncResult) throws IOException {
|
||||
Response readItemsResponse = api.setArticlesState(StateType.READ.name().toLowerCase(),
|
||||
data.getReadItems()).execute();
|
||||
new NextNewsItemIds(data.getReadItems())).execute();
|
||||
|
||||
Response unreadItemsResponse = api.setArticlesState(StateType.UNREAD.toString().toLowerCase(),
|
||||
data.getUnreadItems()).execute();
|
||||
new NextNewsItemIds(data.getUnreadItems())).execute();
|
||||
|
||||
if (!readItemsResponse.isSuccessful())
|
||||
syncResult.setError(true);
|
||||
|
|
|
@ -22,38 +22,38 @@ public class SyncData {
|
|||
unstarredItems = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void addUnreadItem(int itemId) {
|
||||
unreadItems.add(itemId);
|
||||
}
|
||||
|
||||
public void addReadItem(int itemId) {
|
||||
readItems.add(itemId);
|
||||
}
|
||||
|
||||
public void addStarredItem(int itemId) {
|
||||
starredItems.add(itemId);
|
||||
}
|
||||
|
||||
public void addUnstarredItem(int itemId) {
|
||||
unstarredItems.add(itemId);
|
||||
}
|
||||
|
||||
public List<Integer> getUnreadItems() {
|
||||
return unreadItems;
|
||||
}
|
||||
|
||||
public void setUnreadItems(List<Integer> unreadItems) {
|
||||
this.unreadItems = unreadItems;
|
||||
}
|
||||
|
||||
public List<Integer> getReadItems() {
|
||||
return readItems;
|
||||
}
|
||||
|
||||
public void setReadItems(List<Integer> readItems) {
|
||||
this.readItems = readItems;
|
||||
}
|
||||
|
||||
public List<Integer> getStarredItems() {
|
||||
return starredItems;
|
||||
}
|
||||
|
||||
public void setStarredItems(List<Integer> starredItems) {
|
||||
this.starredItems = starredItems;
|
||||
}
|
||||
|
||||
public List<Integer> getUnstarredItems() {
|
||||
return unstarredItems;
|
||||
}
|
||||
|
||||
public void setUnstarredItems(List<Integer> unstarredItems) {
|
||||
this.unstarredItems = unstarredItems;
|
||||
}
|
||||
|
||||
public long getLastModified() {
|
||||
return lastModified;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
package com.readrops.readropslibrary.services.nextcloudnews.json;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class NextNewsItemIds {
|
||||
|
||||
private List<Integer> items;
|
||||
|
||||
public NextNewsItemIds(List<Integer> items) {
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
public List<Integer> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
public void setItems(List<Integer> items) {
|
||||
this.items = items;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue