From d15315b53f6465af44f0ce522482455de95b5e99 Mon Sep 17 00:00:00 2001 From: Shinokuni Date: Thu, 6 May 2021 22:10:27 +0200 Subject: [PATCH] Synchronize local read/star changes --- .../com/readrops/app/item/ItemActivity.java | 6 +- .../com/readrops/app/item/ItemViewModel.java | 10 ++- .../readrops/app/itemslist/MainActivity.java | 6 +- .../app/repositories/ARepository.java | 14 ++-- .../java/com/readrops/db/dao/ItemDao.java | 11 +-- .../com/readrops/db/dao/ItemStateChangeDao.kt | 76 ++++++++++++++++--- .../java/com/readrops/db/dao/ItemStateDao.kt | 13 ++++ 7 files changed, 102 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/com/readrops/app/item/ItemActivity.java b/app/src/main/java/com/readrops/app/item/ItemActivity.java index 45b2b59e..f45f5e1d 100644 --- a/app/src/main/java/com/readrops/app/item/ItemActivity.java +++ b/app/src/main/java/com/readrops/app/item/ItemActivity.java @@ -38,6 +38,7 @@ import com.readrops.app.utils.PermissionManager; import com.readrops.app.utils.SharedPreferencesManager; import com.readrops.app.utils.Utils; import com.readrops.db.entities.Item; +import com.readrops.db.entities.account.Account; import com.readrops.db.pojo.ItemWithFeed; import org.koin.androidx.viewmodel.compat.ViewModelCompat; @@ -49,10 +50,10 @@ import java.util.regex.Pattern; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.schedulers.Schedulers; +import static com.readrops.app.utils.ReadropsKeys.ACCOUNT; import static com.readrops.app.utils.ReadropsKeys.ACTION_BAR_COLOR; import static com.readrops.app.utils.ReadropsKeys.IMAGE_URL; import static com.readrops.app.utils.ReadropsKeys.ITEM_ID; -import static com.readrops.app.utils.ReadropsKeys.STARRED_ITEM; import static com.readrops.app.utils.ReadropsKeys.WEB_URL; public class ItemActivity extends AppCompatActivity { @@ -82,7 +83,7 @@ public class ItemActivity extends AppCompatActivity { Intent intent = getIntent(); int itemId = intent.getIntExtra(ITEM_ID, 0); String imageUrl = intent.getStringExtra(IMAGE_URL); - boolean starredItem = intent.getBooleanExtra(STARRED_ITEM, false); + Account account = intent.getParcelableExtra(ACCOUNT); setSupportActionBar(binding.collapsingLayoutToolbar); @@ -119,6 +120,7 @@ public class ItemActivity extends AppCompatActivity { })); viewModel = ViewModelCompat.getViewModel(this, ItemViewModel.class); + viewModel.setAccount(account); viewModel.getItemById(itemId).observe(this, itemWithFeed1 -> { if (!uiBinded) { bindUI(itemWithFeed1); diff --git a/app/src/main/java/com/readrops/app/item/ItemViewModel.java b/app/src/main/java/com/readrops/app/item/ItemViewModel.java index 2c249c04..d71bcca6 100644 --- a/app/src/main/java/com/readrops/app/item/ItemViewModel.java +++ b/app/src/main/java/com/readrops/app/item/ItemViewModel.java @@ -12,8 +12,10 @@ import androidx.lifecycle.ViewModel; import com.readrops.app.repositories.ARepository; import com.readrops.db.Database; import com.readrops.db.entities.Item; +import com.readrops.db.entities.account.Account; import com.readrops.db.pojo.ItemWithFeed; +import org.koin.core.parameter.DefinitionParametersKt; import org.koin.java.KoinJavaComponent; import java.io.File; @@ -26,17 +28,23 @@ import io.reactivex.Completable; public class ItemViewModel extends ViewModel { private final Database database; + private Account account; public ItemViewModel(@NonNull Database database) { this.database = database; } + public void setAccount(Account account) { + this.account = account; + } + public LiveData getItemById(int id) { return database.itemDao().getItemById(id); } public Completable setStarState(Item item) { - return KoinJavaComponent.get(ARepository.class).setItemStarState(item); + return KoinJavaComponent.get(ARepository.class, null, () -> DefinitionParametersKt.parametersOf(account)) + .setItemStarState(item); } public Uri saveImageInCache(Bitmap bitmap, Context context) throws IOException { diff --git a/app/src/main/java/com/readrops/app/itemslist/MainActivity.java b/app/src/main/java/com/readrops/app/itemslist/MainActivity.java index daa37d5b..fe084296 100644 --- a/app/src/main/java/com/readrops/app/itemslist/MainActivity.java +++ b/app/src/main/java/com/readrops/app/itemslist/MainActivity.java @@ -73,7 +73,6 @@ import static com.readrops.app.utils.ReadropsKeys.FROM_MAIN_ACTIVITY; import static com.readrops.app.utils.ReadropsKeys.IMAGE_URL; import static com.readrops.app.utils.ReadropsKeys.ITEM_ID; import static com.readrops.app.utils.ReadropsKeys.SETTINGS; -import static com.readrops.app.utils.ReadropsKeys.STARRED_ITEM; import static com.readrops.app.utils.ReadropsKeys.SYNCING; public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener, @@ -229,6 +228,7 @@ public class MainActivity extends AppCompatActivity implements SwipeRefreshLayou if (intent.hasExtra(ITEM_ID) && intent.hasExtra(IMAGE_URL)) { Intent itemIntent = new Intent(this, ItemActivity.class); itemIntent.putExtras(intent); + itemIntent.putExtra(ACCOUNT, viewModel.getCurrentAccount()); startActivity(itemIntent); @@ -318,8 +318,8 @@ public class MainActivity extends AppCompatActivity implements SwipeRefreshLayou intent.putExtra(ITEM_ID, itemWithFeed.getItem().getId()); intent.putExtra(IMAGE_URL, itemWithFeed.getItem().getImageLink()); - intent.putExtra(STARRED_ITEM, drawerManager.getCurrentSelection() == DrawerManager.STARS_ID && - viewModel.getCurrentAccount().getConfig().useStarredItems()); + intent.putExtra(ACCOUNT, viewModel.getCurrentAccount()); + startActivityForResult(intent, ITEM_REQUEST); itemWithFeed.getItem().setRead(true); diff --git a/app/src/main/java/com/readrops/app/repositories/ARepository.java b/app/src/main/java/com/readrops/app/repositories/ARepository.java index 3ff351cb..068b71f1 100644 --- a/app/src/main/java/com/readrops/app/repositories/ARepository.java +++ b/app/src/main/java/com/readrops/app/repositories/ARepository.java @@ -18,7 +18,6 @@ import com.readrops.db.entities.Feed; import com.readrops.db.entities.Folder; import com.readrops.db.entities.Item; import com.readrops.db.entities.ItemState; -import com.readrops.db.entities.ItemStateChange; import com.readrops.db.entities.account.Account; import org.koin.java.KoinJavaComponent; @@ -116,9 +115,9 @@ public abstract class ARepository { } public Completable setItemReadState(Item item) { - return database.itemStateDao().upsertItemReadState(new ItemState(0, item.isRead(), item.isStarred(), item.getRemoteId(), account.getId())) - .andThen(database.itemStateChangesDao().upsertItemStateChange(new ItemStateChange(item.getId(), - true, false, account.getId()))); + return database.itemStateChangesDao().upsertItemReadStateChange(item, account.getId()) + .andThen(database.itemStateDao().upsertItemReadState(new ItemState(0, item.isRead(), + item.isStarred(), item.getRemoteId(), account.getId()))); } public Completable setAllItemsReadState(boolean read) { @@ -130,9 +129,10 @@ public abstract class ARepository { } public Completable setItemStarState(Item item) { - return database.itemDao().setStarState(item.getId(), item.isStarred()) - .andThen(database.itemStateChangesDao().upsertItemStateChange(new ItemStateChange(item.getId(), - false, true, account.getId()))); + return database.itemStateChangesDao().upsertItemStarStateChange(item, account.getId()) + .andThen(database.itemStateDao().upsertItemStarState(new ItemState(0, item.isRead(), + item.isStarred(), item.getRemoteId(), account.getId()))); + } public Single getFeedCount(int accountId) { diff --git a/db/src/main/java/com/readrops/db/dao/ItemDao.java b/db/src/main/java/com/readrops/db/dao/ItemDao.java index 3d1cf353..6a3c7021 100644 --- a/db/src/main/java/com/readrops/db/dao/ItemDao.java +++ b/db/src/main/java/com/readrops/db/dao/ItemDao.java @@ -38,12 +38,6 @@ public interface ItemDao extends BaseDao { @Query("Select * From Item Where remoteId = :remoteId And feed_id = :feedId") Item selectByRemoteId(String remoteId, int feedId); - /** - * Set an item read or unread - * - * @param itemId id of the item to update - * @param read 1 for read, 0 for unread - */ @Query("Update Item Set read = :read Where id = :itemId") Completable setReadState(int itemId, boolean read); @@ -60,7 +54,7 @@ public interface ItemDao extends BaseDao { int getUnreadCount(int feedId); @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH) - @Query("Select Item.id, title, Item.description, content, link, pub_date, image_link, author, read, text_color, " + + @Query("Select Item.id, Item.remoteId, title, Item.description, content, link, pub_date, image_link, author, read, text_color, " + "background_color, read_time, starred, Feed.name, Feed.id as feedId, siteUrl, Folder.id as folder_id, " + "Folder.name as folder_name from Item Inner Join Feed On Item.feed_id = Feed.id Left Join Folder on Folder.id = Feed.folder_id Where Item.id = :id") LiveData getItemById(int id); @@ -79,7 +73,4 @@ public interface ItemDao extends BaseDao { @Query("Update Item set read = :read, starred = :starred Where remoteId = :remoteId") void setReadAndStarState(String remoteId, boolean read, boolean starred); - - @Query("Update Item set starred = :starred Where id = :itemId") - Completable setStarState(int itemId, boolean starred); } diff --git a/db/src/main/java/com/readrops/db/dao/ItemStateChangeDao.kt b/db/src/main/java/com/readrops/db/dao/ItemStateChangeDao.kt index 4a25de7a..8eb6cc3c 100644 --- a/db/src/main/java/com/readrops/db/dao/ItemStateChangeDao.kt +++ b/db/src/main/java/com/readrops/db/dao/ItemStateChangeDao.kt @@ -4,6 +4,7 @@ import androidx.room.Dao import androidx.room.Delete import androidx.room.Insert import androidx.room.Query +import com.readrops.db.entities.Item import com.readrops.db.entities.ItemStateChange import com.readrops.db.pojo.ItemReadStarState import io.reactivex.Completable @@ -27,20 +28,73 @@ interface ItemStateChangeDao : BaseDao { "Left Join ItemState On ItemState.remote_id = Item.remoteId Where ItemStateChange.account_id = :accountId") fun getItemStateChanges(accountId: Int): List - fun upsertItemStateChange(itemStateChange: ItemStateChange) = Completable.create { - if (itemStateChange.readChange && readStateChangeExists(itemStateChange.id) || - itemStateChange.starChange && starStateChangeExists(itemStateChange.id)) { - deleteItemStateChange(itemStateChange) - } else { - insertItemStateChange(itemStateChange) - } - - it.onComplete() - } - @Query("Select Case When :itemId In (Select id From ItemStateChange Where read_change = 1) Then 1 Else 0 End") fun readStateChangeExists(itemId: Int): Boolean @Query("Select Case When :itemId In (Select id From ItemStateChange Where star_change = 1) Then 1 Else 0 End") fun starStateChangeExists(itemId: Int): Boolean + + fun upsertItemReadStateChange(item: Item, accountId: Int) = Completable.create { + if (itemStateChangeExists(item.id, accountId)) { + val oldItemReadState = getItemReadState(item.remoteId, accountId) + val readChange = item.isRead != oldItemReadState + + if (readChange) { + val oldItemStateChange = selectItemStateChange(item.id) + val newReadChange = !oldItemStateChange.readChange + + if (!newReadChange && !oldItemStateChange.starChange) { + deleteItemStateChange(oldItemStateChange) + } else { + updateItemReadStateChange(newReadChange, oldItemStateChange.id) + } + } + } else { + insertItemStateChange(ItemStateChange(id = item.id, readChange = true, accountId = accountId)) + } + + it.onComplete() + } + + fun upsertItemStarStateChange(item: Item, accountId: Int) = Completable.create { + if (itemStateChangeExists(item.id, accountId)) { + val oldItemStarState = getItemStarState(item.remoteId, accountId) + val starChange = item.isStarred != oldItemStarState + + if (starChange) { + val oldItemStateChange = selectItemStateChange(item.id) + val newStarChange = !oldItemStateChange.starChange + + if (!newStarChange && !oldItemStateChange.readChange) { + deleteItemStateChange(oldItemStateChange) + } else { + updateItemStarStateChange(newStarChange, oldItemStateChange.id) + } + } + } else { + insertItemStateChange(ItemStateChange(id = item.id, starChange = true, accountId = accountId)) + } + + + it.onComplete() + } + + @Query("Select * From ItemStateChange Where id = :id") + fun selectItemStateChange(id: Int): ItemStateChange + + @Query("Select case When Exists (Select id, account_id From ItemStateChange Where id = :id And account_id = :accountId) Then 1 else 0 End") + fun itemStateChangeExists(id: Int, accountId: Int): Boolean + + @Query("Select read From ItemState Where remote_id = :remoteId And account_id = :accountId") + fun getItemReadState(remoteId: String, accountId: Int): Boolean + + @Query("Select starred From ItemState Where remote_id = :remoteId And account_id = :accountId") + fun getItemStarState(remoteId: String, accountId: Int): Boolean + + @Query("Update ItemStateChange set read_change = :readChange Where id = :id") + fun updateItemReadStateChange(readChange: Boolean, id: Int) + + @Query("Update ItemStateChange set star_change = :starChange Where id = :id") + fun updateItemStarStateChange(starChange: Boolean, id: Int) + } \ No newline at end of file diff --git a/db/src/main/java/com/readrops/db/dao/ItemStateDao.kt b/db/src/main/java/com/readrops/db/dao/ItemStateDao.kt index 7efa52ef..770da7c8 100644 --- a/db/src/main/java/com/readrops/db/dao/ItemStateDao.kt +++ b/db/src/main/java/com/readrops/db/dao/ItemStateDao.kt @@ -24,6 +24,9 @@ interface ItemStateDao : BaseDao { @Query("Update ItemState set read = :read Where remote_id = :remoteId And account_id = :accountId") fun updateItemReadState(read: Boolean, remoteId: String, accountId: Int) + @Query("Update ItemState set starred = :star Where remote_id = :remoteId And account_id = :accountId") + fun updateItemStarState(star: Boolean, remoteId: String, accountId: Int) + @Query("Select case When Exists (Select remote_id, account_id From ItemState Where remote_id = :remoteId And account_id = :accountId) Then 1 else 0 End") fun itemStateExists(remoteId: String, accountId: Int): Boolean @@ -36,4 +39,14 @@ interface ItemStateDao : BaseDao { it.onComplete() } + + fun upsertItemStarState(itemState: ItemState) = Completable.create { + if (itemStateExists(itemState.remoteId, itemState.accountId)) { + updateItemStarState(itemState.starred, itemState.remoteId, itemState.accountId) + } else { + insertItemState(itemState) + } + + it.onComplete() + } } \ No newline at end of file