synchronize read/unread changes

This commit is contained in:
Shinokuni 2019-05-17 11:37:20 +02:00
parent 3119d44264
commit 062e5a6050
14 changed files with 140 additions and 69 deletions

View File

@ -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

View File

@ -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;

View File

@ -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;
}

View File

@ -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";

View File

@ -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();
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}
}