mirror of https://github.com/readrops/Readrops.git
Make FeverRepository compile again and Fever auth work
This commit is contained in:
parent
04820cd700
commit
732ae4efa4
|
@ -1,6 +1,7 @@
|
|||
package com.readrops.api.services
|
||||
|
||||
import com.readrops.api.services.fever.FeverCredentials
|
||||
import com.readrops.api.services.fever.FeverService
|
||||
import com.readrops.api.services.freshrss.FreshRSSCredentials
|
||||
import com.readrops.api.services.freshrss.FreshRSSService
|
||||
import com.readrops.api.services.nextcloudnews.NextcloudNewsCredentials
|
||||
|
@ -27,7 +28,7 @@ abstract class Credentials(val authorization: String?, val url: String) {
|
|||
return when (accountType) {
|
||||
AccountType.FRESHRSS -> FreshRSSService.END_POINT
|
||||
AccountType.NEXTCLOUD_NEWS -> NextcloudNewsService.END_POINT
|
||||
AccountType.FEVER -> ""
|
||||
AccountType.FEVER -> FeverService.END_POINT
|
||||
else -> throw IllegalArgumentException("Unknown account type")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,35 +2,33 @@ package com.readrops.api.services.fever
|
|||
|
||||
import com.readrops.api.services.SyncType
|
||||
import com.readrops.api.services.fever.adapters.FeverAPIAdapter
|
||||
import com.readrops.api.utils.exceptions.LoginException
|
||||
import com.readrops.api.utils.ApiUtils
|
||||
import com.readrops.db.entities.Item
|
||||
import com.squareup.moshi.Moshi
|
||||
import okhttp3.MultipartBody
|
||||
|
||||
class FeverDataSource(private val service: FeverService) {
|
||||
|
||||
suspend fun login(body: MultipartBody) {
|
||||
val response = service.login(body)
|
||||
suspend fun login(login: String, password: String): Boolean {
|
||||
val response = service.login(getFeverRequestBody(login, password))
|
||||
|
||||
val adapter = Moshi.Builder()
|
||||
.add(Boolean::class.java, FeverAPIAdapter())
|
||||
.build()
|
||||
.adapter(Boolean::class.java)
|
||||
.add(Boolean::class.java, FeverAPIAdapter())
|
||||
.build()
|
||||
.adapter(Boolean::class.java)
|
||||
|
||||
val authenticated = adapter.fromJson(response.source())!!
|
||||
|
||||
// Error handling is shit, but it will stay like that until the UI
|
||||
// and the other data sources/repositories are rewritten in Kotlin
|
||||
if (!authenticated) {
|
||||
throw LoginException("Login failed. Please check your credentials")
|
||||
}
|
||||
return adapter.fromJson(response.source())!!
|
||||
}
|
||||
|
||||
suspend fun sync(syncType: SyncType, syncData: FeverSyncData, body: MultipartBody): FeverSyncResult {
|
||||
suspend fun synchronize(
|
||||
syncType: SyncType,
|
||||
syncData: FeverSyncData,
|
||||
body: MultipartBody
|
||||
): FeverSyncResult {
|
||||
if (syncType == SyncType.INITIAL_SYNC) {
|
||||
val unreadIds = service.getUnreadItemsIds(body)
|
||||
.reversed()
|
||||
.subList(0, MAX_ITEMS_IDS)
|
||||
.reversed()
|
||||
.subList(0, MAX_ITEMS_IDS)
|
||||
|
||||
var lastId = unreadIds.first()
|
||||
val items = arrayListOf<Item>()
|
||||
|
@ -42,13 +40,13 @@ class FeverDataSource(private val service: FeverService) {
|
|||
}
|
||||
|
||||
return FeverSyncResult(
|
||||
feverFeeds = service.getFeeds(body),
|
||||
folders = service.getFolders(body),
|
||||
items = items,
|
||||
unreadIds = unreadIds,
|
||||
starredIds = service.getStarredItemsIds(body),
|
||||
favicons = listOf(),
|
||||
sinceId = unreadIds.first().toLong(),
|
||||
feverFeeds = service.getFeeds(body),
|
||||
folders = service.getFolders(body),
|
||||
items = items,
|
||||
unreadIds = unreadIds,
|
||||
starredIds = service.getStarredItemsIds(body),
|
||||
favicons = listOf(),
|
||||
sinceId = unreadIds.first().toLong(),
|
||||
)
|
||||
} else {
|
||||
val items = arrayListOf<Item>()
|
||||
|
@ -63,19 +61,31 @@ class FeverDataSource(private val service: FeverService) {
|
|||
}
|
||||
|
||||
return FeverSyncResult(
|
||||
feverFeeds = service.getFeeds(body),
|
||||
folders = service.getFolders(body),
|
||||
items = items,
|
||||
unreadIds = service.getUnreadItemsIds(body),
|
||||
starredIds = service.getStarredItemsIds(body),
|
||||
favicons = listOf(),
|
||||
sinceId = if (items.isNotEmpty()) items.first().remoteId!!.toLong() else sinceId.toLong(),
|
||||
feverFeeds = service.getFeeds(body),
|
||||
folders = service.getFolders(body),
|
||||
items = items,
|
||||
unreadIds = service.getUnreadItemsIds(body),
|
||||
starredIds = service.getStarredItemsIds(body),
|
||||
favicons = listOf(),
|
||||
sinceId = if (items.isNotEmpty()) items.first().remoteId!!.toLong() else sinceId.toLong(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun setItemState(body: MultipartBody, action: String, id: String) =
|
||||
service.updateItemState(body, action, id)
|
||||
suspend fun setItemState(login: String, password: String, action: String, id: String) {
|
||||
val body = getFeverRequestBody(login, password)
|
||||
|
||||
service.updateItemState(body, action, id)
|
||||
}
|
||||
|
||||
private fun getFeverRequestBody(login: String, password: String): MultipartBody {
|
||||
val credentials = ApiUtils.md5hash("$login:$password")
|
||||
|
||||
return MultipartBody.Builder()
|
||||
.setType(MultipartBody.FORM)
|
||||
.addFormDataPart("api_key", credentials)
|
||||
.build()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val MAX_ITEMS_IDS = 5000
|
||||
|
@ -85,12 +95,12 @@ class FeverDataSource(private val service: FeverService) {
|
|||
|
||||
sealed class ItemAction(val value: String) {
|
||||
sealed class ReadStateAction(value: String) : ItemAction(value) {
|
||||
object ReadAction : ReadStateAction("read")
|
||||
object UnreadAction : ReadStateAction("unread")
|
||||
data object ReadAction : ReadStateAction("read")
|
||||
data object UnreadAction : ReadStateAction("unread")
|
||||
}
|
||||
|
||||
sealed class StarStateAction(value: String) : ItemAction(value) {
|
||||
object StarAction : StarStateAction("saved")
|
||||
object UnstarAction : StarStateAction("unsaved")
|
||||
data object StarAction : StarStateAction("saved")
|
||||
data object UnstarAction : StarStateAction("unsaved")
|
||||
}
|
||||
}
|
|
@ -38,4 +38,8 @@ interface FeverService {
|
|||
suspend fun updateItemState(@Body body: MultipartBody, @Query("as") action: String,
|
||||
@Query("id") id: String)
|
||||
|
||||
companion object {
|
||||
const val END_POINT = "/api/fever.php/"
|
||||
}
|
||||
|
||||
}
|
|
@ -2,7 +2,13 @@ package com.readrops.api.services.fever.adapters
|
|||
|
||||
import com.readrops.api.utils.exceptions.ParseException
|
||||
import com.readrops.api.utils.extensions.skipField
|
||||
import com.squareup.moshi.*
|
||||
import com.readrops.api.utils.extensions.toBoolean
|
||||
import com.squareup.moshi.FromJson
|
||||
import com.squareup.moshi.JsonAdapter
|
||||
import com.squareup.moshi.JsonReader
|
||||
import com.squareup.moshi.JsonReader.Token
|
||||
import com.squareup.moshi.JsonWriter
|
||||
import com.squareup.moshi.ToJson
|
||||
|
||||
class FeverAPIAdapter : JsonAdapter<Boolean>() {
|
||||
|
||||
|
@ -15,19 +21,21 @@ class FeverAPIAdapter : JsonAdapter<Boolean>() {
|
|||
override fun fromJson(reader: JsonReader): Boolean = with(reader) {
|
||||
return try {
|
||||
beginObject()
|
||||
|
||||
skipField()
|
||||
|
||||
var authenticated = 0
|
||||
if (nextName() == "auth") {
|
||||
authenticated = nextInt()
|
||||
} else {
|
||||
skipValue()
|
||||
}
|
||||
|
||||
while (peek() == Token.NAME) {
|
||||
skipField()
|
||||
}
|
||||
|
||||
skipField()
|
||||
endObject()
|
||||
|
||||
|
||||
authenticated == 1
|
||||
authenticated.toBoolean()
|
||||
} catch (e: Exception) {
|
||||
throw ParseException(e.message)
|
||||
}
|
||||
|
|
|
@ -14,10 +14,6 @@ object ApiUtils {
|
|||
const val LAST_MODIFIED_HEADER = "Last-Modified"
|
||||
const val IF_MODIFIED_HEADER = "If-Modified-Since"
|
||||
|
||||
const val HTTP_UNPROCESSABLE = 422
|
||||
const val HTTP_NOT_FOUND = 404
|
||||
const val HTTP_CONFLICT = 409
|
||||
|
||||
val OPML_MIMETYPES = listOf("application/xml", "text/xml", "text/x-opml")
|
||||
|
||||
private const val RSS_CONTENT_TYPE_REGEX = "([^;]+)"
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
package com.readrops.api.utils.exceptions
|
||||
|
||||
class LoginException(override val message: String?) : Exception() {
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
package com.readrops.api.utils.exceptions
|
||||
|
||||
class LoginFailedException(override val message: String? = null) : Exception()
|
|
@ -3,8 +3,9 @@ package com.readrops.api.services.fever.adapters
|
|||
import com.readrops.api.TestUtils
|
||||
import com.squareup.moshi.Moshi
|
||||
import okio.Buffer
|
||||
import kotlin.test.Test
|
||||
import org.junit.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
|
||||
class FeverAPIAdapterTest {
|
||||
|
||||
|
@ -20,4 +21,12 @@ class FeverAPIAdapterTest {
|
|||
val value = adapter.fromJson(Buffer().readFrom(stream))!!
|
||||
assertEquals(value, true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun unauthenticatedTest() {
|
||||
val stream = TestUtils.loadResource("services/fever/unsuccessful_auth.json")
|
||||
|
||||
val value = adapter.fromJson(Buffer().readFrom(stream))!!
|
||||
assertFalse { value }
|
||||
}
|
||||
}
|
|
@ -6,9 +6,8 @@ import com.readrops.api.services.fever.FeverCredentials
|
|||
import com.readrops.api.services.fever.FeverDataSource
|
||||
import com.readrops.api.utils.ApiUtils
|
||||
import com.readrops.api.utils.AuthInterceptor
|
||||
import com.readrops.api.utils.exceptions.LoginException
|
||||
import com.readrops.api.utils.exceptions.LoginFailedException
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import okhttp3.MultipartBody
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.mockwebserver.MockResponse
|
||||
import okhttp3.mockwebserver.MockWebServer
|
||||
|
@ -68,9 +67,7 @@ class FeverDataSourceTest : KoinTest {
|
|||
.setBody(Buffer().readFrom(stream)))
|
||||
|
||||
runBlocking {
|
||||
dataSource.login(MultipartBody.Builder()
|
||||
.addFormDataPart("api_key", "value")
|
||||
.build())
|
||||
dataSource.login("","")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,11 +79,9 @@ class FeverDataSourceTest : KoinTest {
|
|||
.addHeader(ApiUtils.CONTENT_TYPE_HEADER, "application/json")
|
||||
.setBody(Buffer().readFrom(stream)))
|
||||
|
||||
assertThrows(LoginException::class.java) {
|
||||
assertThrows(LoginFailedException::class.java) {
|
||||
runBlocking {
|
||||
dataSource.login(MultipartBody.Builder()
|
||||
.addFormDataPart("api_key", "value")
|
||||
.build())
|
||||
dataSource.login("","")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"api_version": 3,
|
||||
"auth": 0
|
||||
}
|
|
@ -19,6 +19,7 @@ import com.readrops.app.item.ItemScreenModel
|
|||
import com.readrops.app.more.preferences.PreferencesScreenModel
|
||||
import com.readrops.app.notifications.NotificationsScreenModel
|
||||
import com.readrops.app.repositories.BaseRepository
|
||||
import com.readrops.app.repositories.FeverRepository
|
||||
import com.readrops.app.repositories.FreshRSSRepository
|
||||
import com.readrops.app.repositories.GetFoldersWithFeeds
|
||||
import com.readrops.app.repositories.LocalRSSRepository
|
||||
|
@ -61,13 +62,23 @@ val appModule = module {
|
|||
when (account.accountType) {
|
||||
AccountType.LOCAL -> LocalRSSRepository(get(), get(), account)
|
||||
AccountType.FRESHRSS -> FreshRSSRepository(
|
||||
get(), account,
|
||||
get(parameters = { parametersOf(Credentials.toCredentials(account)) })
|
||||
database = get(),
|
||||
account = account,
|
||||
dataSource = get(parameters = { parametersOf(Credentials.toCredentials(account)) })
|
||||
)
|
||||
|
||||
AccountType.NEXTCLOUD_NEWS -> NextcloudNewsRepository(
|
||||
get(), account,
|
||||
get(parameters = { parametersOf(Credentials.toCredentials(account)) })
|
||||
database = get(),
|
||||
account = account,
|
||||
dataSource = get(parameters = { parametersOf(Credentials.toCredentials(account)) })
|
||||
)
|
||||
|
||||
AccountType.FEVER -> FeverRepository(
|
||||
database = get(),
|
||||
account = account,
|
||||
feverDataSource = get(parameters = { parametersOf(Credentials.toCredentials(account)) })
|
||||
)
|
||||
|
||||
else -> throw IllegalArgumentException("Unknown account type")
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +102,7 @@ val appModule = module {
|
|||
corruptionHandler = ReplaceFileCorruptionHandler(
|
||||
produceNewData = { emptyPreferences() }
|
||||
),
|
||||
migrations = listOf(SharedPreferencesMigration(get(),"settings")),
|
||||
migrations = listOf(SharedPreferencesMigration(get(), "settings")),
|
||||
scope = CoroutineScope(Dispatchers.IO + SupervisorJob()),
|
||||
produceFile = { get<Context>().preferencesDataStoreFile("settings") }
|
||||
)
|
||||
|
|
|
@ -41,6 +41,7 @@ import cafe.adriel.voyager.koin.getScreenModel
|
|||
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||
import com.readrops.app.R
|
||||
import com.readrops.app.account.selection.adaptiveIconPainterResource
|
||||
import com.readrops.app.home.HomeScreen
|
||||
import com.readrops.app.util.ErrorMessage
|
||||
import com.readrops.app.util.components.AndroidScreen
|
||||
|
@ -115,7 +116,7 @@ class AccountCredentialsScreen(
|
|||
.verticalScroll(rememberScrollState())
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(id = account.accountType!!.iconRes),
|
||||
painter = adaptiveIconPainterResource(id = account.accountType!!.iconRes),
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(48.dp)
|
||||
)
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package com.readrops.app.repositories
|
||||
|
||||
/*
|
||||
import android.content.Context
|
||||
import android.util.Log
|
||||
import com.readrops.api.services.SyncType
|
||||
import com.readrops.api.services.fever.FeverDataSource
|
||||
|
@ -9,107 +7,103 @@ import com.readrops.api.services.fever.FeverSyncData
|
|||
import com.readrops.api.services.fever.ItemAction
|
||||
import com.readrops.api.services.fever.adapters.FeverFeeds
|
||||
import com.readrops.api.utils.ApiUtils
|
||||
import com.readrops.app.addfeed.FeedInsertionResult
|
||||
import com.readrops.app.addfeed.ParsingResult
|
||||
import com.readrops.app.utils.Utils
|
||||
import com.readrops.api.utils.exceptions.LoginFailedException
|
||||
import com.readrops.app.util.Utils
|
||||
import com.readrops.db.Database
|
||||
import com.readrops.db.entities.Feed
|
||||
import com.readrops.db.entities.Folder
|
||||
import com.readrops.db.entities.Item
|
||||
import com.readrops.db.entities.ItemState
|
||||
import com.readrops.db.entities.account.Account
|
||||
import io.reactivex.Completable
|
||||
import io.reactivex.Single
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.rx2.await
|
||||
import kotlinx.coroutines.rx2.rxCompletable
|
||||
import okhttp3.MultipartBody
|
||||
|
||||
class FeverRepository(
|
||||
private val feverDataSource: FeverDataSource,
|
||||
private val dispatcher: CoroutineDispatcher,
|
||||
database: Database,
|
||||
context: Context,
|
||||
account: Account?,
|
||||
) : BaseRepository(database, context, account) {
|
||||
database: Database,
|
||||
account: Account,
|
||||
private val feverDataSource: FeverDataSource
|
||||
) : BaseRepository(database, account) {
|
||||
|
||||
override fun login(account: Account, insert: Boolean): Completable =
|
||||
rxCompletable(context = dispatcher) {
|
||||
try {
|
||||
feverDataSource.login(getFeverRequestBody())
|
||||
account.displayedName = account.accountType!!.name
|
||||
override suspend fun login(account: Account) {
|
||||
val authenticated = feverDataSource.login(account.login!!, account.password!!)
|
||||
|
||||
database.accountDao().insert(account)
|
||||
.doOnSuccess { account.id = it.toInt() }
|
||||
.await()
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "login: ${e.message}")
|
||||
error(e.message!!)
|
||||
}
|
||||
}
|
||||
if (authenticated) {
|
||||
account.displayedName = account.accountType!!.name
|
||||
} else {
|
||||
throw LoginFailedException()
|
||||
}
|
||||
}
|
||||
|
||||
override fun sync(feeds: List<Feed>?, update: FeedUpdate?): Completable =
|
||||
rxCompletable(context = dispatcher) {
|
||||
try {
|
||||
val syncType = if (account.lastModified != 0L) {
|
||||
SyncType.CLASSIC_SYNC
|
||||
} else {
|
||||
SyncType.INITIAL_SYNC
|
||||
}
|
||||
override suspend fun synchronize(): SyncResult {
|
||||
val syncType = if (account.lastModified != 0L) {
|
||||
SyncType.CLASSIC_SYNC
|
||||
} else {
|
||||
SyncType.INITIAL_SYNC
|
||||
}
|
||||
|
||||
val syncResult = feverDataSource.sync(syncType,
|
||||
FeverSyncData(account.lastModified.toString()), getFeverRequestBody())
|
||||
return feverDataSource.synchronize(
|
||||
syncType,
|
||||
FeverSyncData(account.lastModified.toString()),
|
||||
getFeverRequestBody()
|
||||
).run {
|
||||
insertFolders(folders)
|
||||
insertFeeds(feverFeeds)
|
||||
|
||||
insertFolders(syncResult.folders)
|
||||
insertFeeds(syncResult.feverFeeds)
|
||||
insertItems(items)
|
||||
insertItemsIds(unreadIds, starredIds.toMutableList())
|
||||
|
||||
insertItems(syncResult.items)
|
||||
insertItemsIds(syncResult.unreadIds, syncResult.starredIds.toMutableList())
|
||||
// We store the id to use for the next synchronisation even if it's not a timestamp
|
||||
database.accountDao().updateLastModified(sinceId, account.id)
|
||||
|
||||
// We store the id to use for the next synchronisation even if it's not a timestamp
|
||||
database.accountDao().updateLastModified(account.id, syncResult.sinceId)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "sync: ${e.message}")
|
||||
error(e.message!!)
|
||||
}
|
||||
}
|
||||
SyncResult()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun synchronize(
|
||||
selectedFeeds: List<Feed>,
|
||||
onUpdate: suspend (Feed) -> Unit
|
||||
): Pair<SyncResult, ErrorResult> = throw NotImplementedError("This method can't be called here")
|
||||
|
||||
// Not supported by Fever API
|
||||
override fun addFeeds(results: List<ParsingResult>?): Single<List<FeedInsertionResult>> = Single.just(listOf())
|
||||
override suspend fun insertNewFeeds(
|
||||
newFeeds: List<Feed>,
|
||||
onUpdate: (Feed) -> Unit
|
||||
): ErrorResult = throw CloneNotSupportedException()
|
||||
|
||||
// Not supported by Fever API
|
||||
override fun updateFeed(feed: Feed?): Completable = Completable.complete()
|
||||
override suspend fun updateFeed(feed: Feed) {}
|
||||
|
||||
// Not supported by Fever API
|
||||
override fun deleteFeed(feed: Feed?): Completable = Completable.complete()
|
||||
override suspend fun deleteFeed(feed: Feed) {}
|
||||
|
||||
// Not supported by Fever API
|
||||
override fun addFolder(folder: Folder?): Single<Long> = Single.just(0)
|
||||
override suspend fun addFolder(folder: Folder) {}
|
||||
|
||||
// Not supported by Fever API
|
||||
override fun updateFolder(folder: Folder?): Completable = Completable.complete()
|
||||
override suspend fun updateFolder(folder: Folder) {}
|
||||
|
||||
// Not supported by Fever API
|
||||
override fun deleteFolder(folder: Folder?): Completable = Completable.complete()
|
||||
override suspend fun deleteFolder(folder: Folder) {}
|
||||
|
||||
override fun setItemReadState(item: Item): Completable {
|
||||
val action = if (item.isRead) ItemAction.ReadStateAction.ReadAction else ItemAction.ReadStateAction.UnreadAction
|
||||
override suspend fun setItemReadState(item: Item) {
|
||||
val action =
|
||||
if (item.isRead) ItemAction.ReadStateAction.ReadAction else ItemAction.ReadStateAction.UnreadAction
|
||||
return setItemState(item, action)
|
||||
}
|
||||
|
||||
override fun setItemStarState(item: Item): Completable {
|
||||
val action = if (item.isStarred) ItemAction.StarStateAction.StarAction else ItemAction.StarStateAction.UnstarAction
|
||||
override suspend fun setItemStarState(item: Item) {
|
||||
val action =
|
||||
if (item.isStarred) ItemAction.StarStateAction.StarAction else ItemAction.StarStateAction.UnstarAction
|
||||
return setItemState(item, action)
|
||||
}
|
||||
|
||||
private fun setItemState(item: Item, action: ItemAction): Completable = rxCompletable(context = dispatcher) {
|
||||
private suspend fun setItemState(item: Item, action: ItemAction) {
|
||||
try {
|
||||
feverDataSource.setItemState(getFeverRequestBody(), action.value, item.remoteId!!)
|
||||
feverDataSource.setItemState(account.login!!, account.password!!, action.value, item.remoteId!!)
|
||||
val itemState = ItemState(
|
||||
read = item.isRead,
|
||||
starred = item.isStarred,
|
||||
remoteId = item.remoteId!!,
|
||||
accountId = account.id,
|
||||
read = item.isRead,
|
||||
starred = item.isStarred,
|
||||
remoteId = item.remoteId!!,
|
||||
accountId = account.id,
|
||||
)
|
||||
|
||||
val completable = if (action is ItemAction.ReadStateAction) {
|
||||
|
@ -118,7 +112,6 @@ class FeverRepository(
|
|||
database.itemStateDao().upsertItemStarState(itemState)
|
||||
}
|
||||
|
||||
completable.await()
|
||||
} catch (e: Exception) {
|
||||
val completable = if (action is ItemAction.ReadStateAction) {
|
||||
super.setItemReadState(item)
|
||||
|
@ -126,14 +119,14 @@ class FeverRepository(
|
|||
super.setItemStarState(item)
|
||||
}
|
||||
|
||||
completable.await()
|
||||
Log.e(TAG, "setItemStarState: ${e.message}")
|
||||
error(e.message!!)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun sendPreviousItemStateChanges() {
|
||||
val stateChanges = database.itemStateChangesDao().getItemStateChanges(account.id)
|
||||
val stateChanges = database.itemStateChangeDao()
|
||||
.selectItemStateChanges(account.id)
|
||||
|
||||
for (stateChange in stateChanges) {
|
||||
val action = if (stateChange.readChange) {
|
||||
|
@ -142,28 +135,30 @@ class FeverRepository(
|
|||
if (stateChange.starred) ItemAction.StarStateAction.StarAction else ItemAction.StarStateAction.UnstarAction
|
||||
}
|
||||
|
||||
feverDataSource.setItemState(getFeverRequestBody(), action.value, stateChange.remoteId)
|
||||
feverDataSource.setItemState(account.login!!, account.password!!, action.value, stateChange.remoteId)
|
||||
}
|
||||
}
|
||||
|
||||
private fun insertFolders(folders: List<Folder>) {
|
||||
private suspend fun insertFolders(folders: List<Folder>) {
|
||||
folders.forEach { it.accountId = account.id }
|
||||
database.folderDao().foldersUpsert(folders, account)
|
||||
database.folderDao().upsertFolders(folders, account)
|
||||
}
|
||||
|
||||
private fun insertFeeds(feverFeeds: FeverFeeds) = with(feverFeeds) {
|
||||
private suspend fun insertFeeds(feverFeeds: FeverFeeds) = with(feverFeeds) {
|
||||
for (feed in feeds) {
|
||||
for ((folderId, feedsIds) in feedsGroups) {
|
||||
if (feedsIds.contains(feed.remoteId!!.toInt())) feed.remoteFolderId = folderId.toString()
|
||||
if (feedsIds.contains(feed.remoteId!!.toInt())) {
|
||||
feed.remoteFolderId = folderId.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
feeds.forEach { it.accountId = account.id }
|
||||
database.feedDao().feedsUpsert(feeds, account)
|
||||
database.feedDao().upsertFeeds(feeds, account)
|
||||
}
|
||||
|
||||
private fun insertItems(items: List<Item>) {
|
||||
val itemsToInsert = arrayListOf<Item>()
|
||||
private suspend fun insertItems(items: List<Item>): List<Item> {
|
||||
val newItems = arrayListOf<Item>()
|
||||
val itemsFeedsIds = mutableMapOf<String, Int>()
|
||||
|
||||
for (item in items) {
|
||||
|
@ -171,46 +166,50 @@ class FeverRepository(
|
|||
if (itemsFeedsIds.containsKey(item.feedRemoteId)) {
|
||||
feedId = itemsFeedsIds[item.feedRemoteId]
|
||||
} else {
|
||||
feedId = database.feedDao().getFeedIdByRemoteId(item.feedRemoteId!!, account.id)
|
||||
itemsFeedsIds[item.feedRemoteId!!] = feedId
|
||||
//feedId = database.feedDao().getFeedIdByRemoteId(item.feedRemoteId!!, account.id)
|
||||
// itemsFeedsIds[item.feedRemoteId!!] = feedId
|
||||
}
|
||||
|
||||
item.feedId = feedId!!
|
||||
//item.feedId = feedId!!
|
||||
item.text?.let { item.readTime = Utils.readTimeFromString(it) }
|
||||
|
||||
itemsToInsert += item
|
||||
newItems += item
|
||||
}
|
||||
|
||||
if (itemsToInsert.isNotEmpty()) {
|
||||
itemsToInsert.sortWith(Item::compareTo)
|
||||
database.itemDao().insert(itemsToInsert)
|
||||
if (newItems.isNotEmpty()) {
|
||||
newItems.sortWith(Item::compareTo)
|
||||
database.itemDao().insert(newItems)
|
||||
.zip(newItems)
|
||||
.forEach { (id, item) -> item.id = id.toInt() }
|
||||
}
|
||||
|
||||
return newItems
|
||||
}
|
||||
|
||||
private fun insertItemsIds(unreadIds: List<String>, starredIds: MutableList<String>) {
|
||||
database.itemStateDao().deleteItemsStates(account.id)
|
||||
private suspend fun insertItemsIds(unreadIds: List<String>, starredIds: MutableList<String>) {
|
||||
database.itemStateDao().deleteItemStates(account.id)
|
||||
|
||||
database.itemStateDao().insertItemStates(unreadIds.map { unreadId ->
|
||||
database.itemStateDao().insert(unreadIds.map { unreadId ->
|
||||
val starred = starredIds.any { starredId -> starredId == unreadId }
|
||||
if (starred) starredIds.remove(unreadId)
|
||||
|
||||
ItemState(
|
||||
id = 0,
|
||||
read = false,
|
||||
starred = starred,
|
||||
remoteId = unreadId,
|
||||
accountId = account.id,
|
||||
id = 0,
|
||||
read = false,
|
||||
starred = starred,
|
||||
remoteId = unreadId,
|
||||
accountId = account.id,
|
||||
)
|
||||
})
|
||||
|
||||
if (starredIds.isNotEmpty()) {
|
||||
database.itemStateDao().insertItemStates(starredIds.map { starredId ->
|
||||
database.itemStateDao().insert(starredIds.map { starredId ->
|
||||
ItemState(
|
||||
id = 0,
|
||||
read = true, // if this id wasn't in the unread ids list, it is considered a read
|
||||
starred = true,
|
||||
remoteId = starredId,
|
||||
accountId = account.id,
|
||||
id = 0,
|
||||
read = true, // if this id wasn't in the unread ids list, it is considered a read
|
||||
starred = true,
|
||||
remoteId = starredId,
|
||||
accountId = account.id,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
@ -219,12 +218,12 @@ class FeverRepository(
|
|||
private fun getFeverRequestBody(): MultipartBody {
|
||||
val credentials = ApiUtils.md5hash("${account.login}:${account.password}")
|
||||
return MultipartBody.Builder()
|
||||
.setType(MultipartBody.FORM)
|
||||
.addFormDataPart("api_key", credentials)
|
||||
.build()
|
||||
.setType(MultipartBody.FORM)
|
||||
.addFormDataPart("api_key", credentials)
|
||||
.build()
|
||||
}
|
||||
|
||||
companion object {
|
||||
val TAG: String = FeverRepository::class.java.simpleName
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ enum class AccountType(@DrawableRes val iconRes: Int,
|
|||
val accountConfig: AccountConfig?) {
|
||||
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),
|
||||
//FEEDLY(R.drawable.ic_feedly, R.string.feedly, null),
|
||||
FRESHRSS(R.drawable.ic_freshrss, R.string.freshrss, AccountConfig.FRESHRSS),
|
||||
FEVER(R.mipmap.ic_launcher, R.string.fever, AccountConfig.FEVER)
|
||||
}
|
|
@ -27,7 +27,7 @@ object FeedUnreadCountQueryBuilder {
|
|||
)
|
||||
} else {
|
||||
SimpleSQLiteQuery(
|
||||
"""Select feed_id, count(*) AS item_count From ItemState Inner Join Item On ItemState.remote_id = Item.remoteId
|
||||
"""Select feed_id, count(*) AS item_count From ItemState Inner Join Item On ItemState.remote_id = Item.remote_id
|
||||
Where ItemState.read = 0 And account_id = $accountId $filter Group By feed_id""".trimIndent())
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue