Compare commits

..

No commits in common. "6ec3e96909584cc94406eaa816bc4c9791220cb1" and "381d6acc829ba8dba25deb9d78ee2d616a9cde4f" have entirely different histories.

7 changed files with 36 additions and 1064 deletions

View File

@ -15,7 +15,6 @@ steps:
- echo "---------------------------------------------------------"
- echo "Testing..."
- echo "---------------------------------------------------------"
- ./gradlew test -PignoreGitVersion=true -P appLoginUrl="\"URL\"" -P appLoginUsername="\"LOGIN\"" -P appLoginPassword="\"PASS\"" -P pushCache=false
environment:
SONAR_HOST_URL:
from_secret: sonarScannerHostUrl

View File

@ -355,7 +355,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
val drawerData = DrawerData(repository.getDBTags().map { it.toView() },
repository.getDBSources().map { it.toView() })
runOnUiThread {
// TODO: All this logic should be handled by the repository, simplify and remove direct DB access
// Only refresh if there is no data in the DB, or if the `UpdateSources` setting is enabled
if (drawerData.sources?.isEmpty() == true || appSettingsService.isUpdateSourcesEnabled()) {
drawerApiCalls(drawerData)

View File

@ -163,6 +163,7 @@ class LoginActivity : AppCompatActivity(), DIAware {
CoroutineScope(Dispatchers.IO).launch {
val result = repository.login()
if (result) {
repository.updateApiVersion()
goToMain()
} else {
CoroutineScope(Dispatchers.Main).launch {

View File

@ -52,13 +52,11 @@ override fun doWork(): Result {
repository.handleDBActions()
val apiItems = repository.tryToCacheItemsAndGetNewOnes()
if (appSettingsService.isNotifyNewItemsEnabled()) {
launch {
handleNewItemsNotification(apiItems, notificationManager)
handleNewItemsNotification(repository.tryToCacheItemsAndGetNewOnes(), notificationManager)
}
}
apiItems.map { it.preloadImages(context) }
}
}
return Result.success()
@ -68,7 +66,6 @@ override fun doWork(): Result {
newItems: List<SelfossModel.Item>?,
notificationManager: NotificationManager
) {
// TODO: Check if this coroutine is actually required
CoroutineScope(Dispatchers.IO).launch {
val apiItems = newItems.orEmpty()
@ -105,6 +102,7 @@ override fun doWork(): Result {
notificationManager.notify(2, newItemsNotification.build())
}
}
apiItems.map { it.preloadImages(context) }
Timer("", false).schedule(4000) {
notificationManager.cancel(1)
}

View File

@ -56,8 +56,6 @@ kotlin {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
implementation("io.mockk:mockk:1.12.0")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0")
}
}
val androidMain by getting {

View File

@ -11,7 +11,6 @@ import io.github.aakira.napier.Napier
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
class Repository(private val api: SelfossApi, private val appSettingsService: AppSettingsService, connectivityStatus: ConnectivityStatus, private val db: ReaderForSelfossDB) {
@ -37,12 +36,9 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
var badgeStarred = 0
set(value) {field = if (value < 0) { 0 } else { value } }
private var fetchedSources = false
private var fetchedTags = false
init {
// TODO: Dispatchers.IO not available in KMM, an alternative solution should be found
runBlocking {
CoroutineScope(Dispatchers.Main).launch {
updateApiVersion()
dateUtils = DateUtils(appSettingsService)
reloadBadges()
@ -109,9 +105,9 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
val items = api.getItems(
itemType.type,
0,
null,
null,
null,
tagFilter?.tag,
sourceFilter?.id?.toLong(),
searchFilter,
null,
200
)
@ -135,40 +131,32 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
badgeStarred = response.data.starred
success = true
}
} else if (appSettingsService.isItemCachingEnabled()) {
} else {
// TODO: do this differently, because it's not efficient
val dbItems = getDBItems()
badgeUnread = dbItems.filter { item -> item.unread }.size
badgeStarred = dbItems.filter { item -> item.starred }.size
badgeAll = dbItems.size
success = true
badgeAll = items.size
}
return success
}
suspend fun getTags(): List<SelfossModel.Tag> {
val isDatabaseEnabled = appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled()
return if (isNetworkAvailable() && !fetchedTags) {
suspend fun getTags(): List<SelfossModel.Tag>? {
return if (isNetworkAvailable()) {
val apiTags = api.tags()
if (apiTags.success && apiTags.data != null && isDatabaseEnabled) {
if (apiTags.success && apiTags.data != null && (appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled())) {
resetDBTagsWithData(apiTags.data)
if (!appSettingsService.isUpdateSourcesEnabled()) {
fetchedTags = true
}
}
apiTags.data ?: emptyList()
} else if (isDatabaseEnabled) {
getDBTags().map { it.toView() }
apiTags.data
} else {
emptyList()
getDBTags().map { it.toView() }
}
}
// TODO: Add tests
suspend fun getSpouts(): Map<String, SelfossModel.Spout> {
suspend fun getSpouts(): Map<String, SelfossModel.Spout>? {
return if (isNetworkAvailable()) {
val spouts = api.spouts()
if (spouts.success && spouts.data != null) {
return if (spouts.success && spouts.data != null) {
spouts.data
} else {
emptyMap() // TODO: do something here
@ -178,25 +166,18 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
}
}
suspend fun getSources(): ArrayList<SelfossModel.Source> {
val isDatabaseEnabled = appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled()
return if (isNetworkAvailable() && !fetchedSources) {
suspend fun getSources(): ArrayList<SelfossModel.Source>? {
return if (isNetworkAvailable()) {
val apiSources = api.sources()
if (apiSources.success && apiSources.data != null && isDatabaseEnabled) {
if (apiSources.success && apiSources.data != null && (appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled())) {
resetDBSourcesWithData(apiSources.data)
if (!appSettingsService.isUpdateSourcesEnabled()) {
fetchedSources = true
}
}
apiSources.data ?: ArrayList()
} else if (isDatabaseEnabled) {
ArrayList(getDBSources().map { it.toView() })
apiSources.data
} else {
ArrayList()
ArrayList(getDBSources().map { it.toView() })
}
}
// TODO: Add tests
suspend fun markAsRead(item: SelfossModel.Item): Boolean {
val success = markAsReadById(item.id)
@ -208,14 +189,14 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
private suspend fun markAsReadById(id: Int): Boolean {
return if (isNetworkAvailable()) {
api.markAsRead(id.toString()).isSuccess
api.markAsRead(id.toString())?.isSuccess
} else {
insertDBAction(id.toString(), read = true)
true
}
}
// TODO: Add tests
suspend fun unmarkAsRead(item: SelfossModel.Item): Boolean {
val success = unmarkAsReadById(item.id)
@ -227,14 +208,13 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
private suspend fun unmarkAsReadById(id: Int): Boolean {
return if (isNetworkAvailable()) {
api.unmarkAsRead(id.toString()).isSuccess
api.unmarkAsRead(id.toString())?.isSuccess
} else {
insertDBAction(id.toString(), unread = true)
true
}
}
// TODO: Add tests
suspend fun starr(item: SelfossModel.Item): Boolean {
val success = starrById(item.id)
@ -246,14 +226,13 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
private suspend fun starrById(id: Int): Boolean {
return if (isNetworkAvailable()) {
api.starr(id.toString()).isSuccess
api.starr(id.toString())?.isSuccess
} else {
insertDBAction(id.toString(), starred = true)
true
}
}
// TODO: Add tests
suspend fun unstarr(item: SelfossModel.Item): Boolean {
val success = unstarrById(item.id)
@ -265,18 +244,17 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
private suspend fun unstarrById(id: Int): Boolean {
return if (isNetworkAvailable()) {
api.unstarr(id.toString()).isSuccess
api.unstarr(id.toString())?.isSuccess
} else {
insertDBAction(id.toString(), starred = true)
true
}
}
// TODO: Add tests
suspend fun markAllAsRead(items: ArrayList<SelfossModel.Item>): Boolean {
var success = false
if (isNetworkAvailable() && api.markAllAsRead(items.map { it.id.toString() }).isSuccess) {
if (isNetworkAvailable() && api.markAllAsRead(items.map { it.id.toString() })?.isSuccess) {
success = true
for (item in items) {
markAsReadLocally(item)
@ -345,7 +323,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
tags,
filter,
appSettingsService.getApiVersion()
).isSuccess == true
)?.isSuccess == true
}
return response
@ -355,7 +333,9 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
var success = false
if (isNetworkAvailable()) {
val response = api.deleteSource(id)
success = response.isSuccess
if (response != null) {
success = response.isSuccess
}
}
return success
@ -363,7 +343,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
suspend fun updateRemote(): Boolean {
return if (isNetworkAvailable()) {
api.update().data.equals("finished")
api.update()?.equals("finished")
} else {
false
}
@ -374,7 +354,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
if (isNetworkAvailable()) {
try {
val response = api.login()
result = response.isSuccess == true
result = response?.isSuccess == true
if (result) {
updateApiVersion()
}
@ -391,7 +371,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
api.refreshLoginInformation()
}
private suspend fun updateApiVersion() {
suspend fun updateApiVersion() {
val apiMajorVersion = appSettingsService.getApiVersion()
if (isNetworkAvailable()) {
@ -410,10 +390,8 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
private fun deleteDBAction(action: ACTION) =
db.actionsQueries.deleteAction(action.id)
// TODO: This function should be private
fun getDBTags(): List<TAG> = db.tagsQueries.tags().executeAsList()
// TODO: This function should be private
fun getDBSources(): List<SOURCE> = db.sourcesQueries.sources().executeAsList()
private fun resetDBTagsWithData(tagEntities: List<SelfossModel.Tag>) {
@ -452,7 +430,8 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
private fun updateDBItem(item: SelfossModel.Item) =
db.itemsQueries.updateItem(item.datetime, item.title.getHtmlDecoded(), item.content, item.unread, item.starred, item.thumbnail, item.icon, item.link, item.sourcetitle, item.tags.joinToString(","), item.id.toString())
suspend fun tryToCacheItemsAndGetNewOnes(): List<SelfossModel.Item> {
suspend fun tryToCacheItemsAndGetNewOnes(): List<SelfossModel.Item>? {
try {
val newItems = getMaxItemsForBackground(ItemType.UNREAD)
val allItems = getMaxItemsForBackground(ItemType.ALL)
@ -465,7 +444,6 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
return emptyList()
}
// TODO: Add tests
suspend fun handleDBActions() {
val actions: List<ACTION> = getDBActions()