From 4539fdff92f9a4dd91f9a3c2599d7b88461688bb Mon Sep 17 00:00:00 2001 From: Shinokuni Date: Wed, 18 Aug 2021 19:04:10 +0200 Subject: [PATCH 01/17] Remove kapt declaration from API module --- api/build.gradle | 1 - 1 file changed, 1 deletion(-) diff --git a/api/build.gradle b/api/build.gradle index 5e4c6f2c..d13bb3e2 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -1,6 +1,5 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' -apply plugin: 'kotlin-kapt' android { compileSdkVersion rootProject.ext.compileSdkVersion From 5d86126f1c3dd6d9e54e47acd3e70903c555cb2b Mon Sep 17 00:00:00 2001 From: Shinokuni Date: Mon, 30 Aug 2021 21:32:23 +0200 Subject: [PATCH 02/17] Update android emulator runner step --- .github/workflows/android.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 8b80ad42..ae7bc216 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -22,7 +22,7 @@ jobs: - name: Build with Gradle run: ./gradlew clean build - name: Android Emulator Runner - uses: ReactiveCircus/android-emulator-runner@v2.19.0 + uses: ReactiveCircus/android-emulator-runner@v2.20.0 with: api-level: 29 script: ./gradlew connectedCheck From 61f8798be51f88d16196419a33b79162d74d6f55 Mon Sep 17 00:00:00 2001 From: Shinokuni Date: Wed, 1 Sep 2021 18:46:54 +0200 Subject: [PATCH 03/17] Migrate Feed entity to kotlin --- .../java/com/readrops/api/opml/OPMLParser.kt | 4 +- .../freshrss/adapters/FreshRSSFeedsAdapter.kt | 2 +- .../adapters/NextNewsFeedsAdapter.kt | 2 +- .../app/utils/feedscolors/FeedColors.kt | 2 +- db/build.gradle | 1 + .../java/com/readrops/db/entities/Feed.java | 271 ------------------ .../java/com/readrops/db/entities/Feed.kt | 31 ++ 7 files changed, 37 insertions(+), 276 deletions(-) delete mode 100644 db/src/main/java/com/readrops/db/entities/Feed.java create mode 100644 db/src/main/java/com/readrops/db/entities/Feed.kt diff --git a/api/src/main/java/com/readrops/api/opml/OPMLParser.kt b/api/src/main/java/com/readrops/api/opml/OPMLParser.kt index e68256bb..0cd1e7c2 100644 --- a/api/src/main/java/com/readrops/api/opml/OPMLParser.kt +++ b/api/src/main/java/com/readrops/api/opml/OPMLParser.kt @@ -108,7 +108,7 @@ object OPMLParser { val feedOutlines = arrayListOf() for (feed in folderAndFeeds.value) { - val feedOutline = Outline(feed.name, feed.url, feed.siteUrl) + val feedOutline = Outline(feed.name, feed.url!!, feed.siteUrl) feedOutlines += feedOutline } @@ -117,7 +117,7 @@ object OPMLParser { outlines += outline } else { for (feed in folderAndFeeds.value) { - outlines += Outline(feed.name, feed.url, feed.siteUrl) + outlines += Outline(feed.name, feed.url!!, feed.siteUrl) } } } diff --git a/api/src/main/java/com/readrops/api/services/freshrss/adapters/FreshRSSFeedsAdapter.kt b/api/src/main/java/com/readrops/api/services/freshrss/adapters/FreshRSSFeedsAdapter.kt index a7c7be4e..e1258c41 100644 --- a/api/src/main/java/com/readrops/api/services/freshrss/adapters/FreshRSSFeedsAdapter.kt +++ b/api/src/main/java/com/readrops/api/services/freshrss/adapters/FreshRSSFeedsAdapter.kt @@ -12,7 +12,7 @@ import com.squareup.moshi.ToJson class FreshRSSFeedsAdapter { @ToJson - fun toJson(feed: Feed): String = "" + fun toJson(feeds: List): String = "" @SuppressLint("CheckResult") @FromJson diff --git a/api/src/main/java/com/readrops/api/services/nextcloudnews/adapters/NextNewsFeedsAdapter.kt b/api/src/main/java/com/readrops/api/services/nextcloudnews/adapters/NextNewsFeedsAdapter.kt index a5ccc6e9..9a523585 100644 --- a/api/src/main/java/com/readrops/api/services/nextcloudnews/adapters/NextNewsFeedsAdapter.kt +++ b/api/src/main/java/com/readrops/api/services/nextcloudnews/adapters/NextNewsFeedsAdapter.kt @@ -14,7 +14,7 @@ import java.net.URI class NextNewsFeedsAdapter { @ToJson - fun toJson(feed: Feed): String = "" + fun toJson(feeds: List): String = "" @SuppressLint("CheckResult") @FromJson diff --git a/app/src/main/java/com/readrops/app/utils/feedscolors/FeedColors.kt b/app/src/main/java/com/readrops/app/utils/feedscolors/FeedColors.kt index 0cc45b23..17a18c7f 100644 --- a/app/src/main/java/com/readrops/app/utils/feedscolors/FeedColors.kt +++ b/app/src/main/java/com/readrops/app/utils/feedscolors/FeedColors.kt @@ -31,7 +31,7 @@ fun getFaviconLink(feed: Feed) { feed.iconUrl = if (feed.iconUrl != null) feed.iconUrl else - HtmlParser.getFaviconLink(feed.siteUrl) + HtmlParser.getFaviconLink(feed.siteUrl!!) } diff --git a/db/build.gradle b/db/build.gradle index f6d28aac..4f0226a9 100644 --- a/db/build.gradle +++ b/db/build.gradle @@ -1,6 +1,7 @@ apply plugin: 'com.android.library' apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' +apply plugin: 'kotlin-parcelize' android { compileSdkVersion rootProject.ext.compileSdkVersion diff --git a/db/src/main/java/com/readrops/db/entities/Feed.java b/db/src/main/java/com/readrops/db/entities/Feed.java deleted file mode 100644 index 10e112be..00000000 --- a/db/src/main/java/com/readrops/db/entities/Feed.java +++ /dev/null @@ -1,271 +0,0 @@ -package com.readrops.db.entities; - - -import android.os.Parcel; -import android.os.Parcelable; - -import androidx.annotation.ColorInt; -import androidx.room.ColumnInfo; -import androidx.room.Entity; -import androidx.room.ForeignKey; -import androidx.room.Ignore; -import androidx.room.PrimaryKey; - -import com.readrops.db.entities.account.Account; - -@Entity(foreignKeys = {@ForeignKey(entity = Folder.class, parentColumns = "id", - childColumns = "folder_id", onDelete = ForeignKey.SET_NULL), - @ForeignKey(entity = Account.class, parentColumns = "id", childColumns = "account_id", - onDelete = ForeignKey.CASCADE)}) -public class Feed implements Parcelable { - - @PrimaryKey(autoGenerate = true) - private int id; - - private String name; - - private String description; - - private String url; - - private String siteUrl; - - private String lastUpdated; - - @ColumnInfo(name = "text_color") - private @ColorInt - int textColor; - - @ColumnInfo(name = "background_color") - private @ColorInt - int backgroundColor; - - @ColumnInfo(name = "icon_url") - private String iconUrl; - - private String etag; - - @ColumnInfo(name = "last_modified") - private String lastModified; - - @ColumnInfo(name = "folder_id", index = true) - private Integer folderId; // nullable foreign key so Integer instead of int - - private String remoteId; // remote id can be string or int - - @ColumnInfo(name = "account_id", index = true) - private int accountId; - - @ColumnInfo(name = "notification_enabled", defaultValue = "1") - private boolean notificationEnabled; - - @Ignore - private int unreadCount; - - @Ignore - private String remoteFolderId; - - public Feed() { - - } - - @Ignore - public Feed(String name, String description, String url) { - this.name = name; - this.description = description; - this.url = url; - } - - protected Feed(Parcel in) { - id = in.readInt(); - name = in.readString(); - description = in.readString(); - url = in.readString(); - siteUrl = in.readString(); - lastUpdated = in.readString(); - textColor = in.readInt(); - backgroundColor = in.readInt(); - iconUrl = in.readString(); - etag = in.readString(); - lastModified = in.readString(); - - int parcelFolderId = in.readInt(); - folderId = parcelFolderId == 0 ? null : parcelFolderId; - - remoteId = in.readString(); - notificationEnabled = in.readByte() != 0; - } - - public static final Creator CREATOR = new Creator() { - @Override - public Feed createFromParcel(Parcel in) { - return new Feed(in); - } - - @Override - public Feed[] newArray(int size) { - return new Feed[size]; - } - }; - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getSiteUrl() { - return siteUrl; - } - - public void setSiteUrl(String siteUrl) { - this.siteUrl = siteUrl; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getLastUpdated() { - return lastUpdated; - } - - public void setLastUpdated(String lastUpdated) { - this.lastUpdated = lastUpdated; - } - - public @ColorInt - int getTextColor() { - return textColor; - } - - public void setTextColor(@ColorInt int textColor) { - this.textColor = textColor; - } - - public @ColorInt - int getBackgroundColor() { - return backgroundColor; - } - - public void setBackgroundColor(@ColorInt int backgroundColor) { - this.backgroundColor = backgroundColor; - } - - public String getIconUrl() { - return iconUrl; - } - - public void setIconUrl(String iconUrl) { - this.iconUrl = iconUrl; - } - - public String getEtag() { - return etag; - } - - public void setEtag(String etag) { - this.etag = etag; - } - - public String getLastModified() { - return lastModified; - } - - public void setLastModified(String lastModified) { - this.lastModified = lastModified; - } - - public Integer getFolderId() { - return folderId; - } - - public void setFolderId(Integer folderId) { - this.folderId = folderId; - } - - public int getUnreadCount() { - return unreadCount; - } - - public void setUnreadCount(int unreadCount) { - this.unreadCount = unreadCount; - } - - public String getRemoteId() { - return remoteId; - } - - public void setRemoteId(String remoteId) { - this.remoteId = remoteId; - } - - public int getAccountId() { - return accountId; - } - - public void setAccountId(int accountId) { - this.accountId = accountId; - } - - public boolean isNotificationEnabled() { - return notificationEnabled; - } - - public void setNotificationEnabled(boolean notificationEnabled) { - this.notificationEnabled = notificationEnabled; - } - - public String getRemoteFolderId() { - return remoteFolderId; - } - - public void setRemoteFolderId(String remoteFolderId) { - this.remoteFolderId = remoteFolderId; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(id); - dest.writeString(name); - dest.writeString(description); - dest.writeString(url); - dest.writeString(siteUrl); - dest.writeString(lastUpdated); - dest.writeInt(textColor); - dest.writeInt(backgroundColor); - dest.writeString(iconUrl); - dest.writeString(etag); - dest.writeString(lastModified); - dest.writeInt(folderId == null ? 0 : folderId); - dest.writeString(remoteId); - dest.writeByte((byte) (notificationEnabled ? 1 : 0)); - } -} diff --git a/db/src/main/java/com/readrops/db/entities/Feed.kt b/db/src/main/java/com/readrops/db/entities/Feed.kt new file mode 100644 index 00000000..806d4d44 --- /dev/null +++ b/db/src/main/java/com/readrops/db/entities/Feed.kt @@ -0,0 +1,31 @@ +package com.readrops.db.entities + +import android.os.Parcelable +import androidx.annotation.ColorInt +import androidx.room.* +import com.readrops.db.entities.account.Account +import kotlinx.parcelize.Parcelize + +@Parcelize +@Entity(foreignKeys = [ForeignKey(entity = Folder::class, parentColumns = ["id"], childColumns = ["folder_id"], + onDelete = ForeignKey.SET_NULL), ForeignKey(entity = Account::class, parentColumns = ["id"], + childColumns = ["account_id"], onDelete = ForeignKey.CASCADE)]) +data class Feed( + @PrimaryKey(autoGenerate = true) var id: Int = 0, + var name: String? = null, + var description: String? = null, + var url: String? = null, + var siteUrl: String? = null, + var lastUpdated: String? = null, + @ColumnInfo(name = "text_color") @ColorInt var textColor: Int = 0, + @ColumnInfo(name = "background_color") @ColorInt var backgroundColor: Int = 0, + @ColumnInfo(name = "icon_url") var iconUrl: String? = null, + var etag: String? = null, + @ColumnInfo(name = "last_modified") var lastModified: String? = null, + @ColumnInfo(name = "folder_id", index = true) var folderId: Int? = null, + var remoteId: String? = null, + @ColumnInfo(name = "account_id", index = true) var accountId: Int = 0, + @ColumnInfo(name = "notification_enabled", defaultValue = "1") var isNotificationEnabled: Boolean = false, + @Ignore var unreadCount: Int = 0, + @Ignore var remoteFolderId: String? = null, +) : Parcelable \ No newline at end of file From 40c3a52948306dd9fde36742444788f85cae49cb Mon Sep 17 00:00:00 2001 From: Shinokuni Date: Wed, 1 Sep 2021 19:01:32 +0200 Subject: [PATCH 04/17] Migrate Folder entity to kotlin --- .../java/com/readrops/api/opml/OPMLParser.kt | 2 +- .../adapters/FreshRSSFoldersAdapter.kt | 2 +- .../adapters/NextNewsFoldersAdapter.kt | 2 +- .../ManageFeedsFoldersActivity.java | 3 +- .../java/com/readrops/db/dao/FeedDao.java | 2 +- .../java/com/readrops/db/entities/Folder.java | 123 ------------------ .../java/com/readrops/db/entities/Folder.kt | 22 ++++ 7 files changed, 28 insertions(+), 128 deletions(-) delete mode 100644 db/src/main/java/com/readrops/db/entities/Folder.java create mode 100644 db/src/main/java/com/readrops/db/entities/Folder.kt diff --git a/api/src/main/java/com/readrops/api/opml/OPMLParser.kt b/api/src/main/java/com/readrops/api/opml/OPMLParser.kt index 0cd1e7c2..6a0c8c93 100644 --- a/api/src/main/java/com/readrops/api/opml/OPMLParser.kt +++ b/api/src/main/java/com/readrops/api/opml/OPMLParser.kt @@ -71,7 +71,7 @@ object OPMLParser { if ((outline.outlines != null && !outline.outlines?.isEmpty()!!) || outline.xmlUrl.isNullOrEmpty()) { // if the outline doesn't have text or title value but contains sub outlines, // those sub outlines will be considered as not belonging to any folder and join the others at the top level of the hierarchy - val folder = if (outline.name != null) Folder(outline.name) else null + val folder = if (outline.name != null) Folder(name = outline.name) else null outline.outlines?.forEach { val recursiveFeedsFolders = parseOutline(it) diff --git a/api/src/main/java/com/readrops/api/services/freshrss/adapters/FreshRSSFoldersAdapter.kt b/api/src/main/java/com/readrops/api/services/freshrss/adapters/FreshRSSFoldersAdapter.kt index c89aa499..8d044eb4 100644 --- a/api/src/main/java/com/readrops/api/services/freshrss/adapters/FreshRSSFoldersAdapter.kt +++ b/api/src/main/java/com/readrops/api/services/freshrss/adapters/FreshRSSFoldersAdapter.kt @@ -12,7 +12,7 @@ import java.util.* class FreshRSSFoldersAdapter { @ToJson - fun toJson(folder: Folder): String = "" + fun toJson(folders: List): String = "" @SuppressLint("CheckResult") @FromJson diff --git a/api/src/main/java/com/readrops/api/services/nextcloudnews/adapters/NextNewsFoldersAdapter.kt b/api/src/main/java/com/readrops/api/services/nextcloudnews/adapters/NextNewsFoldersAdapter.kt index 0c81d7dc..a8849472 100644 --- a/api/src/main/java/com/readrops/api/services/nextcloudnews/adapters/NextNewsFoldersAdapter.kt +++ b/api/src/main/java/com/readrops/api/services/nextcloudnews/adapters/NextNewsFoldersAdapter.kt @@ -11,7 +11,7 @@ import com.squareup.moshi.ToJson class NextNewsFoldersAdapter { @ToJson - fun toJson(folder: Folder): String = "" + fun toJson(folders: List): String = "" @SuppressLint("CheckResult") @FromJson diff --git a/app/src/main/java/com/readrops/app/feedsfolders/ManageFeedsFoldersActivity.java b/app/src/main/java/com/readrops/app/feedsfolders/ManageFeedsFoldersActivity.java index 7b79f1a4..6940e3c3 100644 --- a/app/src/main/java/com/readrops/app/feedsfolders/ManageFeedsFoldersActivity.java +++ b/app/src/main/java/com/readrops/app/feedsfolders/ManageFeedsFoldersActivity.java @@ -90,7 +90,8 @@ public class ManageFeedsFoldersActivity extends AppCompatActivity { .title(R.string.add_folder) .positiveText(R.string.validate) .input(R.string.folder, 0, (dialog, input) -> { - Folder folder = new Folder(input.toString()); + Folder folder = new Folder(); + folder.setName(input.toString()); folder.setAccountId(account.getId()); viewModel.addFolder(folder) diff --git a/db/src/main/java/com/readrops/db/dao/FeedDao.java b/db/src/main/java/com/readrops/db/dao/FeedDao.java index af171860..072a4b5b 100644 --- a/db/src/main/java/com/readrops/db/dao/FeedDao.java +++ b/db/src/main/java/com/readrops/db/dao/FeedDao.java @@ -63,7 +63,7 @@ public abstract class FeedDao implements BaseDao { public abstract void updateColors(int feedId, int textColor, int bgColor); @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH) - @Query("Select Feed.name as feed_name, Feed.id as feed_id, Folder.name as folder_name, Folder.id as folder_id, Folder.remoteId as folder_remoteId," + + @Query("Select Feed.name as feed_name, Feed.id as feed_id, Folder.name as folder_name, Folder.id as folder_id, Folder.remoteId as folder_remoteId, Folder.account_id as folder_account_id," + "Feed.description as feed_description, Feed.icon_url as feed_icon_url, Feed.url as feed_url, Feed.folder_id as feed_folder_id" + ", Feed.siteUrl as feed_siteUrl, Feed.remoteId as feed_remoteId from Feed Left Join Folder on Feed.folder_id = Folder.id Where Feed.account_id = :accountId Order by Feed.name") public abstract LiveData> getAllFeedsWithFolder(int accountId); diff --git a/db/src/main/java/com/readrops/db/entities/Folder.java b/db/src/main/java/com/readrops/db/entities/Folder.java deleted file mode 100644 index f03c081e..00000000 --- a/db/src/main/java/com/readrops/db/entities/Folder.java +++ /dev/null @@ -1,123 +0,0 @@ -package com.readrops.db.entities; - -import android.os.Parcel; -import android.os.Parcelable; - -import androidx.room.ColumnInfo; -import androidx.room.Entity; -import androidx.room.ForeignKey; -import androidx.room.Ignore; -import androidx.room.PrimaryKey; - -import com.readrops.db.entities.account.Account; - -import java.util.Objects; - -@Entity(foreignKeys = @ForeignKey(entity = Account.class, parentColumns = "id", - childColumns = "account_id", onDelete = ForeignKey.CASCADE)) -public class Folder implements Parcelable, Comparable { - - @PrimaryKey(autoGenerate = true) - private int id; - - private String name; - - private String remoteId; - - @ColumnInfo(name = "account_id", index = true) - private int accountId; - - public Folder() { - - } - - @Ignore - public Folder(String name) { - this.name = name; - } - - protected Folder(Parcel in) { - id = in.readInt(); - name = in.readString(); - } - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getRemoteId() { - return remoteId; - } - - public void setRemoteId(String remoteId) { - this.remoteId = remoteId; - } - - public int getAccountId() { - return accountId; - } - - public void setAccountId(int accountId) { - this.accountId = accountId; - } - - public static final Creator CREATOR = new Creator() { - @Override - public Folder createFromParcel(Parcel in) { - return new Folder(in); - } - - @Override - public Folder[] newArray(int size) { - return new Folder[size]; - } - }; - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(id); - dest.writeString(name); - } - - @Override - public boolean equals(Object o) { - if (o == null) { - return false; - } else if (!(o instanceof Folder)) { - return false; - } else { - Folder folder = (Folder) o; - - return id == folder.id && Objects.equals(name, folder.name) && - Objects.equals(remoteId, folder.remoteId) && - accountId == folder.accountId; - } - } - - @Override - public int hashCode() { - return Objects.hash(id, name, remoteId, accountId); - } - - @Override - public int compareTo(Folder o) { - return this.getName().compareTo(o.getName()); - } -} diff --git a/db/src/main/java/com/readrops/db/entities/Folder.kt b/db/src/main/java/com/readrops/db/entities/Folder.kt new file mode 100644 index 00000000..4462ac29 --- /dev/null +++ b/db/src/main/java/com/readrops/db/entities/Folder.kt @@ -0,0 +1,22 @@ +package com.readrops.db.entities + +import android.os.Parcelable +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.ForeignKey +import androidx.room.PrimaryKey +import com.readrops.db.entities.account.Account +import kotlinx.parcelize.Parcelize + +@Parcelize +@Entity(foreignKeys = [ForeignKey(entity = Account::class, parentColumns = ["id"], + childColumns = ["account_id"], onDelete = ForeignKey.CASCADE)]) +data class Folder( + @PrimaryKey(autoGenerate = true) var id: Int = 0, + var name: String? = null, + var remoteId: String? = null, + @ColumnInfo(name = "account_id", index = true) var accountId: Int = 0, +) : Parcelable, Comparable { + + override fun compareTo(other: Folder): Int = this.name!!.compareTo(other.name!!) +} \ No newline at end of file From 6b2a279813d09f122e6046f48956f8afe2f2eb60 Mon Sep 17 00:00:00 2001 From: Shinokuni Date: Wed, 1 Sep 2021 19:17:38 +0200 Subject: [PATCH 05/17] Migrate Item entity to kotlin --- .../app/itemslist/MainItemListAdapter.java | 6 +- .../com/readrops/db/dao/ItemStateChangeDao.kt | 8 +- .../java/com/readrops/db/entities/Item.java | 211 ------------------ .../java/com/readrops/db/entities/Item.kt | 38 ++++ 4 files changed, 45 insertions(+), 218 deletions(-) delete mode 100644 db/src/main/java/com/readrops/db/entities/Item.java create mode 100644 db/src/main/java/com/readrops/db/entities/Item.kt diff --git a/app/src/main/java/com/readrops/app/itemslist/MainItemListAdapter.java b/app/src/main/java/com/readrops/app/itemslist/MainItemListAdapter.java index 65f4c2f0..1476bf21 100644 --- a/app/src/main/java/com/readrops/app/itemslist/MainItemListAdapter.java +++ b/app/src/main/java/com/readrops/app/itemslist/MainItemListAdapter.java @@ -218,7 +218,7 @@ public class MainItemListAdapter extends PagedListAdapter getPreloadItems(int position) { - if (getItem(position).getItem().hasImage()) { + if (getItem(position).getItem().getHasImage()) { String url = getItem(position).getItem().getImageLink(); return Collections.singletonList(url); } else { @@ -296,13 +296,13 @@ public class MainItemListAdapter extends PagedListAdapter { fun upsertItemReadStateChange(item: Item, accountId: Int, useSeparateState: Boolean) = Completable.create { if (itemStateChangeExists(item.id, accountId)) { val oldItemReadState = if (useSeparateState) - getItemReadState(item.remoteId, accountId) + getItemReadState(item.remoteId!!, accountId) else - getStandardItemReadState(item.remoteId, accountId) + getStandardItemReadState(item.remoteId!!, accountId) val readChange = item.isRead != oldItemReadState @@ -69,9 +69,9 @@ interface ItemStateChangeDao : BaseDao { fun upsertItemStarStateChange(item: Item, accountId: Int, useSeparateState: Boolean) = Completable.create { if (itemStateChangeExists(item.id, accountId)) { val oldItemStarState = if (useSeparateState) - getItemStarState(item.remoteId, accountId) + getItemStarState(item.remoteId!!, accountId) else - getStandardItemStarState(item.remoteId, accountId) + getStandardItemStarState(item.remoteId!!, accountId) val starChange = item.isStarred != oldItemStarState diff --git a/db/src/main/java/com/readrops/db/entities/Item.java b/db/src/main/java/com/readrops/db/entities/Item.java deleted file mode 100644 index b722574d..00000000 --- a/db/src/main/java/com/readrops/db/entities/Item.java +++ /dev/null @@ -1,211 +0,0 @@ -package com.readrops.db.entities; - -import androidx.room.ColumnInfo; -import androidx.room.Entity; -import androidx.room.ForeignKey; -import androidx.room.Ignore; -import androidx.room.PrimaryKey; - -import org.joda.time.LocalDateTime; - -import static androidx.room.ForeignKey.CASCADE; - - -@Entity(foreignKeys = @ForeignKey(entity = Feed.class, parentColumns = "id", childColumns = "feed_id", onDelete = CASCADE)) -public class Item implements Comparable { - - @PrimaryKey(autoGenerate = true) - private int id; - - private String title; - - private String description; - - @ColumnInfo(name = "clean_description") - private String cleanDescription; - - private String link; - - @ColumnInfo(name = "image_link") - private String imageLink; - - private String author; - - @ColumnInfo(name = "pub_date") - private LocalDateTime pubDate; - - private String content; - - @ColumnInfo(name = "feed_id", index = true) - private int feedId; - - @ColumnInfo(index = true) - private String guid; - - @ColumnInfo(name = "read_time") - private double readTime; - - private boolean read; - - private boolean starred; - - @ColumnInfo(name = "read_it_later") - private boolean readItLater; - - private String remoteId; - - @Ignore - private String feedRemoteId; - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getCleanDescription() { - return cleanDescription; - } - - public void setCleanDescription(String cleanDescription) { - this.cleanDescription = cleanDescription; - } - - public String getLink() { - return link; - } - - public void setLink(String link) { - this.link = link; - } - - public String getImageLink() { - return imageLink; - } - - public void setImageLink(String imageLink) { - this.imageLink = imageLink; - } - - public String getAuthor() { - return author; - } - - public void setAuthor(String author) { - this.author = author; - } - - public LocalDateTime getPubDate() { - return pubDate; - } - - public void setPubDate(LocalDateTime pubDate) { - this.pubDate = pubDate; - } - - public String getContent() { - return content; - } - - public void setContent(String content) { - this.content = content; - } - - public String getGuid() { - return guid; - } - - public void setGuid(String guid) { - this.guid = guid; - } - - public int getFeedId() { - return feedId; - } - - public void setFeedId(int feedId) { - this.feedId = feedId; - } - - public boolean hasImage() { - return getImageLink() != null; - } - - public double getReadTime() { - return readTime; - } - - public void setReadTime(double readTime) { - this.readTime = readTime; - } - - public String getText() { - if (content != null) - return content; - else - return description; - } - - public boolean isRead() { - return read; - } - - public void setRead(boolean read) { - this.read = read; - } - - public boolean isStarred() { - return starred; - } - - public void setStarred(boolean starred) { - this.starred = starred; - } - - public boolean isReadItLater() { - return readItLater; - } - - public void setReadItLater(boolean readItLater) { - this.readItLater = readItLater; - } - - public String getRemoteId() { - return remoteId; - } - - public void setRemoteId(String remoteId) { - this.remoteId = remoteId; - } - - public String getFeedRemoteId() { - return feedRemoteId; - } - - public void setFeedRemoteId(String feedRemoteId) { - this.feedRemoteId = feedRemoteId; - } - - @Override - public int compareTo(Item o) { - return this.pubDate.compareTo(o.getPubDate()); - } -} diff --git a/db/src/main/java/com/readrops/db/entities/Item.kt b/db/src/main/java/com/readrops/db/entities/Item.kt new file mode 100644 index 00000000..c96c558a --- /dev/null +++ b/db/src/main/java/com/readrops/db/entities/Item.kt @@ -0,0 +1,38 @@ +package com.readrops.db.entities + +import android.os.Parcelable +import androidx.room.* +import kotlinx.parcelize.Parcelize +import org.joda.time.LocalDateTime + +@Parcelize +@Entity(foreignKeys = [ForeignKey(entity = Feed::class, parentColumns = ["id"], + childColumns = ["feed_id"], onDelete = ForeignKey.CASCADE)]) +data class Item( + @PrimaryKey(autoGenerate = true) var id: Int = 0, + var title: String? = null, + var description: String? = null, + @ColumnInfo(name = "clean_description") var cleanDescription: String? = null, + var link: String? = null, + @ColumnInfo(name = "image_link") var imageLink: String? = null, + var author: String? = null, + @ColumnInfo(name = "pub_date") var pubDate: LocalDateTime? = null, + var content: String? = null, + @ColumnInfo(name = "feed_id", index = true) var feedId: Int = 0, + @ColumnInfo(index = true) var guid: String? = null, + @ColumnInfo(name = "read_time") var readTime: Double = 0.0, + @ColumnInfo(name = "read") var isRead: Boolean = false, + @ColumnInfo(name = "starred") var isStarred: Boolean = false, + @ColumnInfo(name = "read_it_later") var isReadItLater: Boolean = false, + var remoteId: String? = null, + @Ignore var feedRemoteId: String? = null, +) : Parcelable, Comparable { + + val text + get() = if (content != null) content else description + + val hasImage + get() = imageLink != null + + override fun compareTo(other: Item): Int = this.pubDate!!.compareTo(other.pubDate) +} \ No newline at end of file From 1654d3221197cc97d12ce9a3218365f822fc89f0 Mon Sep 17 00:00:00 2001 From: Shinokuni Date: Wed, 1 Sep 2021 19:41:45 +0200 Subject: [PATCH 06/17] MIgrate Account entity to kotlin --- .../com/readrops/api/services/Credentials.kt | 2 +- .../notifications/sync/SyncResultAnalyser.kt | 2 +- .../readrops/db/entities/account/Account.java | 230 ------------------ .../readrops/db/entities/account/Account.kt | 43 ++++ 4 files changed, 45 insertions(+), 232 deletions(-) delete mode 100644 db/src/main/java/com/readrops/db/entities/account/Account.java create mode 100644 db/src/main/java/com/readrops/db/entities/account/Account.kt diff --git a/api/src/main/java/com/readrops/api/services/Credentials.kt b/api/src/main/java/com/readrops/api/services/Credentials.kt index 38a223f4..a20eacb7 100644 --- a/api/src/main/java/com/readrops/api/services/Credentials.kt +++ b/api/src/main/java/com/readrops/api/services/Credentials.kt @@ -12,7 +12,7 @@ abstract class Credentials(val authorization: String?, val url: String) { companion object { @JvmStatic fun toCredentials(account: Account): Credentials { - val endPoint = getEndPoint(account.accountType) + val endPoint = getEndPoint(account.accountType!!) return when (account.accountType) { AccountType.NEXTCLOUD_NEWS -> NextNewsCredentials(account.login, account.password, account.url + endPoint) diff --git a/app/src/main/java/com/readrops/app/notifications/sync/SyncResultAnalyser.kt b/app/src/main/java/com/readrops/app/notifications/sync/SyncResultAnalyser.kt index b957e24b..5975c6cf 100644 --- a/app/src/main/java/com/readrops/app/notifications/sync/SyncResultAnalyser.kt +++ b/app/src/main/java/com/readrops/app/notifications/sync/SyncResultAnalyser.kt @@ -51,7 +51,7 @@ class SyncResultAnalyser(val context: Context, private val syncResults: Map 1 && itemCount > 1) { notifContent.title = account.accountName notifContent.content = context.getString(R.string.new_items, itemCount.toString()) - notifContent.largeIcon = Utils.getBitmapFromDrawable(ContextCompat.getDrawable(context, account.accountType.iconRes)) + notifContent.largeIcon = Utils.getBitmapFromDrawable(ContextCompat.getDrawable(context, account.accountType!!.iconRes)) } else if (feedsIdsForNewItems.size == 1) // new items from only one feed from one account oneFeedCase(feedsIdsForNewItems.first(), syncResult.items) else if (itemCount == 1) diff --git a/db/src/main/java/com/readrops/db/entities/account/Account.java b/db/src/main/java/com/readrops/db/entities/account/Account.java deleted file mode 100644 index 1e37ecc8..00000000 --- a/db/src/main/java/com/readrops/db/entities/account/Account.java +++ /dev/null @@ -1,230 +0,0 @@ -package com.readrops.db.entities.account; - -import android.os.Parcel; -import android.os.Parcelable; - -import androidx.annotation.Nullable; -import androidx.room.ColumnInfo; -import androidx.room.Entity; -import androidx.room.Ignore; -import androidx.room.PrimaryKey; - -@Entity -public class Account implements Parcelable { - - @PrimaryKey(autoGenerate = true) - private int id; - - private String url; - - @ColumnInfo(name = "account_name") - private String accountName; - - @ColumnInfo(name = "displayed_name") - private String displayedName; - - @ColumnInfo(name = "account_type") - private AccountType accountType; - - @ColumnInfo(name = "last_modified") - private long lastModified; - - @ColumnInfo(name = "current_account") - private boolean currentAccount; - - private String token; - private String writeToken; // TODO : see if there is a better solution to store specific service account fields - - @ColumnInfo(name = "notifications_enabled") - private boolean notificationsEnabled; - - @Ignore - private String login; - - @Ignore - private String password; - - public Account() { - } - - @Ignore - public Account(String url, String accountName, AccountType accountType) { - this.url = url; - this.accountName = accountName; - this.accountType = accountType; - } - - protected Account(Parcel in) { - id = in.readInt(); - url = in.readString(); - accountName = in.readString(); - accountType = AccountType.values()[in.readInt()]; - displayedName = in.readString(); - lastModified = in.readLong(); - currentAccount = in.readByte() != 0; - login = in.readString(); - password = in.readString(); - token = in.readString(); - writeToken = in.readString(); - notificationsEnabled = in.readByte() != 0; - } - - public static final Creator CREATOR = new Creator() { - @Override - public Account createFromParcel(Parcel in) { - return new Account(in); - } - - @Override - public Account[] newArray(int size) { - return new Account[size]; - } - }; - - public int getId() { - return id; - } - - public void setId(int id) { - this.id = id; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getAccountName() { - return accountName; - } - - public void setAccountName(String accountName) { - this.accountName = accountName; - } - - public String getDisplayedName() { - return displayedName; - } - - public void setDisplayedName(String displayedName) { - this.displayedName = displayedName; - } - - public AccountType getAccountType() { - return accountType; - } - - public void setAccountType(AccountType accountType) { - this.accountType = accountType; - } - - public long getLastModified() { - return lastModified; - } - - public void setLastModified(long lastModified) { - this.lastModified = lastModified; - } - - public boolean isCurrentAccount() { - return currentAccount; - } - - public void setCurrentAccount(boolean currentAccount) { - this.currentAccount = currentAccount; - } - - public String getLogin() { - return login; - } - - public void setLogin(String login) { - this.login = login; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public String getLoginKey() { - return accountType.name() + "_login_" + id; - } - - public String getPasswordKey() { - return accountType.name() + "_password_" + id; - } - - public String getToken() { - return token; - } - - public void setToken(String token) { - this.token = token; - } - - public String getWriteToken() { - return writeToken; - } - - public void setWriteToken(String writeToken) { - this.writeToken = writeToken; - } - - public boolean isNotificationsEnabled() { - return notificationsEnabled; - } - - public void setNotificationsEnabled(boolean notificationsEnabled) { - this.notificationsEnabled = notificationsEnabled; - } - - public AccountConfig getConfig() { - return accountType.getAccountConfig(); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(id); - dest.writeString(url); - dest.writeString(accountName); - dest.writeInt(accountType.ordinal()); - dest.writeString(displayedName); - dest.writeLong(lastModified); - dest.writeByte((byte) (currentAccount ? 1 : 0)); - dest.writeString(login); - dest.writeString(password); - dest.writeString(token); - dest.writeString(writeToken); - dest.writeByte((byte) (notificationsEnabled ? 1 : 0)); - } - - public boolean isLocal() { - return accountType == AccountType.LOCAL; - } - - public boolean is(AccountType accountType) { - return this.accountType == accountType; - } - - @Override - public boolean equals(@Nullable Object obj) { - if (obj == null) - return false; - else if (!(obj instanceof Account)) - return false; - else - return this.id == ((Account) obj).getId(); - } -} diff --git a/db/src/main/java/com/readrops/db/entities/account/Account.kt b/db/src/main/java/com/readrops/db/entities/account/Account.kt new file mode 100644 index 00000000..c6fc2f10 --- /dev/null +++ b/db/src/main/java/com/readrops/db/entities/account/Account.kt @@ -0,0 +1,43 @@ +package com.readrops.db.entities.account + +import android.os.Parcelable +import androidx.room.ColumnInfo +import androidx.room.Entity +import androidx.room.Ignore +import androidx.room.PrimaryKey +import kotlinx.parcelize.Parcelize + +@Parcelize +@Entity +data class Account( + @PrimaryKey(autoGenerate = true) var id: Int = 0, + var url: String? = null, + @ColumnInfo(name = "account_name") var accountName: String? = null, + @ColumnInfo(name = "displayed_name") var displayedName: String? = null, + @ColumnInfo(name = "account_type") var accountType: AccountType? = null, + @ColumnInfo(name = "last_modified") var lastModified: Long = 0, + @ColumnInfo(name = "current_account") var isCurrentAccount: Boolean = false, + var token: String? = null, + var writeToken: String? = null, // TODO : see if there is a better solution to store specific service account fields + @ColumnInfo(name = "notifications_enabled") var isNotificationsEnabled: Boolean = false, + @Ignore var login: String? = null, + @Ignore var password: String? = null, +) : Parcelable { + + constructor(accountUrl: String?, accountName: String, accountType: AccountType): + this(url = accountUrl, accountName = accountName, accountType = accountType) + + val config: AccountConfig + get() = accountType!!.accountConfig + + val isLocal + get() = accountType == AccountType.LOCAL + + fun `is`(accountType: AccountType) = this.accountType == accountType + + val loginKey + get() = accountType!!.name + "_login_" + id + + val passwordKey + get() = accountType!!.name + "_password_" + id +} \ No newline at end of file From 80404bb648bc5b4a403520750ff381fe4b8b662a Mon Sep 17 00:00:00 2001 From: Shinokuni Date: Wed, 1 Sep 2021 21:22:07 +0200 Subject: [PATCH 07/17] Migrate AccountConfig and AccountType to kotlin --- .../app/account/AccountTypeListActivity.java | 4 +- .../app/account/AccountTypeListAdapter.java | 2 +- .../app/account/AddAccountActivity.java | 6 +- .../app/addfeed/AccountArrayAdapter.java | 2 +- .../com/readrops/app/item/ItemViewModel.java | 2 +- .../readrops/app/itemslist/MainViewModel.java | 2 +- .../app/repositories/ARepository.java | 4 +- .../readrops/db/entities/account/Account.kt | 2 +- .../db/entities/account/AccountConfig.java | 90 ------------------- .../db/entities/account/AccountConfig.kt | 39 ++++++++ .../db/entities/account/AccountType.java | 65 -------------- .../db/entities/account/AccountType.kt | 17 ++++ 12 files changed, 68 insertions(+), 167 deletions(-) delete mode 100644 db/src/main/java/com/readrops/db/entities/account/AccountConfig.java create mode 100644 db/src/main/java/com/readrops/db/entities/account/AccountConfig.kt delete mode 100644 db/src/main/java/com/readrops/db/entities/account/AccountType.java create mode 100644 db/src/main/java/com/readrops/db/entities/account/AccountType.kt diff --git a/app/src/main/java/com/readrops/app/account/AccountTypeListActivity.java b/app/src/main/java/com/readrops/app/account/AccountTypeListActivity.java index c197eba7..92af2f99 100644 --- a/app/src/main/java/com/readrops/app/account/AccountTypeListActivity.java +++ b/app/src/main/java/com/readrops/app/account/AccountTypeListActivity.java @@ -79,7 +79,7 @@ public class AccountTypeListActivity extends AppCompatActivity { startActivity(intent); finish(); } else { - Account account = new Account(null, getString(AccountType.LOCAL.getName()), AccountType.LOCAL); + Account account = new Account(null, getString(AccountType.LOCAL.getTypeName()), AccountType.LOCAL); account.setCurrentAccount(true); viewModel.insert(account) @@ -150,7 +150,7 @@ public class AccountTypeListActivity extends AppCompatActivity { } private void parseOPMLFile(Uri uri, MaterialDialog dialog) { - Account account = new Account(null, getString(AccountType.LOCAL.getName()), AccountType.LOCAL); + Account account = new Account(null, getString(AccountType.LOCAL.getTypeName()), AccountType.LOCAL); account.setCurrentAccount(true); viewModel.insert(account) diff --git a/app/src/main/java/com/readrops/app/account/AccountTypeListAdapter.java b/app/src/main/java/com/readrops/app/account/AccountTypeListAdapter.java index 3b93d325..1d03e17d 100644 --- a/app/src/main/java/com/readrops/app/account/AccountTypeListAdapter.java +++ b/app/src/main/java/com/readrops/app/account/AccountTypeListAdapter.java @@ -33,7 +33,7 @@ public class AccountTypeListAdapter extends RecyclerView.Adapter listener.onItemClick(accountType)); diff --git a/app/src/main/java/com/readrops/app/account/AddAccountActivity.java b/app/src/main/java/com/readrops/app/account/AddAccountActivity.java index 23f11283..9226c23c 100644 --- a/app/src/main/java/com/readrops/app/account/AddAccountActivity.java +++ b/app/src/main/java/com/readrops/app/account/AddAccountActivity.java @@ -65,8 +65,8 @@ public class AddAccountActivity extends AppCompatActivity { fillFields(); } else { binding.providerImage.setImageResource(accountType.getIconRes()); - binding.providerName.setText(accountType.getName()); - binding.addAccountName.setText(accountType.getName()); + binding.providerName.setText(accountType.getTypeName()); + binding.addAccountName.setText(accountType.getTypeName()); if (accountType == AccountType.FRESHRSS) { binding.addAccountPasswordLayout.setHelperText(getString(R.string.password_helper)); @@ -178,7 +178,7 @@ public class AddAccountActivity extends AppCompatActivity { private void fillFields() { binding.providerImage.setImageResource(accountToEdit.getAccountType().getIconRes()); - binding.providerName.setText(accountToEdit.getAccountType().getName()); + binding.providerName.setText(accountToEdit.getAccountType().getTypeName()); binding.addAccountUrl.setText(accountToEdit.getUrl()); binding.addAccountName.setText(accountToEdit.getAccountName()); diff --git a/app/src/main/java/com/readrops/app/addfeed/AccountArrayAdapter.java b/app/src/main/java/com/readrops/app/addfeed/AccountArrayAdapter.java index af594ea1..5be62acf 100644 --- a/app/src/main/java/com/readrops/app/addfeed/AccountArrayAdapter.java +++ b/app/src/main/java/com/readrops/app/addfeed/AccountArrayAdapter.java @@ -44,7 +44,7 @@ public class AccountArrayAdapter extends ArrayAdapter { TextView accountName = convertView.findViewById(R.id.account_type_name); accountIcon.setImageResource(account.getAccountType().getIconRes()); - accountName.setText(account.getAccountType().getName()); + accountName.setText(account.getAccountType().getTypeName()); return convertView; } 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 9fddfe78..7d7ce6c3 100644 --- a/app/src/main/java/com/readrops/app/item/ItemViewModel.java +++ b/app/src/main/java/com/readrops/app/item/ItemViewModel.java @@ -41,7 +41,7 @@ public class ItemViewModel extends ViewModel { public LiveData getItemById(int id) { return database.itemDao().getItemById(ItemSelectionQueryBuilder.buildQuery(id, - account.getConfig().useSeparateState())); + account.getConfig().getUseSeparateState())); } public Completable setStarState(Item item) { diff --git a/app/src/main/java/com/readrops/app/itemslist/MainViewModel.java b/app/src/main/java/com/readrops/app/itemslist/MainViewModel.java index f9c46dd1..e22b0906 100644 --- a/app/src/main/java/com/readrops/app/itemslist/MainViewModel.java +++ b/app/src/main/java/com/readrops/app/itemslist/MainViewModel.java @@ -70,7 +70,7 @@ public class MainViewModel extends ViewModel { } DataSource.Factory items; - items = database.itemDao().selectAll(ItemsQueryBuilder.buildItemsQuery(queryFilters, currentAccount.getConfig().useSeparateState())); + items = database.itemDao().selectAll(ItemsQueryBuilder.buildItemsQuery(queryFilters, currentAccount.getConfig().getUseSeparateState())); lastFetch = new LivePagedListBuilder<>(new RoomFactoryWrapper<>(items), new PagedList.Config.Builder() 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 45839309..89f9bb13 100644 --- a/app/src/main/java/com/readrops/app/repositories/ARepository.java +++ b/app/src/main/java/com/readrops/app/repositories/ARepository.java @@ -115,7 +115,7 @@ public abstract class ARepository { } public Completable setItemReadState(Item item) { - if (account.getConfig().useSeparateState()) { + if (account.getConfig().getUseSeparateState()) { return database.itemStateChangesDao().upsertItemReadStateChange(item, account.getId(), true) .andThen(database.itemStateDao().upsertItemReadState(new ItemState(0, item.isRead(), item.isStarred(), item.getRemoteId(), account.getId()))); @@ -145,7 +145,7 @@ public abstract class ARepository { } public Completable setItemStarState(Item item) { - if (account.getConfig().useSeparateState()) { + if (account.getConfig().getUseSeparateState()) { return database.itemStateChangesDao().upsertItemStarStateChange(item, account.getId(), true) .andThen(database.itemStateDao().upsertItemStarState(new ItemState(0, item.isRead(), item.isStarred(), item.getRemoteId(), account.getId()))); diff --git a/db/src/main/java/com/readrops/db/entities/account/Account.kt b/db/src/main/java/com/readrops/db/entities/account/Account.kt index c6fc2f10..978051cd 100644 --- a/db/src/main/java/com/readrops/db/entities/account/Account.kt +++ b/db/src/main/java/com/readrops/db/entities/account/Account.kt @@ -28,7 +28,7 @@ data class Account( this(url = accountUrl, accountName = accountName, accountType = accountType) val config: AccountConfig - get() = accountType!!.accountConfig + get() = accountType!!.accountConfig!! val isLocal get() = accountType == AccountType.LOCAL diff --git a/db/src/main/java/com/readrops/db/entities/account/AccountConfig.java b/db/src/main/java/com/readrops/db/entities/account/AccountConfig.java deleted file mode 100644 index 7474c10c..00000000 --- a/db/src/main/java/com/readrops/db/entities/account/AccountConfig.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.readrops.db.entities.account; - -public class AccountConfig { - - public static final AccountConfig LOCAL = new AccountConfigBuilder() - .setFeedUrlEditable(true) - .setFolderCreation(true) - .setNoFolderCase(false) - .setUseSeparateState(false) - .build(); - - public static final AccountConfig NEXTCLOUD_NEWS = new AccountConfigBuilder() - .setFeedUrlEditable(false) - .setFolderCreation(true) - .setNoFolderCase(false) - .setUseSeparateState(false) - .build(); - - public static final AccountConfig FRESHRSS = new AccountConfigBuilder() - .setFeedUrlEditable(false) - .setFolderCreation(false) - .setNoFolderCase(true) - .setUseSeparateState(true) - .build(); - - private final boolean feedUrlEditable; - - private final boolean folderCreation; - - private final boolean noFolderCase; - - /* - Let knows if it uses ItemState table to synchronize state - */ - private final boolean useSeparateState; - - public boolean isFeedUrlEditable() { - return feedUrlEditable; - } - - public boolean isFolderCreation() { - return folderCreation; - } - - public boolean isNoFolderCase() { - return noFolderCase; - } - - public boolean useSeparateState() { - return useSeparateState; - } - - public AccountConfig(AccountConfigBuilder builder) { - this.feedUrlEditable = builder.feedUrlEditable; - this.folderCreation = builder.folderCreation; - this.noFolderCase = builder.noFolderCase; - this.useSeparateState = builder.useSeparateState; - } - - public static class AccountConfigBuilder { - private boolean feedUrlEditable; - private boolean folderCreation; - private boolean noFolderCase; - private boolean useSeparateState; - - public AccountConfigBuilder setFeedUrlEditable(boolean feedUrlEditable) { - this.feedUrlEditable = feedUrlEditable; - return this; - } - - public AccountConfigBuilder setFolderCreation(boolean folderCreation) { - this.folderCreation = folderCreation; - return this; - } - - public AccountConfigBuilder setNoFolderCase(boolean noFolderCase) { - this.noFolderCase = noFolderCase; - return this; - } - - public AccountConfigBuilder setUseSeparateState(boolean useSeparateState) { - this.useSeparateState = useSeparateState; - return this; - } - - public AccountConfig build() { - return new AccountConfig(this); - } - } -} diff --git a/db/src/main/java/com/readrops/db/entities/account/AccountConfig.kt b/db/src/main/java/com/readrops/db/entities/account/AccountConfig.kt new file mode 100644 index 00000000..ad2af98c --- /dev/null +++ b/db/src/main/java/com/readrops/db/entities/account/AccountConfig.kt @@ -0,0 +1,39 @@ +package com.readrops.db.entities.account + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +data class AccountConfig( + val isFeedUrlEditable: Boolean, // Enables or disables feed url modification in management screen + val isFolderCreation: Boolean, // Enables or disables folder creation in management screen + val isNoFolderCase: Boolean, // Add a "No folder" option when modifying a feed's folder + val useSeparateState: Boolean, // Let knows if it uses ItemState table to synchronize state +) : Parcelable { + + companion object { + @JvmField + val LOCAL = AccountConfig( + isFeedUrlEditable = true, + isFolderCreation = true, + isNoFolderCase = false, + useSeparateState = false, + ) + + @JvmField + val NEXTCLOUD_NEWS = AccountConfig( + isFeedUrlEditable = false, + isFolderCreation = true, + isNoFolderCase = false, + useSeparateState = false, + ) + + @JvmField + val FRESHRSS = AccountConfig( + isFeedUrlEditable = false, + isFolderCreation = false, + isNoFolderCase = true, + useSeparateState = true, + ) + } +} \ No newline at end of file diff --git a/db/src/main/java/com/readrops/db/entities/account/AccountType.java b/db/src/main/java/com/readrops/db/entities/account/AccountType.java deleted file mode 100644 index 65ec00cd..00000000 --- a/db/src/main/java/com/readrops/db/entities/account/AccountType.java +++ /dev/null @@ -1,65 +0,0 @@ -package com.readrops.db.entities.account; - -import android.os.Parcel; -import android.os.Parcelable; - -import androidx.annotation.DrawableRes; -import androidx.annotation.StringRes; - -import com.readrops.db.R; - - -public enum AccountType implements Parcelable { - LOCAL(R.mipmap.ic_launcher, R.string.local_account, AccountConfig.LOCAL), - NEXTCLOUD_NEWS(R.drawable.ic_nextcloud_news, R.string.nextcloud_news, AccountConfig.NEXTCLOUD_NEWS), - FEEDLY(R.drawable.ic_feedly, R.string.feedly, null), - FRESHRSS(R.drawable.ic_freshrss, R.string.freshrss, AccountConfig.FRESHRSS); - - private @DrawableRes - int iconRes; - private @StringRes - int name; - private AccountConfig accountConfig; - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(ordinal()); - } - - @Override - public int describeContents() { - return 0; - } - - public static final Creator CREATOR = new Creator() { - @Override - public AccountType createFromParcel(Parcel in) { - return AccountType.values()[in.readInt()]; - } - - @Override - public AccountType[] newArray(int size) { - return new AccountType[size]; - } - }; - - public @DrawableRes - int getIconRes() { - return iconRes; - } - - public @StringRes - int getName() { - return name; - } - - public AccountConfig getAccountConfig() { - return accountConfig; - } - - AccountType(@DrawableRes int iconRes, @StringRes int name, AccountConfig accountConfig) { - this.iconRes = iconRes; - this.name = name; - this.accountConfig = accountConfig; - } -} diff --git a/db/src/main/java/com/readrops/db/entities/account/AccountType.kt b/db/src/main/java/com/readrops/db/entities/account/AccountType.kt new file mode 100644 index 00000000..edb235d1 --- /dev/null +++ b/db/src/main/java/com/readrops/db/entities/account/AccountType.kt @@ -0,0 +1,17 @@ +package com.readrops.db.entities.account + +import android.os.Parcelable +import androidx.annotation.DrawableRes +import androidx.annotation.StringRes +import com.readrops.db.R +import kotlinx.parcelize.Parcelize + +@Parcelize +enum class AccountType(@DrawableRes val iconRes: Int, + @StringRes val typeName: Int, + val accountConfig: AccountConfig?) : Parcelable { + LOCAL(R.mipmap.ic_launcher, R.string.local_account, AccountConfig.LOCAL), + NEXTCLOUD_NEWS(R.drawable.ic_nextcloud_news, R.string.nextcloud_news, AccountConfig.NEXTCLOUD_NEWS), + FEEDLY(R.drawable.ic_feedly, R.string.feedly, null), + FRESHRSS(R.drawable.ic_freshrss, R.string.freshrss, AccountConfig.FRESHRSS); +} \ No newline at end of file From bb24daff64f2a463577d270cd3b682362f1c4638 Mon Sep 17 00:00:00 2001 From: Shinokuni Date: Wed, 1 Sep 2021 21:48:25 +0200 Subject: [PATCH 08/17] Migrate FeedWithFolder to kotlin --- .../java/com/readrops/db/dao/FeedDao.java | 5 +- .../com/readrops/db/pojo/FeedWithFolder.java | 68 ------------------- .../com/readrops/db/pojo/FeedWithFolder.kt | 13 ++++ 3 files changed, 15 insertions(+), 71 deletions(-) delete mode 100644 db/src/main/java/com/readrops/db/pojo/FeedWithFolder.java create mode 100644 db/src/main/java/com/readrops/db/pojo/FeedWithFolder.kt diff --git a/db/src/main/java/com/readrops/db/dao/FeedDao.java b/db/src/main/java/com/readrops/db/dao/FeedDao.java index 072a4b5b..12e78923 100644 --- a/db/src/main/java/com/readrops/db/dao/FeedDao.java +++ b/db/src/main/java/com/readrops/db/dao/FeedDao.java @@ -62,10 +62,9 @@ public abstract class FeedDao implements BaseDao { @Query("Update Feed set text_color = :textColor, background_color = :bgColor Where id = :feedId") public abstract void updateColors(int feedId, int textColor, int bgColor); - @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH) @Query("Select Feed.name as feed_name, Feed.id as feed_id, Folder.name as folder_name, Folder.id as folder_id, Folder.remoteId as folder_remoteId, Folder.account_id as folder_account_id," + - "Feed.description as feed_description, Feed.icon_url as feed_icon_url, Feed.url as feed_url, Feed.folder_id as feed_folder_id" + - ", Feed.siteUrl as feed_siteUrl, Feed.remoteId as feed_remoteId from Feed Left Join Folder on Feed.folder_id = Folder.id Where Feed.account_id = :accountId Order by Feed.name") + "Feed.description as feed_description, Feed.icon_url as feed_icon_url, Feed.url as feed_url, Feed.folder_id as feed_folder_id, Feed.text_color as feed_text_color, Feed.background_color as feed_background_color" + + ", Feed.account_id as feed_account_id, Feed.notification_enabled as feed_notification_enabled, Feed.siteUrl as feed_siteUrl, Feed.remoteId as feed_remoteId from Feed Left Join Folder on Feed.folder_id = Folder.id Where Feed.account_id = :accountId Order by Feed.name") public abstract LiveData> getAllFeedsWithFolder(int accountId); @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH) diff --git a/db/src/main/java/com/readrops/db/pojo/FeedWithFolder.java b/db/src/main/java/com/readrops/db/pojo/FeedWithFolder.java deleted file mode 100644 index 6f0316b9..00000000 --- a/db/src/main/java/com/readrops/db/pojo/FeedWithFolder.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.readrops.db.pojo; - -import android.os.Parcel; -import android.os.Parcelable; - -import androidx.room.Embedded; - -import com.readrops.db.entities.Feed; -import com.readrops.db.entities.Folder; - -public class FeedWithFolder implements Parcelable { - - @Embedded(prefix = "feed_") - private Feed feed; - - @Embedded(prefix = "folder_") - private Folder folder; - - public FeedWithFolder() { - - } - - protected FeedWithFolder(Parcel in) { - feed = in.readParcelable(Feed.class.getClassLoader()); - folder = in.readParcelable(Folder.class.getClassLoader()); - } - - @Override - public void writeToParcel(Parcel dest, int flags) { - dest.writeParcelable(feed, flags); - dest.writeParcelable(folder, flags); - } - - @Override - public int describeContents() { - return 0; - } - - public static final Creator CREATOR = new Creator() { - @Override - public FeedWithFolder createFromParcel(Parcel in) { - return new FeedWithFolder(in); - } - - @Override - public FeedWithFolder[] newArray(int size) { - return new FeedWithFolder[size]; - } - }; - - public Feed getFeed() { - return feed; - } - - public void setFeed(Feed feed) { - this.feed = feed; - } - - public Folder getFolder() { - return folder; - } - - public void setFolder(Folder folder) { - this.folder = folder; - } - - -} diff --git a/db/src/main/java/com/readrops/db/pojo/FeedWithFolder.kt b/db/src/main/java/com/readrops/db/pojo/FeedWithFolder.kt new file mode 100644 index 00000000..dd78e3d7 --- /dev/null +++ b/db/src/main/java/com/readrops/db/pojo/FeedWithFolder.kt @@ -0,0 +1,13 @@ +package com.readrops.db.pojo + +import android.os.Parcelable +import androidx.room.Embedded +import com.readrops.db.entities.Feed +import com.readrops.db.entities.Folder +import kotlinx.parcelize.Parcelize + +@Parcelize +data class FeedWithFolder( + @Embedded(prefix = "feed_") val feed: Feed, + @Embedded(prefix = "folder_") val folder: Folder, +) : Parcelable \ No newline at end of file From 96be5af06e89f82f5fe23d3b990bc23e0598817c Mon Sep 17 00:00:00 2001 From: Shinokuni Date: Wed, 1 Sep 2021 22:13:03 +0200 Subject: [PATCH 09/17] Migrate FolderWithFeedCount and ItemWithFeed to kotlin --- .../readrops/db/pojo/FolderWithFeedCount.java | 34 ------- .../readrops/db/pojo/FolderWithFeedCount.kt | 10 ++ .../com/readrops/db/pojo/ItemWithFeed.java | 99 ------------------- .../java/com/readrops/db/pojo/ItemWithFeed.kt | 18 ++++ 4 files changed, 28 insertions(+), 133 deletions(-) delete mode 100644 db/src/main/java/com/readrops/db/pojo/FolderWithFeedCount.java create mode 100644 db/src/main/java/com/readrops/db/pojo/FolderWithFeedCount.kt delete mode 100644 db/src/main/java/com/readrops/db/pojo/ItemWithFeed.java create mode 100644 db/src/main/java/com/readrops/db/pojo/ItemWithFeed.kt diff --git a/db/src/main/java/com/readrops/db/pojo/FolderWithFeedCount.java b/db/src/main/java/com/readrops/db/pojo/FolderWithFeedCount.java deleted file mode 100644 index a4fda1ba..00000000 --- a/db/src/main/java/com/readrops/db/pojo/FolderWithFeedCount.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.readrops.db.pojo; - -import androidx.room.ColumnInfo; -import androidx.room.Embedded; - -import com.readrops.db.entities.Folder; - -public class FolderWithFeedCount { - - @Embedded - private Folder folder; - - @ColumnInfo(name = "feed_count") - private int feedCount; - - public FolderWithFeedCount() { - } - - public Folder getFolder() { - return folder; - } - - public void setFolder(Folder folder) { - this.folder = folder; - } - - public int getFeedCount() { - return feedCount; - } - - public void setFeedCount(int feedCount) { - this.feedCount = feedCount; - } -} diff --git a/db/src/main/java/com/readrops/db/pojo/FolderWithFeedCount.kt b/db/src/main/java/com/readrops/db/pojo/FolderWithFeedCount.kt new file mode 100644 index 00000000..b87d5178 --- /dev/null +++ b/db/src/main/java/com/readrops/db/pojo/FolderWithFeedCount.kt @@ -0,0 +1,10 @@ +package com.readrops.db.pojo + +import androidx.room.ColumnInfo +import androidx.room.Embedded +import com.readrops.db.entities.Folder + +data class FolderWithFeedCount( + @Embedded val folder: Folder, + @ColumnInfo(name = "feed_count") val feedCount: Int, +) \ No newline at end of file diff --git a/db/src/main/java/com/readrops/db/pojo/ItemWithFeed.java b/db/src/main/java/com/readrops/db/pojo/ItemWithFeed.java deleted file mode 100644 index 6a23e6f8..00000000 --- a/db/src/main/java/com/readrops/db/pojo/ItemWithFeed.java +++ /dev/null @@ -1,99 +0,0 @@ -package com.readrops.db.pojo; - -import androidx.room.ColumnInfo; -import androidx.room.Embedded; -import androidx.annotation.ColorInt; - -import com.readrops.db.entities.Folder; -import com.readrops.db.entities.Item; - -public class ItemWithFeed { - - @Embedded - private Item item; - - @ColumnInfo(name = "name") - private String feedName; - - @ColumnInfo(name = "feedId") - private int feedId; - - @ColumnInfo(name = "text_color") - private @ColorInt int color; - - @ColumnInfo(name = "background_color") - private @ColorInt int bgColor; - - @ColumnInfo(name = "icon_url") - private String feedIconUrl; - - @ColumnInfo(name = "siteUrl") - private String websiteUrl; - - @Embedded(prefix = "folder_") - private Folder folder; - - public Item getItem() { - return item; - } - - public void setItem(Item item) { - this.item = item; - } - - public String getFeedName() { - return feedName; - } - - public void setFeedName(String feedName) { - this.feedName = feedName; - } - - public int getFeedId() { - return feedId; - } - - public void setFeedId(int feedId) { - this.feedId = feedId; - } - - public @ColorInt int getColor() { - return color; - } - - public void setColor(@ColorInt int color) { - this.color = color; - } - - public String getFeedIconUrl() { - return feedIconUrl; - } - - public void setFeedIconUrl(String feedIconUrl) { - this.feedIconUrl = feedIconUrl; - } - - public @ColorInt int getBgColor() { - return bgColor; - } - - public void setBgColor(@ColorInt int bgColor) { - this.bgColor = bgColor; - } - - public Folder getFolder() { - return folder; - } - - public void setFolder(Folder folder) { - this.folder = folder; - } - - public String getWebsiteUrl() { - return websiteUrl; - } - - public void setWebsiteUrl(String websiteUrl) { - this.websiteUrl = websiteUrl; - } -} diff --git a/db/src/main/java/com/readrops/db/pojo/ItemWithFeed.kt b/db/src/main/java/com/readrops/db/pojo/ItemWithFeed.kt new file mode 100644 index 00000000..24357509 --- /dev/null +++ b/db/src/main/java/com/readrops/db/pojo/ItemWithFeed.kt @@ -0,0 +1,18 @@ +package com.readrops.db.pojo + +import androidx.annotation.ColorInt +import androidx.room.ColumnInfo +import androidx.room.Embedded +import com.readrops.db.entities.Folder +import com.readrops.db.entities.Item + +data class ItemWithFeed( + @Embedded val item: Item, + @ColumnInfo(name = "name") val feedName: String, + @ColumnInfo(name = "feedId") val feedId: Int, + @ColumnInfo(name = "text_color") @ColorInt val color: Int, + @ColumnInfo(name = "background_color") @ColorInt val bgColor: Int, + @ColumnInfo(name = "icon_url") val feedIconUrl: String?, + @ColumnInfo(name = "siteUrl") val websiteUrl: String?, + @Embedded(prefix = "folder_") val folder: Folder, +) \ No newline at end of file From 4dfa474d14264caad71ed2a701960ba05245a8eb Mon Sep 17 00:00:00 2001 From: Shinokuni Date: Wed, 1 Sep 2021 22:21:50 +0200 Subject: [PATCH 10/17] Migrate FilterType and ListSortTYpe to kotlin --- .../readrops/db/filters/{FilterType.java => FilterType.kt} | 4 ++-- db/src/main/java/com/readrops/db/filters/ListSortType.java | 6 ------ db/src/main/java/com/readrops/db/filters/ListSortType.kt | 6 ++++++ 3 files changed, 8 insertions(+), 8 deletions(-) rename db/src/main/java/com/readrops/db/filters/{FilterType.java => FilterType.kt} (82%) delete mode 100644 db/src/main/java/com/readrops/db/filters/ListSortType.java create mode 100644 db/src/main/java/com/readrops/db/filters/ListSortType.kt diff --git a/db/src/main/java/com/readrops/db/filters/FilterType.java b/db/src/main/java/com/readrops/db/filters/FilterType.kt similarity index 82% rename from db/src/main/java/com/readrops/db/filters/FilterType.java rename to db/src/main/java/com/readrops/db/filters/FilterType.kt index e971c0af..d6443501 100644 --- a/db/src/main/java/com/readrops/db/filters/FilterType.java +++ b/db/src/main/java/com/readrops/db/filters/FilterType.kt @@ -1,9 +1,9 @@ package com.readrops.db.filters; -public enum FilterType { +enum class FilterType { FEED_FILTER, FOLDER_FILER, READ_IT_LATER_FILTER, STARS_FILTER, NO_FILTER -} +} \ No newline at end of file diff --git a/db/src/main/java/com/readrops/db/filters/ListSortType.java b/db/src/main/java/com/readrops/db/filters/ListSortType.java deleted file mode 100644 index a348b03f..00000000 --- a/db/src/main/java/com/readrops/db/filters/ListSortType.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.readrops.db.filters; - -public enum ListSortType { - NEWEST_TO_OLDEST, - OLDEST_TO_NEWEST -} diff --git a/db/src/main/java/com/readrops/db/filters/ListSortType.kt b/db/src/main/java/com/readrops/db/filters/ListSortType.kt new file mode 100644 index 00000000..7d039556 --- /dev/null +++ b/db/src/main/java/com/readrops/db/filters/ListSortType.kt @@ -0,0 +1,6 @@ +package com.readrops.db.filters + +enum class ListSortType { + NEWEST_TO_OLDEST, + OLDEST_TO_NEWEST +} From 07e586a98901af5ed6c7bed78f2cf0cc329fcdc4 Mon Sep 17 00:00:00 2001 From: Shinokuni Date: Wed, 1 Sep 2021 22:27:05 +0200 Subject: [PATCH 11/17] Migrate Converters to kotlin --- .../main/java/com/readrops/db/Converters.java | 31 ------------------- .../main/java/com/readrops/db/Converters.kt | 28 +++++++++++++++++ 2 files changed, 28 insertions(+), 31 deletions(-) delete mode 100644 db/src/main/java/com/readrops/db/Converters.java create mode 100644 db/src/main/java/com/readrops/db/Converters.kt diff --git a/db/src/main/java/com/readrops/db/Converters.java b/db/src/main/java/com/readrops/db/Converters.java deleted file mode 100644 index 1939315f..00000000 --- a/db/src/main/java/com/readrops/db/Converters.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.readrops.db; - -import androidx.room.TypeConverter; - -import com.readrops.db.entities.account.AccountType; - -import org.joda.time.LocalDateTime; - -public class Converters { - - @TypeConverter - public LocalDateTime fromTimeStamp(Long value) { - return new LocalDateTime(value); - } - - @TypeConverter - public long fromLocalDateTime(LocalDateTime localDateTime) { - return localDateTime.toDateTime().getMillis(); - } - - @TypeConverter - public AccountType fromAccountTypeCode(int ordinal) { - return AccountType.values()[ordinal]; - } - - @TypeConverter - public int getAccountTypeCode(AccountType accountType) { - return accountType.ordinal(); - } - -} diff --git a/db/src/main/java/com/readrops/db/Converters.kt b/db/src/main/java/com/readrops/db/Converters.kt new file mode 100644 index 00000000..5291deeb --- /dev/null +++ b/db/src/main/java/com/readrops/db/Converters.kt @@ -0,0 +1,28 @@ +package com.readrops.db + +import androidx.room.TypeConverter +import com.readrops.db.entities.account.AccountType +import org.joda.time.LocalDateTime + +object Converters { + + @TypeConverter + fun fromTimeStamp(value: Long): LocalDateTime { + return LocalDateTime(value) + } + + @TypeConverter + fun fromLocalDateTime(localDateTime: LocalDateTime): Long { + return localDateTime.toDateTime().millis + } + + @TypeConverter + fun fromAccountTypeCode(ordinal: Int): AccountType { + return AccountType.values()[ordinal] + } + + @TypeConverter + fun getAccountTypeCode(accountType: AccountType): Int { + return accountType.ordinal + } +} \ No newline at end of file From 2f82efe4cbd608a426b0a51fea968c8ce5b27729 Mon Sep 17 00:00:00 2001 From: Shinokuni Date: Wed, 1 Sep 2021 22:58:16 +0200 Subject: [PATCH 12/17] Migrate AccountDao and ItemDao to kotlin --- .../notifications/sync/SyncResultAnalyser.kt | 2 +- .../java/com/readrops/db/dao/AccountDao.java | 46 ------------- .../java/com/readrops/db/dao/AccountDao.kt | 42 ++++++++++++ .../java/com/readrops/db/dao/ItemDao.java | 66 ------------------- .../main/java/com/readrops/db/dao/ItemDao.kt | 61 +++++++++++++++++ 5 files changed, 104 insertions(+), 113 deletions(-) delete mode 100644 db/src/main/java/com/readrops/db/dao/AccountDao.java create mode 100644 db/src/main/java/com/readrops/db/dao/AccountDao.kt delete mode 100644 db/src/main/java/com/readrops/db/dao/ItemDao.java create mode 100644 db/src/main/java/com/readrops/db/dao/ItemDao.kt diff --git a/app/src/main/java/com/readrops/app/notifications/sync/SyncResultAnalyser.kt b/app/src/main/java/com/readrops/app/notifications/sync/SyncResultAnalyser.kt index 5975c6cf..cf6c24eb 100644 --- a/app/src/main/java/com/readrops/app/notifications/sync/SyncResultAnalyser.kt +++ b/app/src/main/java/com/readrops/app/notifications/sync/SyncResultAnalyser.kt @@ -80,7 +80,7 @@ class SyncResultAnalyser(val context: Context, private val syncResults: Map { - - @Query("Select * from Account") - LiveData> selectAllAsync(); - - @Query("Select * From Account Where id = :accountId") - LiveData selectAsync(int accountId); - - @Query("Select * from Account") - List selectAll(); - - @Query("Select * From Account Where id = :accountId") - Account select(int accountId); - - @Query("Update Account set last_modified = :lastModified Where id = :accountId") - void updateLastModified(int accountId, long lastModified); - - @Query("Update Account set current_account = 0 Where id Not In (:accountId)") - void deselectOldCurrentAccount(int accountId); - - @Query("Update Account set current_account = 1 Where id = :accountId") - void setCurrentAccount(int accountId); - - @Query("Select count(*) From Account") - Single getAccountCount(); - - @Query("Update Account set writeToken = :writeToken Where id = :accountId") - void updateWriteToken(int accountId, String writeToken); - - @Query("Update Account set notifications_enabled = :enabled Where id = :accountId") - Completable updateNotificationState(int accountId, boolean enabled); -} diff --git a/db/src/main/java/com/readrops/db/dao/AccountDao.kt b/db/src/main/java/com/readrops/db/dao/AccountDao.kt new file mode 100644 index 00000000..e13f5662 --- /dev/null +++ b/db/src/main/java/com/readrops/db/dao/AccountDao.kt @@ -0,0 +1,42 @@ +package com.readrops.db.dao + +import androidx.lifecycle.LiveData +import androidx.room.Dao +import androidx.room.Query +import com.readrops.db.entities.account.Account +import io.reactivex.Completable +import io.reactivex.Single + +@Dao +interface AccountDao : BaseDao { + + @Query("Select * from Account") + fun selectAllAsync(): LiveData> + + @Query("Select * From Account Where id = :accountId") + fun selectAsync(accountId: Int): LiveData + + @Query("Select * from Account") + fun selectAll(): List + + @Query("Select * From Account Where id = :accountId") + fun select(accountId: Int): Account + + @Query("Update Account set last_modified = :lastModified Where id = :accountId") + fun updateLastModified(accountId: Int, lastModified: Long) + + @Query("Update Account set current_account = 0 Where id Not In (:accountId)") + fun deselectOldCurrentAccount(accountId: Int) + + @Query("Update Account set current_account = 1 Where id = :accountId") + fun setCurrentAccount(accountId: Int) + + @get:Query("Select count(*) From Account") + val accountCount: Single + + @Query("Update Account set writeToken = :writeToken Where id = :accountId") + fun updateWriteToken(accountId: Int, writeToken: String) + + @Query("Update Account set notifications_enabled = :enabled Where id = :accountId") + fun updateNotificationState(accountId: Int, enabled: Boolean): Completable +} \ No newline at end of file diff --git a/db/src/main/java/com/readrops/db/dao/ItemDao.java b/db/src/main/java/com/readrops/db/dao/ItemDao.java deleted file mode 100644 index 30f368c0..00000000 --- a/db/src/main/java/com/readrops/db/dao/ItemDao.java +++ /dev/null @@ -1,66 +0,0 @@ -package com.readrops.db.dao; - - -import androidx.lifecycle.LiveData; -import androidx.paging.DataSource; -import androidx.room.Dao; -import androidx.room.Query; -import androidx.room.RawQuery; -import androidx.sqlite.db.SupportSQLiteQuery; - -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.pojo.ItemWithFeed; -import com.readrops.db.pojo.StarItem; - -import java.util.List; - -import io.reactivex.Completable; - -@Dao -public interface ItemDao extends BaseDao { - - @RawQuery(observedEntities = {Item.class, Folder.class, Feed.class, ItemState.class}) - DataSource.Factory selectAll(SupportSQLiteQuery query); - - @Query("Select * From Item Where id = :itemId") - Item select(int itemId); - - @Query("Select case When :guid In (Select guid From Item Inner Join Feed on Item.feed_id = Feed.id and account_id = :accountId) Then 1 else 0 end") - boolean itemExists(String guid, int accountId); - - @Query("Select case When :remoteId In (Select remoteId from Item) And :feedId In (Select feed_id From Item) Then 1 else 0 end") - boolean remoteItemExists(String remoteId, int feedId); - - @Query("Select * From Item Where remoteId = :remoteId And feed_id = :feedId") - Item selectByRemoteId(String remoteId, int feedId); - - @Query("Update Item Set read = :read Where id = :itemId") - Completable setReadState(int itemId, boolean read); - - @Query("Update Item set starred = :starred Where id = :itemId") - Completable setStarState(int itemId, boolean starred); - - @Query("Update Item set read = :readState Where feed_id In (Select id From Feed Where account_id = :accountId)") - Completable setAllItemsReadState(int readState, int accountId); - - @Query("Update Item set read = :readState Where feed_id = :feedId") - Completable setAllFeedItemsReadState(int feedId, int readState); - - @Query("Update Item set read_it_later = :readLater Where id = :itemId") - Completable setReadItLater(boolean readLater, int itemId); - - @Query("Select count(*) From Item Where feed_id = :feedId And read = 0") - int getUnreadCount(int feedId); - - @RawQuery(observedEntities = {Item.class, ItemState.class}) - LiveData getItemById(SupportSQLiteQuery query); - - @Query("Select Item.guid, Feed.remoteId as feedRemoteId From Item Inner Join Feed On Item.feed_id = Feed.id Where Item.remoteId In (:remoteIds) And account_id = :accountId") - List getStarChanges(List remoteIds, int accountId); - - @Query("Update Item set read = :read, starred = :starred Where remoteId = :remoteId") - void setReadAndStarState(String remoteId, boolean read, boolean starred); -} diff --git a/db/src/main/java/com/readrops/db/dao/ItemDao.kt b/db/src/main/java/com/readrops/db/dao/ItemDao.kt new file mode 100644 index 00000000..5cd7ce0d --- /dev/null +++ b/db/src/main/java/com/readrops/db/dao/ItemDao.kt @@ -0,0 +1,61 @@ +package com.readrops.db.dao + +import androidx.lifecycle.LiveData +import androidx.paging.DataSource +import androidx.room.Dao +import androidx.room.Query +import androidx.room.RawQuery +import androidx.sqlite.db.SupportSQLiteQuery +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.pojo.ItemWithFeed +import com.readrops.db.pojo.StarItem +import io.reactivex.Completable + +@Dao +interface ItemDao : BaseDao { + + @RawQuery(observedEntities = [Item::class, Folder::class, Feed::class, ItemState::class]) + fun selectAll(query: SupportSQLiteQuery): DataSource.Factory + + @Query("Select * From Item Where id = :itemId") + fun select(itemId: Int): Item + + @Query("Select case When :guid In (Select guid From Item Inner Join Feed on Item.feed_id = Feed.id and account_id = :accountId) Then 1 else 0 end") + fun itemExists(guid: String, accountId: Int): Boolean + + @Query("Select case When :remoteId In (Select remoteId from Item) And :feedId In (Select feed_id From Item) Then 1 else 0 end") + fun remoteItemExists(remoteId: String, feedId: Int): Boolean + + @Query("Select * From Item Where remoteId = :remoteId And feed_id = :feedId") + fun selectByRemoteId(remoteId: String, feedId: Int): Item + + @Query("Update Item Set read = :read Where id = :itemId") + fun setReadState(itemId: Int, read: Boolean): Completable + + @Query("Update Item set starred = :starred Where id = :itemId") + fun setStarState(itemId: Int, starred: Boolean): Completable + + @Query("Update Item set read = :readState Where feed_id In (Select id From Feed Where account_id = :accountId)") + fun setAllItemsReadState(readState: Int, accountId: Int): Completable + + @Query("Update Item set read = :readState Where feed_id = :feedId") + fun setAllFeedItemsReadState(feedId: Int, readState: Int): Completable + + @Query("Update Item set read_it_later = :readLater Where id = :itemId") + fun setReadItLater(readLater: Boolean, itemId: Int): Completable + + @Query("Select count(*) From Item Where feed_id = :feedId And read = 0") + fun getUnreadCount(feedId: Int): Int + + @RawQuery(observedEntities = [Item::class, ItemState::class]) + fun getItemById(query: SupportSQLiteQuery): LiveData + + @Query("Select Item.guid, Feed.remoteId as feedRemoteId From Item Inner Join Feed On Item.feed_id = Feed.id Where Item.remoteId In (:remoteIds) And account_id = :accountId") + fun getStarChanges(remoteIds: List, accountId: Int): List + + @Query("Update Item set read = :read, starred = :starred Where remoteId = :remoteId") + fun setReadAndStarState(remoteId: String, read: Boolean, starred: Boolean) +} \ No newline at end of file From 1c981e96f6dac8d8ff4c03c85503b27c870b4d5e Mon Sep 17 00:00:00 2001 From: Shinokuni Date: Wed, 1 Sep 2021 23:03:57 +0200 Subject: [PATCH 13/17] Update formatting --- .../java/com/readrops/db/pojo/ItemReadStarState.kt | 12 +++++++----- db/src/main/java/com/readrops/db/pojo/StarItem.kt | 6 ++++-- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/db/src/main/java/com/readrops/db/pojo/ItemReadStarState.kt b/db/src/main/java/com/readrops/db/pojo/ItemReadStarState.kt index 4ada491f..45e1c30e 100644 --- a/db/src/main/java/com/readrops/db/pojo/ItemReadStarState.kt +++ b/db/src/main/java/com/readrops/db/pojo/ItemReadStarState.kt @@ -2,8 +2,10 @@ package com.readrops.db.pojo import androidx.room.ColumnInfo -data class ItemReadStarState(val remoteId: String, - val read: Boolean, - val starred: Boolean, - @ColumnInfo(name = "read_change") val readChange: Boolean, - @ColumnInfo(name = "star_change") val starChange: Boolean) \ No newline at end of file +data class ItemReadStarState( + val remoteId: String, + val read: Boolean, + val starred: Boolean, + @ColumnInfo(name = "read_change") val readChange: Boolean, + @ColumnInfo(name = "star_change") val starChange: Boolean, +) \ No newline at end of file diff --git a/db/src/main/java/com/readrops/db/pojo/StarItem.kt b/db/src/main/java/com/readrops/db/pojo/StarItem.kt index a58ba616..bc41b9af 100644 --- a/db/src/main/java/com/readrops/db/pojo/StarItem.kt +++ b/db/src/main/java/com/readrops/db/pojo/StarItem.kt @@ -3,5 +3,7 @@ package com.readrops.db.pojo import androidx.room.ColumnInfo -data class StarItem(@ColumnInfo val feedRemoteId: String, - @ColumnInfo(name = "guid") val guidHash: String) \ No newline at end of file +data class StarItem( + @ColumnInfo val feedRemoteId: String, + @ColumnInfo(name = "guid") val guidHash: String, +) \ No newline at end of file From 574199e6c83f1812693568193228746f3d13255d Mon Sep 17 00:00:00 2001 From: Shinokuni Date: Wed, 1 Sep 2021 23:30:10 +0200 Subject: [PATCH 14/17] Migrate FeedDao to kotlin --- .../java/com/readrops/db/dao/FeedDao.java | 132 ------------------ .../main/java/com/readrops/db/dao/FeedDao.kt | 120 ++++++++++++++++ 2 files changed, 120 insertions(+), 132 deletions(-) delete mode 100644 db/src/main/java/com/readrops/db/dao/FeedDao.java create mode 100644 db/src/main/java/com/readrops/db/dao/FeedDao.kt diff --git a/db/src/main/java/com/readrops/db/dao/FeedDao.java b/db/src/main/java/com/readrops/db/dao/FeedDao.java deleted file mode 100644 index 12e78923..00000000 --- a/db/src/main/java/com/readrops/db/dao/FeedDao.java +++ /dev/null @@ -1,132 +0,0 @@ -package com.readrops.db.dao; - - -import androidx.lifecycle.LiveData; -import androidx.room.Dao; -import androidx.room.Query; -import androidx.room.RoomWarnings; -import androidx.room.Transaction; - -import com.readrops.db.entities.Feed; -import com.readrops.db.entities.account.Account; -import com.readrops.db.pojo.FeedWithFolder; - -import java.util.ArrayList; -import java.util.List; - -import io.reactivex.Completable; -import io.reactivex.Single; - -@Dao -public abstract class FeedDao implements BaseDao { - - @Query("Select * from Feed Where account_id = :accountId order by name ASC") - public abstract List getFeeds(int accountId); - - @Query("Select * from Feed Order By name ASC") - public abstract LiveData> getAllFeeds(); - - @Query("Select * from Feed Where id = :feedId") - public abstract Feed getFeedById(int feedId); - - @Query("Select case When :feedUrl In (Select url from Feed Where account_id = :accountId) Then 1 else 0 end") - public abstract boolean feedExists(String feedUrl, int accountId); - - @Query("Select case When :remoteId In (Select remoteId from Feed Where account_id = :accountId) Then 1 else 0 end") - public abstract boolean remoteFeedExists(String remoteId, int accountId); - - @Query("Select count(*) from Feed Where account_id = :accountId") - public abstract Single getFeedCount(int accountId); - - @Query("Select * from Feed Where url = :feedUrl And account_id = :accountId") - public abstract Feed getFeedByUrl(String feedUrl, int accountId); - - @Query("Select id from Feed Where remoteId = :remoteId And account_id = :accountId") - public abstract int getFeedIdByRemoteId(String remoteId, int accountId); - - @Query("Select * from Feed Where folder_id = :folderId") - public abstract List getFeedsByFolder(int folderId); - - @Query("Select * from Feed Where account_id = :accountId And folder_id is null") - public abstract List getFeedsWithoutFolder(int accountId); - - @Query("Update Feed set etag = :etag, last_modified = :lastModified Where id = :feedId") - public abstract void updateHeaders(String etag, String lastModified, int feedId); - - @Query("Update Feed set name = :feedName, url = :feedUrl, folder_id = :folderId Where id = :feedId") - public abstract void updateFeedFields(int feedId, String feedName, String feedUrl, Integer folderId); - - @Query("Update Feed set name = :name, folder_id = :folderId Where remoteId = :remoteFeedId And account_id = :accountId") - public abstract void updateNameAndFolder(String remoteFeedId, int accountId, String name, Integer folderId); - - @Query("Update Feed set text_color = :textColor, background_color = :bgColor Where id = :feedId") - public abstract void updateColors(int feedId, int textColor, int bgColor); - - @Query("Select Feed.name as feed_name, Feed.id as feed_id, Folder.name as folder_name, Folder.id as folder_id, Folder.remoteId as folder_remoteId, Folder.account_id as folder_account_id," + - "Feed.description as feed_description, Feed.icon_url as feed_icon_url, Feed.url as feed_url, Feed.folder_id as feed_folder_id, Feed.text_color as feed_text_color, Feed.background_color as feed_background_color" + - ", Feed.account_id as feed_account_id, Feed.notification_enabled as feed_notification_enabled, Feed.siteUrl as feed_siteUrl, Feed.remoteId as feed_remoteId from Feed Left Join Folder on Feed.folder_id = Folder.id Where Feed.account_id = :accountId Order by Feed.name") - public abstract LiveData> getAllFeedsWithFolder(int accountId); - - @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH) - @Query("Select id, name, icon_url, notification_enabled, text_color, background_color, account_id From Feed Where account_id = :accountId") - public abstract LiveData> getFeedsForNotifPermission(int accountId); - - @Query("Select * From Feed Where id in (:ids)") - public abstract List selectFromIdList(List ids); - - @Query("Select remoteId From Feed Where account_id = :accountId") - public abstract List getFeedRemoteIdsOfAccount(int accountId); - - @Query("Delete from Feed Where remoteId in (:ids) And account_id = :accountId") - abstract void deleteByIds(List ids, int accountId); - - @Query("Select id From Folder Where remoteId = :remoteId And account_id = :accountId") - abstract int getRemoteFolderLocalId(String remoteId, int accountId); - - @Query("Update Feed set notification_enabled = :enabled Where id = :feedId") - public abstract Completable updateFeedNotificationState(int feedId, boolean enabled); - - @Query("Update Feed set notification_enabled = :enabled Where account_id = :accountId") - public abstract Completable updateAllFeedsNotificationState(int accountId, boolean enabled); - - /** - * Insert, update and delete feeds, by account - * - * @param feeds feeds to insert or update - * @param account owner of the feeds - * @return the list of the inserted feeds ids - */ - @Transaction - public List feedsUpsert(List feeds, Account account) { - List accountFeedIds = getFeedRemoteIdsOfAccount(account.getId()); - List feedsToInsert = new ArrayList<>(); - - for (Feed feed : feeds) { - Integer folderId; - - try { - int remoteFolderId = Integer.parseInt(feed.getRemoteFolderId()); - folderId = remoteFolderId == 0 ? null : getRemoteFolderLocalId(feed.getRemoteFolderId(), account.getId()); - } catch (Exception e) { - folderId = feed.getRemoteFolderId() == null ? null : getRemoteFolderLocalId(feed.getRemoteFolderId(), account.getId()); - } - - if (remoteFeedExists(feed.getRemoteId(), account.getId())) { - updateNameAndFolder(feed.getRemoteId(), account.getId(), feed.getName(), folderId); - - accountFeedIds.remove(feed.getRemoteId()); - } else { - feed.setFolderId(folderId); - - feedsToInsert.add(feed); - } - } - - if (!accountFeedIds.isEmpty()) { - deleteByIds(accountFeedIds, account.getId()); - } - - return insert(feedsToInsert); - } -} - diff --git a/db/src/main/java/com/readrops/db/dao/FeedDao.kt b/db/src/main/java/com/readrops/db/dao/FeedDao.kt new file mode 100644 index 00000000..6cf64ce6 --- /dev/null +++ b/db/src/main/java/com/readrops/db/dao/FeedDao.kt @@ -0,0 +1,120 @@ +package com.readrops.db.dao + +import androidx.lifecycle.LiveData +import androidx.room.Dao +import androidx.room.Query +import androidx.room.Transaction +import com.readrops.db.entities.Feed +import com.readrops.db.entities.account.Account +import com.readrops.db.pojo.FeedWithFolder +import io.reactivex.Completable +import io.reactivex.Single +import java.lang.Exception +import java.util.ArrayList + +@Dao +abstract class FeedDao : BaseDao { + + @Query("Select * from Feed Where account_id = :accountId order by name ASC") + abstract fun getFeeds(accountId: Int): List + + @get:Query("Select * from Feed Order By name ASC") + abstract val allFeeds: LiveData> + + @Query("Select * from Feed Where id = :feedId") + abstract fun getFeedById(feedId: Int): Feed + + @Query("Select case When :feedUrl In (Select url from Feed Where account_id = :accountId) Then 1 else 0 end") + abstract fun feedExists(feedUrl: String, accountId: Int): Boolean + + @Query("Select case When :remoteId In (Select remoteId from Feed Where account_id = :accountId) Then 1 else 0 end") + abstract fun remoteFeedExists(remoteId: String, accountId: Int): Boolean + + @Query("Select count(*) from Feed Where account_id = :accountId") + abstract fun getFeedCount(accountId: Int): Single + + @Query("Select * from Feed Where url = :feedUrl And account_id = :accountId") + abstract fun getFeedByUrl(feedUrl: String, accountId: Int): Feed + + @Query("Select id from Feed Where remoteId = :remoteId And account_id = :accountId") + abstract fun getFeedIdByRemoteId(remoteId: String, accountId: Int): Int + + @Query("Select * from Feed Where folder_id = :folderId") + abstract fun getFeedsByFolder(folderId: Int): List + + @Query("Select * from Feed Where account_id = :accountId And folder_id is null") + abstract fun getFeedsWithoutFolder(accountId: Int): List + + @Query("Update Feed set etag = :etag, last_modified = :lastModified Where id = :feedId") + abstract fun updateHeaders(etag: String, lastModified: String, feedId: Int) + + @Query("Update Feed set name = :feedName, url = :feedUrl, folder_id = :folderId Where id = :feedId") + abstract fun updateFeedFields(feedId: Int, feedName: String, feedUrl: String, folderId: Int) + + @Query("Update Feed set name = :name, folder_id = :folderId Where remoteId = :remoteFeedId And account_id = :accountId") + abstract fun updateNameAndFolder(remoteFeedId: String, accountId: Int, name: String, folderId: Int?) + + @Query("Update Feed set text_color = :textColor, background_color = :bgColor Where id = :feedId") + abstract fun updateColors(feedId: Int, textColor: Int, bgColor: Int) + + @Query("Select Feed.name as feed_name, Feed.id as feed_id, Folder.name as folder_name, Folder.id as folder_id, Folder.remoteId as folder_remoteId, Folder.account_id as folder_account_id," + + "Feed.description as feed_description, Feed.icon_url as feed_icon_url, Feed.url as feed_url, Feed.folder_id as feed_folder_id, Feed.text_color as feed_text_color, Feed.background_color as feed_background_color" + + ", Feed.account_id as feed_account_id, Feed.notification_enabled as feed_notification_enabled, Feed.siteUrl as feed_siteUrl, Feed.remoteId as feed_remoteId from Feed Left Join Folder on Feed.folder_id = Folder.id Where Feed.account_id = :accountId Order by Feed.name") + abstract fun getAllFeedsWithFolder(accountId: Int): LiveData> + + @Query("Select id, name, icon_url, notification_enabled, text_color, background_color, account_id From Feed Where account_id = :accountId") + abstract fun getFeedsForNotifPermission(accountId: Int): LiveData> + + @Query("Select * From Feed Where id in (:ids)") + abstract fun selectFromIdList(ids: List): List + + @Query("Select remoteId From Feed Where account_id = :accountId") + abstract fun getFeedRemoteIdsOfAccount(accountId: Int): MutableList + + @Query("Delete from Feed Where remoteId in (:ids) And account_id = :accountId") + abstract fun deleteByIds(ids: List, accountId: Int) + + @Query("Select id From Folder Where remoteId = :remoteId And account_id = :accountId") + abstract fun getRemoteFolderLocalId(remoteId: String, accountId: Int): Int + + @Query("Update Feed set notification_enabled = :enabled Where id = :feedId") + abstract fun updateFeedNotificationState(feedId: Int, enabled: Boolean): Completable + + @Query("Update Feed set notification_enabled = :enabled Where account_id = :accountId") + abstract fun updateAllFeedsNotificationState(accountId: Int, enabled: Boolean): Completable + + /** + * Insert, update and delete feeds, by account + * + * @param feeds feeds to insert or update + * @param account owner of the feeds + * @return the list of the inserted feeds ids + */ + @Transaction + open fun feedsUpsert(feeds: List, account: Account): List { + val accountFeedIds = getFeedRemoteIdsOfAccount(account.id) + val feedsToInsert = arrayListOf() + + for (feed in feeds) { + val folderId: Int? = try { + val remoteFolderId = feed.remoteFolderId!!.toInt() + if (remoteFolderId == 0) null else getRemoteFolderLocalId(feed.remoteFolderId!!, account.id) + } catch (e: Exception) { + if (feed.remoteFolderId == null) null else getRemoteFolderLocalId(feed.remoteFolderId!!, account.id) + } + + if (remoteFeedExists(feed.remoteId!!, account.id)) { + updateNameAndFolder(feed.remoteId!!, account.id, feed.name!!, folderId) + accountFeedIds.remove(feed.remoteId) + } else { + feed.folderId = folderId + feedsToInsert.add(feed) + } + } + + if (accountFeedIds.isNotEmpty()) + deleteByIds(accountFeedIds, account.id) + + return insert(feedsToInsert) + } +} \ No newline at end of file From 85042e5d3c6b6d34a52e66b5a89ce4fbc3c658d3 Mon Sep 17 00:00:00 2001 From: Shinokuni Date: Wed, 1 Sep 2021 23:45:38 +0200 Subject: [PATCH 15/17] MIgrate FolderDao to kotlin --- .../java/com/readrops/db/dao/FolderDao.java | 73 ------------------- .../java/com/readrops/db/dao/FolderDao.kt | 68 +++++++++++++++++ 2 files changed, 68 insertions(+), 73 deletions(-) delete mode 100644 db/src/main/java/com/readrops/db/dao/FolderDao.java create mode 100644 db/src/main/java/com/readrops/db/dao/FolderDao.kt diff --git a/db/src/main/java/com/readrops/db/dao/FolderDao.java b/db/src/main/java/com/readrops/db/dao/FolderDao.java deleted file mode 100644 index 75f1b507..00000000 --- a/db/src/main/java/com/readrops/db/dao/FolderDao.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.readrops.db.dao; - -import androidx.lifecycle.LiveData; -import androidx.room.Dao; -import androidx.room.Query; -import androidx.room.Transaction; - -import com.readrops.db.entities.Folder; -import com.readrops.db.entities.account.Account; -import com.readrops.db.pojo.FolderWithFeedCount; - -import java.util.ArrayList; -import java.util.List; - -@Dao -public abstract class FolderDao implements BaseDao { - - @Query("Select * from Folder Where account_id = :accountId Order By name ASC") - public abstract LiveData> getAllFolders(int accountId); - - @Query("Select Folder.*, count(Feed.id) as feed_count from Folder Left Join Feed on Folder.id = Feed.folder_id Where Folder.account_id = :accountId Group by Folder.id Order By name ASC") - public abstract LiveData> getFoldersWithFeedCount(int accountId); - - @Query("Select * from Folder Where account_id = :accountId Order By name ASC") - public abstract List getFolders(int accountId); - - @Query("Update Folder set name = :name Where remoteId = :remoteFolderId And account_id = :accountId") - public abstract void updateName(String remoteFolderId, int accountId, String name); - - @Query("Select case When :remoteId In (Select remoteId From Folder Where account_id = :accountId) Then 1 else 0 end") - abstract boolean remoteFolderExists(String remoteId, int accountId); - - @Query("Select * from Folder Where id = :folderId") - public abstract Folder select(int folderId); - - @Query("Select remoteId From Folder Where account_id = :accountId") - public abstract List getFolderRemoteIdsOfAccount(int accountId); - - @Query("Delete From Folder Where remoteId in (:ids) And account_id = :accountId") - abstract void deleteByIds(List ids, int accountId); - - @Query("Select * From Folder Where name = :name And account_id = :accountId") - public abstract Folder getFolderByName(String name, int accountId); - - /** - * Insert, update and delete folders - * - * @param folders folders to insert or update - * @param account owner of the feeds - * @return the list of the inserted folders ids - */ - @Transaction - public List foldersUpsert(List folders, Account account) { - List accountFolderIds = getFolderRemoteIdsOfAccount(account.getId()); - List foldersToInsert = new ArrayList<>(); - - for (Folder folder : folders) { - if (remoteFolderExists(folder.getRemoteId(), account.getId())) { - updateName(folder.getRemoteId(), account.getId(), folder.getName()); - - accountFolderIds.remove(folder.getRemoteId()); - } else { - foldersToInsert.add(folder); - } - } - - if (!accountFolderIds.isEmpty()) { - deleteByIds(accountFolderIds, account.getId()); - } - - return insert(foldersToInsert); - } -} diff --git a/db/src/main/java/com/readrops/db/dao/FolderDao.kt b/db/src/main/java/com/readrops/db/dao/FolderDao.kt new file mode 100644 index 00000000..d3cdd545 --- /dev/null +++ b/db/src/main/java/com/readrops/db/dao/FolderDao.kt @@ -0,0 +1,68 @@ +package com.readrops.db.dao + +import androidx.lifecycle.LiveData +import androidx.room.Dao +import androidx.room.Query +import androidx.room.Transaction +import com.readrops.db.entities.Folder +import com.readrops.db.entities.account.Account +import com.readrops.db.pojo.FolderWithFeedCount +import java.util.ArrayList + +@Dao +abstract class FolderDao : BaseDao { + + @Query("Select * from Folder Where account_id = :accountId Order By name ASC") + abstract fun getAllFolders(accountId: Int): LiveData> + + @Query("Select Folder.*, count(Feed.id) as feed_count from Folder Left Join Feed on Folder.id = Feed.folder_id Where Folder.account_id = :accountId Group by Folder.id Order By name ASC") + abstract fun getFoldersWithFeedCount(accountId: Int): LiveData> + + @Query("Select * from Folder Where account_id = :accountId Order By name ASC") + abstract fun getFolders(accountId: Int): List + + @Query("Update Folder set name = :name Where remoteId = :remoteFolderId And account_id = :accountId") + abstract fun updateName(remoteFolderId: String, accountId: Int, name: String) + + @Query("Select case When :remoteId In (Select remoteId From Folder Where account_id = :accountId) Then 1 else 0 end") + abstract fun remoteFolderExists(remoteId: String, accountId: Int): Boolean + + @Query("Select * from Folder Where id = :folderId") + abstract fun select(folderId: Int): Folder + + @Query("Select remoteId From Folder Where account_id = :accountId") + abstract fun getFolderRemoteIdsOfAccount(accountId: Int): MutableList + + @Query("Delete From Folder Where remoteId in (:ids) And account_id = :accountId") + abstract fun deleteByIds(ids: List, accountId: Int) + + @Query("Select * From Folder Where name = :name And account_id = :accountId") + abstract fun getFolderByName(name: String, accountId: Int): Folder + + /** + * Insert, update and delete folders + * + * @param folders folders to insert or update + * @param account owner of the feeds + * @return the list of the inserted folders ids + */ + @Transaction + open fun foldersUpsert(folders: List, account: Account): List { + val accountFolderIds = getFolderRemoteIdsOfAccount(account.id) + val foldersToInsert = arrayListOf() + + for (folder in folders) { + if (remoteFolderExists(folder.remoteId!!, account.id)) { + updateName(folder.remoteId!!, account.id, folder.name!!) + accountFolderIds.remove(folder.remoteId) + } else { + foldersToInsert.add(folder) + } + } + + if (accountFolderIds.isNotEmpty()) + deleteByIds(accountFolderIds, account.id) + + return insert(foldersToInsert) + } +} \ No newline at end of file From c2110b08c9efdd2bb8a85da6aad0ac2cb72c673d Mon Sep 17 00:00:00 2001 From: Shinokuni Date: Thu, 2 Sep 2021 13:36:02 +0200 Subject: [PATCH 16/17] MIgrate BaseDao to kotlin --- .../java/com/readrops/db/dao/BaseDao.java | 36 ------------------- .../main/java/com/readrops/db/dao/BaseDao.kt | 33 +++++++++++++++++ 2 files changed, 33 insertions(+), 36 deletions(-) delete mode 100644 db/src/main/java/com/readrops/db/dao/BaseDao.java create mode 100644 db/src/main/java/com/readrops/db/dao/BaseDao.kt diff --git a/db/src/main/java/com/readrops/db/dao/BaseDao.java b/db/src/main/java/com/readrops/db/dao/BaseDao.java deleted file mode 100644 index 3eebfe1c..00000000 --- a/db/src/main/java/com/readrops/db/dao/BaseDao.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.readrops.db.dao; - -import androidx.room.Delete; -import androidx.room.Insert; -import androidx.room.Update; - -import java.util.List; - -import io.reactivex.Completable; -import io.reactivex.Single; - -public interface BaseDao { - - @Insert - Single insert(T entity); - - // only here for compatibility with LocalFeedRepository - // which hasn't been written with rxjava usage in mind - @Insert - long compatInsert(T entity); - - @Insert - List insert(List entities); - - @Update - Completable update(T entity); - - @Update - Completable update(List entities); - - @Delete - Completable delete(T entity); - - @Delete - Completable delete(List entities); -} diff --git a/db/src/main/java/com/readrops/db/dao/BaseDao.kt b/db/src/main/java/com/readrops/db/dao/BaseDao.kt new file mode 100644 index 00000000..e070c04f --- /dev/null +++ b/db/src/main/java/com/readrops/db/dao/BaseDao.kt @@ -0,0 +1,33 @@ +package com.readrops.db.dao + +import androidx.room.Delete +import androidx.room.Insert +import androidx.room.Update +import io.reactivex.Completable +import io.reactivex.Single + +interface BaseDao { + + @Insert + fun insert(entity: T): Single + + // only here for compatibility with LocalFeedRepository + // which hasn't been written with rxjava usage in mind + @Insert + fun compatInsert(entity: T): Long + + @Insert + fun insert(entities: List?): List + + @Update + fun update(entity: T): Completable + + @Update + fun update(entities: List?): Completable + + @Delete + fun delete(entity: T): Completable + + @Delete + fun delete(entities: List?): Completable +} \ No newline at end of file From 63a8891880a03e5e8bff3c026ec9dc82fcf86f29 Mon Sep 17 00:00:00 2001 From: Shinokuni Date: Thu, 2 Sep 2021 13:54:27 +0200 Subject: [PATCH 17/17] Fix tests --- .../localfeed/rss1/RSS1ItemsAdapterTest.kt | 4 ++-- .../com/readrops/api/opml/OPMLParserTest.kt | 24 +++++++++---------- .../main/java/com/readrops/db/dao/FeedDao.kt | 3 +++ 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/api/src/test/java/com/readrops/api/localfeed/rss1/RSS1ItemsAdapterTest.kt b/api/src/test/java/com/readrops/api/localfeed/rss1/RSS1ItemsAdapterTest.kt index 7efda78f..07bcf72f 100644 --- a/api/src/test/java/com/readrops/api/localfeed/rss1/RSS1ItemsAdapterTest.kt +++ b/api/src/test/java/com/readrops/api/localfeed/rss1/RSS1ItemsAdapterTest.kt @@ -25,9 +25,9 @@ class RSS1ItemsAdapterTest { assertEquals(items.size, 4) assertEquals(item.title, "Google Expands its Flutter Development Kit To Windows Apps") - assertEquals(item.link.trim(), "https://developers.slashdot.org/story/20/09/23/1616231/google-expands-" + + assertEquals(item.link!!.trim(), "https://developers.slashdot.org/story/20/09/23/1616231/google-expands-" + "its-flutter-development-kit-to-windows-apps?utm_source=rss1.0mainlinkanon&utm_medium=feed") - assertEquals(item.guid.trim(), "https://developers.slashdot.org/story/20/09/23/1616231/google-expands-" + + assertEquals(item.guid!!.trim(), "https://developers.slashdot.org/story/20/09/23/1616231/google-expands-" + "its-flutter-development-kit-to-windows-apps?utm_source=rss1.0mainlinkanon&utm_medium=feed") assertEquals(item.pubDate, DateUtils.parse("2020-09-23T16:15:00+00:00")) assertEquals(item.author, "msmash") diff --git a/api/src/test/java/com/readrops/api/opml/OPMLParserTest.kt b/api/src/test/java/com/readrops/api/opml/OPMLParserTest.kt index a28a8df7..32d3fd56 100644 --- a/api/src/test/java/com/readrops/api/opml/OPMLParserTest.kt +++ b/api/src/test/java/com/readrops/api/opml/OPMLParserTest.kt @@ -25,11 +25,11 @@ class OPMLParserTest { assertEquals(foldersAndFeeds?.size, 6) - assertEquals(foldersAndFeeds?.get(Folder("Folder 1"))?.size, 2) - assertEquals(foldersAndFeeds?.get(Folder("Subfolder 1"))?.size, 4) - assertEquals(foldersAndFeeds?.get(Folder("Subfolder 2"))?.size, 1) - assertEquals(foldersAndFeeds?.get(Folder("Sub subfolder 1"))?.size, 2) - assertEquals(foldersAndFeeds?.get(Folder("Sub subfolder 2"))?.size, 0) + assertEquals(foldersAndFeeds?.get(Folder(name = "Folder 1"))?.size, 2) + assertEquals(foldersAndFeeds?.get(Folder(name = "Subfolder 1"))?.size, 4) + assertEquals(foldersAndFeeds?.get(Folder(name = "Subfolder 2"))?.size, 1) + assertEquals(foldersAndFeeds?.get(Folder(name = "Sub subfolder 1"))?.size, 2) + assertEquals(foldersAndFeeds?.get(Folder(name = "Sub subfolder 2"))?.size, 0) assertEquals(foldersAndFeeds?.get(null)?.size, 2) stream.close() @@ -68,11 +68,11 @@ class OPMLParserTest { val outputStream = FileOutputStream(file) val foldersAndFeeds: Map> = HashMap>().apply { - put(null, listOf(Feed("Feed1", "", "https://feed1.com"), - Feed("Feed2", "", "https://feed2.com"))) - put(Folder("Folder1"), listOf()) - put(Folder("Folder2"), listOf(Feed("Feed3", "", "https://feed3.com"), - Feed("Feed4", "", "https://feed4.com"))) + put(null, listOf(Feed(name = "Feed1", url = "https://feed1.com"), + Feed(name = "Feed2", url = "https://feed2.com"))) + put(Folder(name = "Folder1"), listOf()) + put(Folder(name = "Folder2"), listOf(Feed(name = "Feed3", url = "https://feed3.com"), + Feed(name = "Feed4", url ="https://feed4.com"))) } OPMLParser.write(foldersAndFeeds, outputStream) @@ -87,8 +87,8 @@ class OPMLParserTest { OPMLParser.read(inputStream).subscribe { result -> foldersAndFeeds2 = result } assertEquals(foldersAndFeeds.size, foldersAndFeeds2?.size) - assertEquals(foldersAndFeeds[Folder("Folder1")]?.size, foldersAndFeeds2?.get(Folder("Folder1"))?.size) - assertEquals(foldersAndFeeds[Folder("Folder2")]?.size, foldersAndFeeds2?.get(Folder("Folder2"))?.size) + assertEquals(foldersAndFeeds[Folder(name = "Folder1")]?.size, foldersAndFeeds2?.get(Folder(name = "Folder1"))?.size) + assertEquals(foldersAndFeeds[Folder(name = "Folder2")]?.size, foldersAndFeeds2?.get(Folder(name = "Folder2"))?.size) assertEquals(foldersAndFeeds[null]?.size, foldersAndFeeds2?.get(null)?.size) inputStream.close() diff --git a/db/src/main/java/com/readrops/db/dao/FeedDao.kt b/db/src/main/java/com/readrops/db/dao/FeedDao.kt index 6cf64ce6..9cd24948 100644 --- a/db/src/main/java/com/readrops/db/dao/FeedDao.kt +++ b/db/src/main/java/com/readrops/db/dao/FeedDao.kt @@ -3,6 +3,7 @@ package com.readrops.db.dao import androidx.lifecycle.LiveData import androidx.room.Dao import androidx.room.Query +import androidx.room.RoomWarnings import androidx.room.Transaction import com.readrops.db.entities.Feed import com.readrops.db.entities.account.Account @@ -57,11 +58,13 @@ abstract class FeedDao : BaseDao { @Query("Update Feed set text_color = :textColor, background_color = :bgColor Where id = :feedId") abstract fun updateColors(feedId: Int, textColor: Int, bgColor: Int) + @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH) @Query("Select Feed.name as feed_name, Feed.id as feed_id, Folder.name as folder_name, Folder.id as folder_id, Folder.remoteId as folder_remoteId, Folder.account_id as folder_account_id," + "Feed.description as feed_description, Feed.icon_url as feed_icon_url, Feed.url as feed_url, Feed.folder_id as feed_folder_id, Feed.text_color as feed_text_color, Feed.background_color as feed_background_color" + ", Feed.account_id as feed_account_id, Feed.notification_enabled as feed_notification_enabled, Feed.siteUrl as feed_siteUrl, Feed.remoteId as feed_remoteId from Feed Left Join Folder on Feed.folder_id = Folder.id Where Feed.account_id = :accountId Order by Feed.name") abstract fun getAllFeedsWithFolder(accountId: Int): LiveData> + @SuppressWarnings(RoomWarnings.CURSOR_MISMATCH) @Query("Select id, name, icon_url, notification_enabled, text_color, background_color, account_id From Feed Where account_id = :accountId") abstract fun getFeedsForNotifPermission(accountId: Int): LiveData>