forked from Louvorg/ReaderForSelfoss-multiplatform
Compare commits
89 Commits
v122092701
...
v122113101
Author | SHA1 | Date | |
---|---|---|---|
e36189e2e7 | |||
d6bdf510a4 | |||
a464e93370 | |||
4b63afe62a | |||
ac4c4b9441 | |||
16b10dc1b7 | |||
02d734eee8 | |||
c5cdfc0d53 | |||
6d610ed61a | |||
792950be7c | |||
af8969ce4a | |||
27c55e59a1 | |||
94a0747947 | |||
d862bfba4f | |||
b0d1d9c29a | |||
7b40a31979 | |||
823a8c3692 | |||
5494978db8 | |||
6076eb1cee | |||
131101d2ee | |||
62ad1f45ba | |||
402d18b889 | |||
e32699c93f | |||
059a237b99 | |||
d2bdbae6c8 | |||
510fcbe47e | |||
667e9c1a5d | |||
53b1d1f8b2 | |||
c25e8889a4 | |||
8b0bbe71c9 | |||
8bfe14c019 | |||
208babbce3 | |||
02098a7aa9 | |||
d0a982f385 | |||
1d1c121aab | |||
fe12819163 | |||
023a30c008 | |||
a2862a2587 | |||
054e936657 | |||
1d2e5069b8 | |||
a147646743 | |||
32e7fc0038 | |||
c15bf44032 | |||
0bcd55bd4e | |||
ebef0b3511 | |||
713ceb05bf | |||
dc8381b661 | |||
b5b820c64b | |||
f7055626d9 | |||
6ec3e96909 | |||
22da30eaa8 | |||
79fd115f5e | |||
8dc3d319cd | |||
27bb056397 | |||
f9ba13dc32 | |||
6f60ef4346 | |||
28b950f467 | |||
a9c7ec3dc1 | |||
920d4ac1ef | |||
0e96d313ec | |||
7211fdb1a3 | |||
381d6acc82 | |||
d311c2cdeb | |||
219cae5d74 | |||
2968aee309 | |||
6cb4b35c93 | |||
15ec0f2d26 | |||
4781e30da2 | |||
c8759cc035 | |||
cb4f2f02ef | |||
7517626ab7 | |||
41c951b659 | |||
e2afff0b8e | |||
a382fc89ea | |||
3f0a3903ae | |||
f46f98cef0 | |||
bf6f1a917e | |||
71c0a4d340 | |||
63c550ead3 | |||
366b2e10f1 | |||
d2436bb976 | |||
ef994460c1 | |||
758708e18d | |||
c0381144d1 | |||
cda3ba6cb4 | |||
a4636cc0c8 | |||
60c24fc75a | |||
5853a19937 | |||
99f2c04bf6 |
26
.drone.yml
26
.drone.yml
@ -3,28 +3,22 @@ type: docker
|
|||||||
name: test
|
name: test
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Anylyse
|
- name: AnylyseBuildTest
|
||||||
image: mingc/android-build-box:latest
|
image: mingc/android-build-box:latest
|
||||||
failure: ignore
|
|
||||||
detach: true
|
|
||||||
commands:
|
commands:
|
||||||
|
- echo "---------------------------------------------------------"
|
||||||
|
- echo "Configure gradle..."
|
||||||
|
- mkdir -p ~/.gradle && echo "org.gradle.daemon=false\nignoreGitVersion=true\nappLoginUrl=\"URL\"\nappLoginUsername=\"LOGIN\"\nappLoginPassword=\"PASS\"\npushCache=false" >> ~/.gradle/gradle.properties
|
||||||
- echo "---------------------------------------------------------"
|
- echo "---------------------------------------------------------"
|
||||||
- echo "Analysing..."
|
- echo "Analysing..."
|
||||||
- ./gradlew sonarqube -Dsonar.projectKey=RFS2 -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.login=$SONAR_LOGIN -PignoreGitVersion=true -P appLoginUrl="\"URL\"" -P appLoginUsername="\"LOGIN\"" -P appLoginPassword="\"PASS\""
|
- ./gradlew sonarqube -Dsonar.projectKey=RFS2 -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.login=$SONAR_LOGIN
|
||||||
- echo "---------------------------------------------------------"
|
- echo "---------------------------------------------------------"
|
||||||
environment:
|
|
||||||
SONAR_HOST_URL:
|
|
||||||
from_secret: sonarScannerHostUrl
|
|
||||||
SONAR_LOGIN:
|
|
||||||
from_secret: sonarScannerLogin
|
|
||||||
- name: BuildAndTest
|
|
||||||
image: mingc/android-build-box:latest
|
|
||||||
commands:
|
|
||||||
- echo "Building..."
|
- echo "Building..."
|
||||||
- ./gradlew :androidApp:build -PignoreGitVersion=true -P appLoginUrl="\"URL\"" -P appLoginUsername="\"LOGIN\"" -P appLoginPassword="\"PASS\"" -P pushCache=false
|
- ./gradlew build
|
||||||
- echo "---------------------------------------------------------"
|
- echo "---------------------------------------------------------"
|
||||||
- echo "Testing..."
|
- echo "Testing..."
|
||||||
- echo "---------------------------------------------------------"
|
- echo "---------------------------------------------------------"
|
||||||
|
- ./gradlew test
|
||||||
environment:
|
environment:
|
||||||
SONAR_HOST_URL:
|
SONAR_HOST_URL:
|
||||||
from_secret: sonarScannerHostUrl
|
from_secret: sonarScannerHostUrl
|
||||||
@ -94,8 +88,12 @@ steps:
|
|||||||
- name: build
|
- name: build
|
||||||
image: mingc/android-build-box:latest
|
image: mingc/android-build-box:latest
|
||||||
commands:
|
commands:
|
||||||
|
- echo "---------------------------------------------------------"
|
||||||
|
- echo "Configure gradle..."
|
||||||
|
- mkdir -p ~/.gradle && echo "org.gradle.daemon=false\nignoreGitVersion=true\nappLoginUrl=\"URL\"\nappLoginUsername=\"LOGIN\"\nappLoginPassword=\"PASS\"\npushCache=false" >> ~/.gradle/gradle.properties
|
||||||
|
- echo "---------------------------------------------------------"
|
||||||
- echo "Generate APK"
|
- echo "Generate APK"
|
||||||
- ./gradlew :androidApp:assembleGithubConfigRelease -PignoreGitVersion=true -P appLoginUrl="\"URL\"" -P appLoginUsername="\"LOGIN\"" -P appLoginPassword="\"PASS\"" -P pushCache=false
|
- ./gradlew :androidApp:assembleGithubConfigRelease -P pushCache=false
|
||||||
- echo "---------------------------------------------------------"
|
- echo "---------------------------------------------------------"
|
||||||
- echo "Get Key"
|
- echo "Get Key"
|
||||||
- wget https://amine-louveau.fr/key
|
- wget https://amine-louveau.fr/key
|
||||||
|
@ -6,6 +6,7 @@ plugins {
|
|||||||
id("com.android.application")
|
id("com.android.application")
|
||||||
kotlin("android")
|
kotlin("android")
|
||||||
kotlin("kapt")
|
kotlin("kapt")
|
||||||
|
id("com.mikepenz.aboutlibraries.plugin")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Project.execWithOutput(cmd: String, ignore: Boolean = false): String {
|
fun Project.execWithOutput(cmd: String, ignore: Boolean = false): String {
|
||||||
@ -54,11 +55,15 @@ fun versionNameFromGit(): String {
|
|||||||
android {
|
android {
|
||||||
compileOptions {
|
compileOptions {
|
||||||
// Flag to enable support for the new language APIs
|
// Flag to enable support for the new language APIs
|
||||||
isCoreLibraryDesugaringEnabled = true
|
sourceCompatibility = JavaVersion.VERSION_11
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
targetCompatibility = JavaVersion.VERSION_11
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
}
|
}
|
||||||
compileSdk = 31
|
|
||||||
|
// For Kotlin projects
|
||||||
|
kotlinOptions {
|
||||||
|
jvmTarget = "11"
|
||||||
|
}
|
||||||
|
compileSdk = 33
|
||||||
buildToolsVersion = "31.0.0"
|
buildToolsVersion = "31.0.0"
|
||||||
buildFeatures {
|
buildFeatures {
|
||||||
viewBinding = true
|
viewBinding = true
|
||||||
@ -66,7 +71,7 @@ android {
|
|||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = "bou.amine.apps.readerforselfossv2.android"
|
applicationId = "bou.amine.apps.readerforselfossv2.android"
|
||||||
minSdk = 21
|
minSdk = 21
|
||||||
targetSdk = 31
|
targetSdk = 33
|
||||||
versionCode = versionCodeFromGit()
|
versionCode = versionCodeFromGit()
|
||||||
versionName = versionNameFromGit()
|
versionName = versionNameFromGit()
|
||||||
|
|
||||||
@ -79,6 +84,11 @@ android {
|
|||||||
// tests
|
// tests
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
packagingOptions {
|
||||||
|
resources {
|
||||||
|
excludes += "/META-INF/{AL2.0,LGPL2.1}"
|
||||||
|
}
|
||||||
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
getByName("release") {
|
getByName("release") {
|
||||||
isMinifyEnabled = true
|
isMinifyEnabled = true
|
||||||
@ -98,9 +108,6 @@ android {
|
|||||||
dimension = "build"
|
dimension = "build"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
kotlinOptions {
|
|
||||||
jvmTarget = "1.8"
|
|
||||||
}
|
|
||||||
namespace = "bou.amine.apps.readerforselfossv2.android"
|
namespace = "bou.amine.apps.readerforselfossv2.android"
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -114,13 +121,6 @@ dependencies {
|
|||||||
|
|
||||||
implementation("androidx.preference:preference-ktx:1.1.1")
|
implementation("androidx.preference:preference-ktx:1.1.1")
|
||||||
|
|
||||||
// Testing
|
|
||||||
androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0-alpha02")
|
|
||||||
androidTestImplementation("androidx.test:runner:1.3.1-alpha02")
|
|
||||||
// Espresso-contrib for DatePicker, RecyclerView, Drawer actions, Accessibility checks, CountingIdlingResource
|
|
||||||
androidTestImplementation("androidx.test.espresso:espresso-contrib:3.4.0-alpha02")
|
|
||||||
// Espresso-intents for validation and stubbing of Intents
|
|
||||||
androidTestImplementation("androidx.test.espresso:espresso-intents:3.4.0-alpha02")
|
|
||||||
implementation(fileTree(mapOf("include" to listOf("*.jar"), "dir" to "libs")))
|
implementation(fileTree(mapOf("include" to listOf("*.jar"), "dir" to "libs")))
|
||||||
|
|
||||||
// Android Support
|
// Android Support
|
||||||
@ -135,18 +135,12 @@ dependencies {
|
|||||||
implementation("androidx.constraintlayout:constraintlayout:2.1.3")
|
implementation("androidx.constraintlayout:constraintlayout:2.1.3")
|
||||||
implementation("org.jsoup:jsoup:1.14.3")
|
implementation("org.jsoup:jsoup:1.14.3")
|
||||||
|
|
||||||
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:1.1.5")
|
|
||||||
|
|
||||||
//multidex
|
//multidex
|
||||||
implementation("androidx.multidex:multidex:2.0.1")
|
implementation("androidx.multidex:multidex:2.0.1")
|
||||||
|
|
||||||
// About
|
// About
|
||||||
implementation("com.mikepenz:aboutlibraries-core:8.9.4")
|
implementation("com.mikepenz:aboutlibraries-core:10.5.1")
|
||||||
implementation("com.mikepenz:aboutlibraries:8.9.4")
|
implementation("com.mikepenz:aboutlibraries:10.5.1")
|
||||||
implementation("com.mikepenz:aboutlibraries-definitions:8.9.4")
|
|
||||||
|
|
||||||
// Async
|
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.0")
|
|
||||||
|
|
||||||
// Retrofit + http logging + okhttp
|
// Retrofit + http logging + okhttp
|
||||||
implementation("com.squareup.retrofit2:retrofit:2.9.0")
|
implementation("com.squareup.retrofit2:retrofit:2.9.0")
|
||||||
@ -188,14 +182,41 @@ dependencies {
|
|||||||
|
|
||||||
implementation("androidx.core:core-ktx:1.8.0")
|
implementation("androidx.core:core-ktx:1.8.0")
|
||||||
|
|
||||||
// implementation("androidx.lifecycle:lifecycle-livedata-ktx:2.5.1")
|
|
||||||
// implementation("androidx.lifecycle:lifecycle-common-java8:2.5.1")
|
|
||||||
// implementation("androidx.lifecycle:lifecycle-runtime:2.5.1")
|
|
||||||
implementation("androidx.lifecycle:lifecycle-extensions:2.2.0")
|
implementation("androidx.lifecycle:lifecycle-extensions:2.2.0")
|
||||||
|
|
||||||
// Network information
|
// Network information
|
||||||
implementation("com.github.ln-12:multiplatform-connectivity-status:1.3.0")
|
implementation("com.github.ln-12:multiplatform-connectivity-status:1.3.0")
|
||||||
|
|
||||||
// SQLDELIGHT
|
// SQLDELIGHT
|
||||||
implementation("com.squareup.sqldelight:android-driver:1.5.3")
|
implementation("com.squareup.sqldelight:android-driver:1.5.4")
|
||||||
|
|
||||||
|
//test
|
||||||
|
testImplementation("junit:junit:4.13.2")
|
||||||
|
testImplementation("io.mockk:mockk:1.12.0")
|
||||||
|
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0")
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType<Test> {
|
||||||
|
outputs.upToDateWhen { false }
|
||||||
|
useJUnit()
|
||||||
|
testLogging {
|
||||||
|
exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL
|
||||||
|
events = setOf(
|
||||||
|
org.gradle.api.tasks.testing.logging.TestLogEvent.PASSED,
|
||||||
|
org.gradle.api.tasks.testing.logging.TestLogEvent.FAILED,
|
||||||
|
org.gradle.api.tasks.testing.logging.TestLogEvent.STANDARD_ERROR
|
||||||
|
)
|
||||||
|
showStandardStreams = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aboutLibraries {
|
||||||
|
offlineMode = true
|
||||||
|
fetchRemoteLicense = false
|
||||||
|
fetchRemoteFunding = false
|
||||||
|
includePlatform = false
|
||||||
|
strictMode = com.mikepenz.aboutlibraries.plugin.StrictMode.FAIL
|
||||||
|
duplicationMode = com.mikepenz.aboutlibraries.plugin.DuplicateMode.MERGE
|
||||||
|
duplicationRule = com.mikepenz.aboutlibraries.plugin.DuplicateRule.GROUP
|
||||||
}
|
}
|
2
androidApp/proguard-rules.pro
vendored
2
androidApp/proguard-rules.pro
vendored
@ -90,3 +90,5 @@
|
|||||||
# @Serializable and @Polymorphic are used at runtime for polymorphic serialization.
|
# @Serializable and @Polymorphic are used at runtime for polymorphic serialization.
|
||||||
-keepattributes RuntimeVisibleAnnotations,AnnotationDefault
|
-keepattributes RuntimeVisibleAnnotations,AnnotationDefault
|
||||||
|
|
||||||
|
-dontwarn io.mockk.**
|
||||||
|
-keep class io.mockk.** { *; }
|
||||||
|
@ -94,7 +94,7 @@ class AddSourceActivity : AppCompatActivity(), DIAware {
|
|||||||
CoroutineScope(Dispatchers.Main).launch {
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
try {
|
try {
|
||||||
val items = repository.getSpouts()
|
val items = repository.getSpouts()
|
||||||
if (items != null) {
|
if (items.isNotEmpty()) {
|
||||||
val itemsStrings = items.map { it.value.name }
|
val itemsStrings = items.map { it.value.name }
|
||||||
for ((key, value) in items) {
|
for ((key, value) in items) {
|
||||||
spoutsKV[value.name] = key
|
spoutsKV[value.name] = key
|
||||||
|
@ -15,12 +15,10 @@ import androidx.activity.result.contract.ActivityResultContracts
|
|||||||
import androidx.appcompat.app.ActionBarDrawerToggle
|
import androidx.appcompat.app.ActionBarDrawerToggle
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
|
||||||
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_NO
|
|
||||||
import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_YES
|
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.core.view.doOnNextLayout
|
import androidx.core.view.doOnNextLayout
|
||||||
import androidx.drawerlayout.widget.DrawerLayout
|
import androidx.drawerlayout.widget.DrawerLayout
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.recyclerview.widget.*
|
import androidx.recyclerview.widget.*
|
||||||
import androidx.work.Constraints
|
import androidx.work.Constraints
|
||||||
import androidx.work.ExistingPeriodicWorkPolicy
|
import androidx.work.ExistingPeriodicWorkPolicy
|
||||||
@ -98,8 +96,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
private val repository : Repository by instance()
|
private val repository : Repository by instance()
|
||||||
private val appSettingsService : AppSettingsService by instance()
|
private val appSettingsService : AppSettingsService by instance()
|
||||||
|
|
||||||
data class DrawerData(val tags: List<SelfossModel.Tag>?, val sources: List<SelfossModel.Source>?)
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
binding = ActivityHomeBinding.inflate(layoutInflater)
|
binding = ActivityHomeBinding.inflate(layoutInflater)
|
||||||
@ -183,8 +179,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
|
|
||||||
adapter.handleItemAtIndex(position)
|
adapter.handleItemAtIndex(position)
|
||||||
|
|
||||||
reloadBadgeContent()
|
|
||||||
|
|
||||||
val tagHashes = i.tags.map { it.longHash() }
|
val tagHashes = i.tags.map { it.longHash() }
|
||||||
tagsBadge = tagsBadge.map {
|
tagsBadge = tagsBadge.map {
|
||||||
if (tagHashes.contains(it.key)) {
|
if (tagHashes.contains(it.key)) {
|
||||||
@ -212,6 +206,16 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
ItemTouchHelper(simpleItemTouchCallback).attachToRecyclerView(binding.recyclerView)
|
ItemTouchHelper(simpleItemTouchCallback).attachToRecyclerView(binding.recyclerView)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateBottomBarBadgeCount(badge: TextBadgeItem, count: Int) {
|
||||||
|
if (count > 0) {
|
||||||
|
badge
|
||||||
|
.setText(count.toString())
|
||||||
|
.maybeShow()
|
||||||
|
} else {
|
||||||
|
badge.removeBadge()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun handleBottomBar() {
|
private fun handleBottomBar() {
|
||||||
|
|
||||||
tabNewBadge = TextBadgeItem()
|
tabNewBadge = TextBadgeItem()
|
||||||
@ -224,6 +228,28 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
.setText("")
|
.setText("")
|
||||||
.setHideOnSelect(false).hide(false)
|
.setHideOnSelect(false).hide(false)
|
||||||
|
|
||||||
|
if (appSettingsService.isDisplayUnreadCountEnabled()) {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
repository.badgeUnread.collect {
|
||||||
|
updateBottomBarBadgeCount(tabNewBadge, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appSettingsService.isDisplayAllCountEnabled()) {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
repository.badgeAll.collect {
|
||||||
|
updateBottomBarBadgeCount(tabArchiveBadge, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lifecycleScope.launch {
|
||||||
|
repository.badgeStarred.collect {
|
||||||
|
updateBottomBarBadgeCount(tabStarredBadge, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val tabNew =
|
val tabNew =
|
||||||
BottomNavigationItem(
|
BottomNavigationItem(
|
||||||
R.drawable.ic_tab_fiber_new_black_24dp,
|
R.drawable.ic_tab_fiber_new_black_24dp,
|
||||||
@ -352,27 +378,15 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
)
|
)
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
val drawerData = DrawerData(repository.getDBTags().map { it.toView() },
|
val tags = repository.getTags()
|
||||||
repository.getDBSources().map { it.toView() })
|
val sources = repository.getSources()
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
// Only refresh if there is no data in the DB, or if the `UpdateSources` setting is enabled
|
handleDrawerData(tags, sources)
|
||||||
if (drawerData.sources?.isEmpty() == true || appSettingsService.isUpdateSourcesEnabled()) {
|
|
||||||
drawerApiCalls(drawerData)
|
|
||||||
} else {
|
|
||||||
handleDrawerData(drawerData, loadedFromCache = true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun drawerApiCalls(drawerData: DrawerData) {
|
private fun handleDrawerData(tags: List<SelfossModel.Tag>, sources: List<SelfossModel.Source>) {
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
|
||||||
val apiDrawerData = DrawerData(repository.getTags(), repository.getSources())
|
|
||||||
handleDrawerData(if (drawerData != apiDrawerData) apiDrawerData else drawerData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleDrawerData(drawerData: DrawerData, loadedFromCache: Boolean = false) {
|
|
||||||
binding.mainDrawer.itemAdapter.clear()
|
binding.mainDrawer.itemAdapter.clear()
|
||||||
|
|
||||||
// Filters title with clear action
|
// Filters title with clear action
|
||||||
@ -386,24 +400,24 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Hidden tags
|
// Hidden tags
|
||||||
if (drawerData.tags != null && drawerData.tags.isNotEmpty() && appSettingsService.getHiddenTags().isNotEmpty()) {
|
if (tags.isNotEmpty() && appSettingsService.getHiddenTags().isNotEmpty()) {
|
||||||
secondaryItem(
|
secondaryItem(
|
||||||
withDivider = true,
|
withDivider = true,
|
||||||
R.string.drawer_item_hidden_tags,
|
R.string.drawer_item_hidden_tags,
|
||||||
DRAWER_ID_HIDDEN_TAGS
|
DRAWER_ID_HIDDEN_TAGS
|
||||||
)
|
)
|
||||||
handleHiddenTags(drawerData.tags)
|
handleHiddenTags(tags)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tags
|
// Tags
|
||||||
secondaryItem(withDivider = true, R.string.drawer_item_tags, DRAWER_ID_TAGS)
|
secondaryItem(withDivider = true, R.string.drawer_item_tags, DRAWER_ID_TAGS)
|
||||||
if (drawerData.tags == null && !loadedFromCache) {
|
if (tags.isEmpty()) {
|
||||||
binding.mainDrawer.itemAdapter.add(
|
binding.mainDrawer.itemAdapter.add(
|
||||||
SecondaryDrawerItem()
|
SecondaryDrawerItem()
|
||||||
.apply { nameRes = R.string.drawer_error_loading_tags; isSelectable = false }
|
.apply { nameRes = R.string.drawer_error_loading_tags; isSelectable = false }
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
handleTags(drawerData.tags!!)
|
handleTags(tags)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sources
|
// Sources
|
||||||
@ -411,15 +425,15 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
startActivity(Intent(v!!.context, SourcesActivity::class.java))
|
startActivity(Intent(v!!.context, SourcesActivity::class.java))
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
if (drawerData.sources == null && !loadedFromCache) {
|
if (sources.isEmpty()) {
|
||||||
binding.mainDrawer.itemAdapter.add(
|
binding.mainDrawer.itemAdapter.add(
|
||||||
SecondaryDrawerItem().apply {
|
SecondaryDrawerItem().apply {
|
||||||
nameRes = R.string.drawer_error_loading_tags
|
nameRes = R.string.drawer_error_loading_sources
|
||||||
isSelectable = false
|
isSelectable = false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
handleSources(drawerData.sources!!)
|
handleSources(sources)
|
||||||
}
|
}
|
||||||
|
|
||||||
// About action
|
// About action
|
||||||
@ -731,29 +745,12 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
|
|
||||||
private fun reloadBadges() {
|
private fun reloadBadges() {
|
||||||
if (appSettingsService.isDisplayUnreadCountEnabled() || appSettingsService.isDisplayAllCountEnabled()) {
|
if (appSettingsService.isDisplayUnreadCountEnabled() || appSettingsService.isDisplayAllCountEnabled()) {
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
repository.reloadBadges()
|
repository.reloadBadges()
|
||||||
reloadBadgeContent()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun reloadBadgeContent() {
|
|
||||||
if (appSettingsService.isDisplayUnreadCountEnabled()) {
|
|
||||||
tabNewBadge
|
|
||||||
.setText(repository.badgeUnread.toString())
|
|
||||||
.maybeShow()
|
|
||||||
}
|
|
||||||
if (appSettingsService.isDisplayAllCountEnabled()) {
|
|
||||||
tabArchiveBadge
|
|
||||||
.setText(repository.badgeAll.toString())
|
|
||||||
.maybeShow()
|
|
||||||
tabStarredBadge
|
|
||||||
.setText(repository.badgeStarred.toString())
|
|
||||||
.maybeShow()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun reloadTagsBadges() {
|
private fun reloadTagsBadges() {
|
||||||
tagsBadge.forEach {
|
tagsBadge.forEach {
|
||||||
binding.mainDrawer.updateBadge(it.key, StringHolder(it.value.toString()))
|
binding.mainDrawer.updateBadge(it.key, StringHolder(it.value.toString()))
|
||||||
@ -875,10 +872,10 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
|
|
||||||
private fun maxItemNumber(): Int =
|
private fun maxItemNumber(): Int =
|
||||||
when (elementsShown) {
|
when (elementsShown) {
|
||||||
ItemType.UNREAD -> repository.badgeUnread
|
ItemType.UNREAD -> repository.badgeUnread.value
|
||||||
ItemType.ALL -> repository.badgeAll
|
ItemType.ALL -> repository.badgeAll.value
|
||||||
ItemType.STARRED -> repository.badgeStarred
|
ItemType.STARRED -> repository.badgeStarred.value
|
||||||
else -> repository.badgeUnread // if !elementsShown then unread are fetched.
|
else -> repository.badgeUnread.value // if !elementsShown then unread are fetched.
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateItems(adapterItems: ArrayList<SelfossModel.Item>) {
|
private fun updateItems(adapterItems: ArrayList<SelfossModel.Item>) {
|
||||||
|
@ -93,12 +93,15 @@ class LoginActivity : AppCompatActivity(), DIAware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun goToMain() {
|
private fun goToMain() {
|
||||||
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
|
repository.updateApiVersion()
|
||||||
|
}
|
||||||
val intent = Intent(this, HomeActivity::class.java)
|
val intent = Intent(this, HomeActivity::class.java)
|
||||||
startActivity(intent)
|
startActivity(intent)
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun preferenceError(t: Throwable) {
|
private fun preferenceError() {
|
||||||
appSettingsService.resetLoginInformation()
|
appSettingsService.resetLoginInformation()
|
||||||
|
|
||||||
binding.urlView.error = getString(R.string.wrong_infos)
|
binding.urlView.error = getString(R.string.wrong_infos)
|
||||||
@ -163,11 +166,10 @@ class LoginActivity : AppCompatActivity(), DIAware {
|
|||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
val result = repository.login()
|
val result = repository.login()
|
||||||
if (result) {
|
if (result) {
|
||||||
repository.updateApiVersion()
|
|
||||||
goToMain()
|
goToMain()
|
||||||
} else {
|
} else {
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
preferenceError(Exception("Not success"))
|
preferenceError()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ import androidx.lifecycle.ProcessLifecycleOwner
|
|||||||
import androidx.multidex.MultiDexApplication
|
import androidx.multidex.MultiDexApplication
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
import bou.amine.apps.readerforselfossv2.DI.networkModule
|
import bou.amine.apps.readerforselfossv2.DI.networkModule
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAccessible
|
||||||
import bou.amine.apps.readerforselfossv2.android.viewmodel.AppViewModel
|
import bou.amine.apps.readerforselfossv2.android.viewmodel.AppViewModel
|
||||||
import bou.amine.apps.readerforselfossv2.dao.DriverFactory
|
import bou.amine.apps.readerforselfossv2.dao.DriverFactory
|
||||||
import bou.amine.apps.readerforselfossv2.dao.ReaderForSelfossDB
|
import bou.amine.apps.readerforselfossv2.dao.ReaderForSelfossDB
|
||||||
@ -28,6 +29,7 @@ import io.github.aakira.napier.DebugAntilog
|
|||||||
import io.github.aakira.napier.Napier
|
import io.github.aakira.napier.Napier
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.kodein.di.*
|
import org.kodein.di.*
|
||||||
|
|
||||||
@ -37,7 +39,7 @@ class MyApp : MultiDexApplication(), DIAware {
|
|||||||
import(networkModule)
|
import(networkModule)
|
||||||
bind<DriverFactory>() with singleton { DriverFactory(applicationContext) }
|
bind<DriverFactory>() with singleton { DriverFactory(applicationContext) }
|
||||||
bind<ReaderForSelfossDB>() with singleton { ReaderForSelfossDB(driverFactory.createDriver()) }
|
bind<ReaderForSelfossDB>() with singleton { ReaderForSelfossDB(driverFactory.createDriver()) }
|
||||||
bind<Repository>() with singleton { Repository(instance(), instance(), connectivityStatus, instance()) }
|
bind<Repository>() with singleton { Repository(instance(), instance(), isConnectionAvailable, instance()) }
|
||||||
bind<ConnectivityStatus>() with singleton { ConnectivityStatus(applicationContext) }
|
bind<ConnectivityStatus>() with singleton { ConnectivityStatus(applicationContext) }
|
||||||
bind<AppViewModel>() with singleton { AppViewModel(repository = instance()) }
|
bind<AppViewModel>() with singleton { AppViewModel(repository = instance()) }
|
||||||
}
|
}
|
||||||
@ -47,6 +49,9 @@ class MyApp : MultiDexApplication(), DIAware {
|
|||||||
private val connectivityStatus: ConnectivityStatus by instance()
|
private val connectivityStatus: ConnectivityStatus by instance()
|
||||||
private val driverFactory: DriverFactory by instance()
|
private val driverFactory: DriverFactory by instance()
|
||||||
|
|
||||||
|
// TODO: handle with the "previous" way
|
||||||
|
private val isConnectionAvailable: MutableStateFlow<Boolean> = MutableStateFlow(true)
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
Napier.base(DebugAntilog())
|
Napier.base(DebugAntilog())
|
||||||
@ -75,7 +80,6 @@ class MyApp : MultiDexApplication(), DIAware {
|
|||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleNotificationChannels() {
|
private fun handleNotificationChannels() {
|
||||||
|
@ -36,9 +36,9 @@ class ReaderActivity : AppCompatActivity(), DIAware {
|
|||||||
|
|
||||||
private fun showMenuItem(willAddToFavorite: Boolean) {
|
private fun showMenuItem(willAddToFavorite: Boolean) {
|
||||||
if (willAddToFavorite) {
|
if (willAddToFavorite) {
|
||||||
toolbarMenu.findItem(R.id.star).icon.setTint(Color.WHITE)
|
toolbarMenu.findItem(R.id.star).icon?.setTint(Color.WHITE)
|
||||||
} else {
|
} else {
|
||||||
toolbarMenu.findItem(R.id.star).icon.setTint(Color.RED)
|
toolbarMenu.findItem(R.id.star).icon?.setTint(Color.RED)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,20 +56,13 @@ class SourcesActivity : AppCompatActivity(), DIAware {
|
|||||||
|
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
val response = repository.getSources()
|
val response = repository.getSources()
|
||||||
if (response != null) {
|
if (response.isNotEmpty()) {
|
||||||
items = response
|
items = response
|
||||||
val mAdapter = SourcesListAdapter(
|
val mAdapter = SourcesListAdapter(
|
||||||
this@SourcesActivity, items
|
this@SourcesActivity, items
|
||||||
)
|
)
|
||||||
binding.recyclerView.adapter = mAdapter
|
binding.recyclerView.adapter = mAdapter
|
||||||
mAdapter.notifyDataSetChanged()
|
mAdapter.notifyDataSetChanged()
|
||||||
if (items.isEmpty()) {
|
|
||||||
Toast.makeText(
|
|
||||||
this@SourcesActivity,
|
|
||||||
R.string.nothing_here,
|
|
||||||
Toast.LENGTH_SHORT
|
|
||||||
).show()
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
this@SourcesActivity,
|
this@SourcesActivity,
|
||||||
|
@ -10,9 +10,12 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import bou.amine.apps.readerforselfossv2.android.R
|
import bou.amine.apps.readerforselfossv2.android.R
|
||||||
import bou.amine.apps.readerforselfossv2.android.databinding.CardItemBinding
|
import bou.amine.apps.readerforselfossv2.android.databinding.CardItemBinding
|
||||||
import bou.amine.apps.readerforselfossv2.android.model.toTextDrawableString
|
import bou.amine.apps.readerforselfossv2.android.model.toTextDrawableString
|
||||||
import bou.amine.apps.readerforselfossv2.android.utils.*
|
import bou.amine.apps.readerforselfossv2.android.utils.LinkOnTouchListener
|
||||||
import bou.amine.apps.readerforselfossv2.android.utils.glide.bitmapCenterCrop
|
import bou.amine.apps.readerforselfossv2.android.utils.glide.bitmapCenterCrop
|
||||||
import bou.amine.apps.readerforselfossv2.android.utils.glide.circularBitmapDrawable
|
import bou.amine.apps.readerforselfossv2.android.utils.glide.circularBitmapDrawable
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.utils.openInBrowserAsNewTask
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.utils.openItemUrl
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.utils.shareLink
|
||||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||||
import bou.amine.apps.readerforselfossv2.repository.Repository
|
import bou.amine.apps.readerforselfossv2.repository.Repository
|
||||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
@ -59,7 +62,7 @@ class ItemCardAdapter(
|
|||||||
|
|
||||||
binding.title.setLinkTextColor(c.resources.getColor(R.color.colorAccent))
|
binding.title.setLinkTextColor(c.resources.getColor(R.color.colorAccent))
|
||||||
|
|
||||||
binding.sourceTitleAndDate.text = itm.sourceAndDateText(repository.dateUtils)
|
binding.sourceTitleAndDate.text = itm.sourceAndDateText()
|
||||||
|
|
||||||
if (!appSettingsService.isFullHeightCardsEnabled()) {
|
if (!appSettingsService.isFullHeightCardsEnabled()) {
|
||||||
binding.itemImage.maxHeight = imageMaxHeight
|
binding.itemImage.maxHeight = imageMaxHeight
|
||||||
@ -108,13 +111,11 @@ class ItemCardAdapter(
|
|||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
repository.unstarr(item)
|
repository.unstarr(item)
|
||||||
}
|
}
|
||||||
item.starred = false
|
|
||||||
binding.favButton.isSelected = false
|
binding.favButton.isSelected = false
|
||||||
} else {
|
} else {
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
repository.starr(item)
|
repository.starr(item)
|
||||||
}
|
}
|
||||||
item.starred = true
|
|
||||||
binding.favButton.isSelected = true
|
binding.favButton.isSelected = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ class ItemListAdapter(
|
|||||||
|
|
||||||
binding.title.setLinkTextColor(c.resources.getColor(R.color.colorAccent))
|
binding.title.setLinkTextColor(c.resources.getColor(R.color.colorAccent))
|
||||||
|
|
||||||
binding.sourceTitleAndDate.text = itm.sourceAndDateText(repository.dateUtils)
|
binding.sourceTitleAndDate.text = itm.sourceAndDateText()
|
||||||
|
|
||||||
if (itm.getThumbnail(repository.baseUrl).isEmpty()) {
|
if (itm.getThumbnail(repository.baseUrl).isEmpty()) {
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte
|
|||||||
updateItems(this.items)
|
updateItems(this.items)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun unmarkSnackbar(position: Int) {
|
private fun unmarkSnackbar(item: SelfossModel.Item, position: Int) {
|
||||||
val s = Snackbar
|
val s = Snackbar
|
||||||
.make(
|
.make(
|
||||||
app.findViewById(R.id.coordLayout),
|
app.findViewById(R.id.coordLayout),
|
||||||
@ -37,7 +37,7 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte
|
|||||||
)
|
)
|
||||||
.setAction(R.string.undo_string) {
|
.setAction(R.string.undo_string) {
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
unreadItemAtIndex(position, false)
|
unreadItemAtIndex(item, position, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,7 +47,7 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte
|
|||||||
s.show()
|
s.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun markSnackbar(position: Int) {
|
private fun markSnackbar(item: SelfossModel.Item, position: Int) {
|
||||||
val s = Snackbar
|
val s = Snackbar
|
||||||
.make(
|
.make(
|
||||||
app.findViewById(R.id.coordLayout),
|
app.findViewById(R.id.coordLayout),
|
||||||
@ -55,7 +55,7 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte
|
|||||||
Snackbar.LENGTH_LONG
|
Snackbar.LENGTH_LONG
|
||||||
)
|
)
|
||||||
.setAction(R.string.undo_string) {
|
.setAction(R.string.undo_string) {
|
||||||
readItemAtIndex(position)
|
readItemAtIndex(item, position, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
val view = s.view
|
val view = s.view
|
||||||
@ -66,37 +66,36 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte
|
|||||||
|
|
||||||
fun handleItemAtIndex(position: Int) {
|
fun handleItemAtIndex(position: Int) {
|
||||||
if (items[position].unread) {
|
if (items[position].unread) {
|
||||||
readItemAtIndex(position)
|
readItemAtIndex(items[position], position)
|
||||||
} else {
|
} else {
|
||||||
unreadItemAtIndex(position)
|
unreadItemAtIndex(items[position], position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun readItemAtIndex(position: Int, showSnackbar: Boolean = true) {
|
private fun readItemAtIndex(item: SelfossModel.Item, position: Int, showSnackbar: Boolean = true) {
|
||||||
val i = items[position]
|
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
repository.markAsRead(i)
|
repository.markAsRead(item)
|
||||||
}
|
}
|
||||||
if (repository.displayedItems == ItemType.UNREAD) {
|
if (repository.displayedItems == ItemType.UNREAD) {
|
||||||
items.remove(i)
|
items.remove(item)
|
||||||
notifyItemRemoved(position)
|
notifyItemRemoved(position)
|
||||||
updateItems(items)
|
updateItems(items)
|
||||||
} else {
|
} else {
|
||||||
notifyItemChanged(position)
|
notifyItemChanged(position)
|
||||||
}
|
}
|
||||||
if (showSnackbar) {
|
if (showSnackbar) {
|
||||||
unmarkSnackbar(position)
|
unmarkSnackbar(item, position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun unreadItemAtIndex(position: Int, showSnackbar: Boolean = true) {
|
private fun unreadItemAtIndex(item: SelfossModel.Item, position: Int, showSnackbar: Boolean = true) {
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
repository.unmarkAsRead(items[position])
|
repository.unmarkAsRead(item)
|
||||||
|
|
||||||
}
|
}
|
||||||
notifyItemChanged(position)
|
notifyItemChanged(position)
|
||||||
if (showSnackbar) {
|
if (showSnackbar) {
|
||||||
markSnackbar(position)
|
markSnackbar(item, position)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,9 +61,13 @@ class SourcesListAdapter(
|
|||||||
binding.sourceTitle.text = itm.title.getHtmlDecoded()
|
binding.sourceTitle.text = itm.title.getHtmlDecoded()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getItemId(position: Int) = position.toLong()
|
||||||
|
|
||||||
|
override fun getItemViewType(position: Int) = position
|
||||||
|
|
||||||
override fun getItemCount(): Int = items.size
|
override fun getItemCount(): Int = items.size
|
||||||
|
|
||||||
inner class ViewHolder(internal val mView: ConstraintLayout) : RecyclerView.ViewHolder(mView) {
|
inner class ViewHolder(private val mView: ConstraintLayout) : RecyclerView.ViewHolder(mView) {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
handleClickListeners()
|
handleClickListeners()
|
||||||
@ -74,13 +78,13 @@ class SourcesListAdapter(
|
|||||||
val deleteBtn: Button = mView.findViewById(R.id.deleteBtn)
|
val deleteBtn: Button = mView.findViewById(R.id.deleteBtn)
|
||||||
|
|
||||||
deleteBtn.setOnClickListener {
|
deleteBtn.setOnClickListener {
|
||||||
val (id) = items[adapterPosition]
|
val (id) = items[bindingAdapterPosition]
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
val successfullyDeletedSource = repository.deleteSource(id)
|
val successfullyDeletedSource = repository.deleteSource(id)
|
||||||
if (successfullyDeletedSource) {
|
if (successfullyDeletedSource) {
|
||||||
items.removeAt(adapterPosition)
|
items.removeAt(bindingAdapterPosition)
|
||||||
notifyItemRemoved(adapterPosition)
|
notifyItemRemoved(bindingAdapterPosition)
|
||||||
notifyItemRangeChanged(adapterPosition, itemCount)
|
notifyItemRangeChanged(bindingAdapterPosition, itemCount)
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
app,
|
app,
|
||||||
|
@ -52,11 +52,13 @@ override fun doWork(): Result {
|
|||||||
|
|
||||||
repository.handleDBActions()
|
repository.handleDBActions()
|
||||||
|
|
||||||
|
val apiItems = repository.tryToCacheItemsAndGetNewOnes()
|
||||||
if (appSettingsService.isNotifyNewItemsEnabled()) {
|
if (appSettingsService.isNotifyNewItemsEnabled()) {
|
||||||
launch {
|
launch {
|
||||||
handleNewItemsNotification(repository.tryToCacheItemsAndGetNewOnes(), notificationManager)
|
handleNewItemsNotification(apiItems, notificationManager)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
apiItems.map { it.preloadImages(context) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Result.success()
|
return Result.success()
|
||||||
@ -66,6 +68,7 @@ override fun doWork(): Result {
|
|||||||
newItems: List<SelfossModel.Item>?,
|
newItems: List<SelfossModel.Item>?,
|
||||||
notificationManager: NotificationManager
|
notificationManager: NotificationManager
|
||||||
) {
|
) {
|
||||||
|
// TODO: Check if this coroutine is actually required
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
val apiItems = newItems.orEmpty()
|
val apiItems = newItems.orEmpty()
|
||||||
|
|
||||||
@ -102,7 +105,6 @@ override fun doWork(): Result {
|
|||||||
notificationManager.notify(2, newItemsNotification.build())
|
notificationManager.notify(2, newItemsNotification.build())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
apiItems.map { it.preloadImages(context) }
|
|
||||||
Timer("", false).schedule(4000) {
|
Timer("", false).schedule(4000) {
|
||||||
notificationManager.cancel(1)
|
notificationManager.cancel(1)
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,7 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
contentText = item.content
|
contentText = item.content
|
||||||
contentTitle = item.title.getHtmlDecoded()
|
contentTitle = item.title.getHtmlDecoded()
|
||||||
contentImage = item.getThumbnail(repository.baseUrl)
|
contentImage = item.getThumbnail(repository.baseUrl)
|
||||||
contentSource = item.sourceAndDateText(repository.dateUtils)
|
contentSource = item.sourceAndDateText()
|
||||||
allImages = item.getImages()
|
allImages = item.getImages()
|
||||||
|
|
||||||
fontSize = appSettingsService.getFontSize()
|
fontSize = appSettingsService.getFontSize()
|
||||||
@ -354,6 +354,7 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
binding.webcontent.settings.javaScriptEnabled = false
|
binding.webcontent.settings.javaScriptEnabled = false
|
||||||
|
|
||||||
binding.webcontent.webViewClient = object : WebViewClient() {
|
binding.webcontent.webViewClient = object : WebViewClient() {
|
||||||
|
@Deprecated("Deprecated in Java")
|
||||||
override fun shouldOverrideUrlLoading(view: WebView?, url : String): Boolean {
|
override fun shouldOverrideUrlLoading(view: WebView?, url : String): Boolean {
|
||||||
if (binding.webcontent.hitTestResult.type != WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
|
if (binding.webcontent.hitTestResult.type != WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE) {
|
||||||
requireContext().startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
|
requireContext().startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
|
||||||
@ -361,6 +362,7 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated("Deprecated in Java")
|
||||||
override fun shouldInterceptRequest(view: WebView?, url: String): WebResourceResponse? {
|
override fun shouldInterceptRequest(view: WebView?, url: String): WebResourceResponse? {
|
||||||
val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL)
|
val glideOptions = RequestOptions.diskCacheStrategyOf(DiskCacheStrategy.ALL)
|
||||||
if (url.lowercase(Locale.US).contains(".jpg") || url.lowercase(Locale.US).contains(".jpeg")) {
|
if (url.lowercase(Locale.US).contains(".jpg") || url.lowercase(Locale.US).contains(".jpeg")) {
|
||||||
@ -387,7 +389,7 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val gestureDetector = GestureDetector(activity, object : GestureDetector.SimpleOnGestureListener() {
|
val gestureDetector = GestureDetector(activity, object : GestureDetector.SimpleOnGestureListener() {
|
||||||
override fun onSingleTapUp(e: MotionEvent?): Boolean {
|
override fun onSingleTapUp(e: MotionEvent): Boolean {
|
||||||
return performClick()
|
return performClick()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -132,4 +132,5 @@
|
|||||||
<string name="mode_dark">Dark mode</string>
|
<string name="mode_dark">Dark mode</string>
|
||||||
<string name="mode_system">Follow the system setting</string>
|
<string name="mode_system">Follow the system setting</string>
|
||||||
<string name="mode_light">Light mode</string>
|
<string name="mode_light">Light mode</string>
|
||||||
|
<string name="drawer_error_loading_sources">Error loading sources…</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -132,4 +132,5 @@
|
|||||||
<string name="mode_dark">Dark mode</string>
|
<string name="mode_dark">Dark mode</string>
|
||||||
<string name="mode_system">Follow the system setting</string>
|
<string name="mode_system">Follow the system setting</string>
|
||||||
<string name="mode_light">Light mode</string>
|
<string name="mode_light">Light mode</string>
|
||||||
|
<string name="drawer_error_loading_sources">Error loading sources…</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -132,4 +132,5 @@
|
|||||||
<string name="mode_dark">Dark mode</string>
|
<string name="mode_dark">Dark mode</string>
|
||||||
<string name="mode_system">Follow the system setting</string>
|
<string name="mode_system">Follow the system setting</string>
|
||||||
<string name="mode_light">Light mode</string>
|
<string name="mode_light">Light mode</string>
|
||||||
|
<string name="drawer_error_loading_sources">Error loading sources…</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -132,4 +132,5 @@
|
|||||||
<string name="mode_dark">Dark mode</string>
|
<string name="mode_dark">Dark mode</string>
|
||||||
<string name="mode_system">Follow the system setting</string>
|
<string name="mode_system">Follow the system setting</string>
|
||||||
<string name="mode_light">Light mode</string>
|
<string name="mode_light">Light mode</string>
|
||||||
|
<string name="drawer_error_loading_sources">Error loading sources…</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -132,4 +132,5 @@
|
|||||||
<string name="mode_dark">Thème sombre</string>
|
<string name="mode_dark">Thème sombre</string>
|
||||||
<string name="mode_system">Utiliser les paramètres système</string>
|
<string name="mode_system">Utiliser les paramètres système</string>
|
||||||
<string name="mode_light">Thème clair</string>
|
<string name="mode_light">Thème clair</string>
|
||||||
|
<string name="drawer_error_loading_sources">Error loading sources…</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -132,4 +132,5 @@
|
|||||||
<string name="mode_dark">Dark mode</string>
|
<string name="mode_dark">Dark mode</string>
|
||||||
<string name="mode_system">Follow the system setting</string>
|
<string name="mode_system">Follow the system setting</string>
|
||||||
<string name="mode_light">Light mode</string>
|
<string name="mode_light">Light mode</string>
|
||||||
|
<string name="drawer_error_loading_sources">Error loading sources…</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -132,4 +132,5 @@
|
|||||||
<string name="mode_dark">Dark mode</string>
|
<string name="mode_dark">Dark mode</string>
|
||||||
<string name="mode_system">Follow the system setting</string>
|
<string name="mode_system">Follow the system setting</string>
|
||||||
<string name="mode_light">Light mode</string>
|
<string name="mode_light">Light mode</string>
|
||||||
|
<string name="drawer_error_loading_sources">Error loading sources…</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -132,4 +132,5 @@
|
|||||||
<string name="mode_dark">Dark mode</string>
|
<string name="mode_dark">Dark mode</string>
|
||||||
<string name="mode_system">Follow the system setting</string>
|
<string name="mode_system">Follow the system setting</string>
|
||||||
<string name="mode_light">Light mode</string>
|
<string name="mode_light">Light mode</string>
|
||||||
|
<string name="drawer_error_loading_sources">Error loading sources…</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -132,4 +132,5 @@
|
|||||||
<string name="mode_dark">Dark mode</string>
|
<string name="mode_dark">Dark mode</string>
|
||||||
<string name="mode_system">Follow the system setting</string>
|
<string name="mode_system">Follow the system setting</string>
|
||||||
<string name="mode_light">Light mode</string>
|
<string name="mode_light">Light mode</string>
|
||||||
|
<string name="drawer_error_loading_sources">Error loading sources…</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -132,4 +132,5 @@
|
|||||||
<string name="mode_dark">Dark mode</string>
|
<string name="mode_dark">Dark mode</string>
|
||||||
<string name="mode_system">Follow the system setting</string>
|
<string name="mode_system">Follow the system setting</string>
|
||||||
<string name="mode_light">Light mode</string>
|
<string name="mode_light">Light mode</string>
|
||||||
|
<string name="drawer_error_loading_sources">Error loading sources…</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -132,4 +132,5 @@
|
|||||||
<string name="mode_dark">Dark mode</string>
|
<string name="mode_dark">Dark mode</string>
|
||||||
<string name="mode_system">Follow the system setting</string>
|
<string name="mode_system">Follow the system setting</string>
|
||||||
<string name="mode_light">Light mode</string>
|
<string name="mode_light">Light mode</string>
|
||||||
|
<string name="drawer_error_loading_sources">Error loading sources…</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -132,4 +132,5 @@
|
|||||||
<string name="mode_dark">Dark mode</string>
|
<string name="mode_dark">Dark mode</string>
|
||||||
<string name="mode_system">Follow the system setting</string>
|
<string name="mode_system">Follow the system setting</string>
|
||||||
<string name="mode_light">Light mode</string>
|
<string name="mode_light">Light mode</string>
|
||||||
|
<string name="drawer_error_loading_sources">Error loading sources…</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -132,4 +132,5 @@
|
|||||||
<string name="mode_dark">Dark mode</string>
|
<string name="mode_dark">Dark mode</string>
|
||||||
<string name="mode_system">Follow the system setting</string>
|
<string name="mode_system">Follow the system setting</string>
|
||||||
<string name="mode_light">Light mode</string>
|
<string name="mode_light">Light mode</string>
|
||||||
|
<string name="drawer_error_loading_sources">Error loading sources…</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -132,4 +132,5 @@
|
|||||||
<string name="mode_dark">Dark mode</string>
|
<string name="mode_dark">Dark mode</string>
|
||||||
<string name="mode_system">Follow the system setting</string>
|
<string name="mode_system">Follow the system setting</string>
|
||||||
<string name="mode_light">Light mode</string>
|
<string name="mode_light">Light mode</string>
|
||||||
|
<string name="drawer_error_loading_sources">Error loading sources…</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -132,4 +132,5 @@
|
|||||||
<string name="mode_dark">深色模式</string>
|
<string name="mode_dark">深色模式</string>
|
||||||
<string name="mode_system">遵循系统设置</string>
|
<string name="mode_system">遵循系统设置</string>
|
||||||
<string name="mode_light">浅色模式</string>
|
<string name="mode_light">浅色模式</string>
|
||||||
|
<string name="drawer_error_loading_sources">Error loading sources…</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -132,4 +132,5 @@
|
|||||||
<string name="mode_dark">Dark mode</string>
|
<string name="mode_dark">Dark mode</string>
|
||||||
<string name="mode_system">Follow the system setting</string>
|
<string name="mode_system">Follow the system setting</string>
|
||||||
<string name="mode_light">Light mode</string>
|
<string name="mode_light">Light mode</string>
|
||||||
|
<string name="drawer_error_loading_sources">Error loading sources…</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -63,6 +63,7 @@
|
|||||||
<string name="card_height_off">Card height will be fixed</string>
|
<string name="card_height_off">Card height will be fixed</string>
|
||||||
<string name="source_code">Source code</string>
|
<string name="source_code">Source code</string>
|
||||||
<string name="drawer_error_loading_tags">Error loading tags…</string>
|
<string name="drawer_error_loading_tags">Error loading tags…</string>
|
||||||
|
<string name="drawer_error_loading_sources">Error loading sources…</string>
|
||||||
<string name="drawer_item_filters">Filters</string>
|
<string name="drawer_item_filters">Filters</string>
|
||||||
<string name="drawer_action_clear">clear</string>
|
<string name="drawer_action_clear">clear</string>
|
||||||
<string name="drawer_item_tags">Tags</string>
|
<string name="drawer_item_tags">Tags</string>
|
||||||
@ -109,7 +110,7 @@
|
|||||||
<string name="pref_switch_periodic_refresh_on">Articles will periodically be synced</string>
|
<string name="pref_switch_periodic_refresh_on">Articles will periodically be synced</string>
|
||||||
<string name="pref_periodic_refresh_minutes_title"><![CDATA[Sync interval ( >= 15 minutes)]]></string>
|
<string name="pref_periodic_refresh_minutes_title"><![CDATA[Sync interval ( >= 15 minutes)]]></string>
|
||||||
<string name="pref_switch_refresh_when_charging">Only refresh when phone is charging</string>
|
<string name="pref_switch_refresh_when_charging">Only refresh when phone is charging</string>
|
||||||
<string name="loading_notification_title">Loading ...</string>
|
<string name="loading_notification_title">Loading …</string>
|
||||||
<string name="loading_notification_text">Selfoss is syncing your articles</string>
|
<string name="loading_notification_text">Selfoss is syncing your articles</string>
|
||||||
<string name="notification_channel_sync">Sync notification</string>
|
<string name="notification_channel_sync">Sync notification</string>
|
||||||
<string name="new_items_channel_sync">New items notification</string>
|
<string name="new_items_channel_sync">New items notification</string>
|
||||||
|
33
androidApp/src/test/kotlin/DatesTest.kt
Normal file
33
androidApp/src/test/kotlin/DatesTest.kt
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package bou.amine.apps.readerforselfossv2.repository
|
||||||
|
|
||||||
|
import bou.amine.apps.readerforselfossv2.utils.DateUtils
|
||||||
|
import junit.framework.TestCase.assertEquals
|
||||||
|
import kotlinx.datetime.LocalDateTime
|
||||||
|
import kotlinx.datetime.TimeZone
|
||||||
|
import kotlinx.datetime.toInstant
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class DatesTest {
|
||||||
|
|
||||||
|
private val v3Date = "2013-04-07T13:43:00+01:00"
|
||||||
|
private val v4Date = "2013-04-07 13:43:00"
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun v3_date_should_be_parsed() {
|
||||||
|
val date = DateUtils.parseDate(v3Date)
|
||||||
|
val expected = LocalDateTime(2013, 4, 7, 13, 43, 0, 0).toInstant(TimeZone.of("UTC+1")) .toEpochMilliseconds()
|
||||||
|
|
||||||
|
assertEquals(date, expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun v4_date_should_be_parsed() {
|
||||||
|
val date = DateUtils.parseDate(v4Date)
|
||||||
|
val expected =
|
||||||
|
LocalDateTime(2013, 4, 7, 13, 43, 0, 0).toInstant(TimeZone.currentSystemDefault())
|
||||||
|
.toEpochMilliseconds()
|
||||||
|
|
||||||
|
assertEquals(date, expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
1368
androidApp/src/test/kotlin/RepositoryTest.kt
Normal file
1368
androidApp/src/test/kotlin/RepositoryTest.kt
Normal file
File diff suppressed because it is too large
Load Diff
57
androidApp/src/test/kotlin/TestUtils.kt
Normal file
57
androidApp/src/test/kotlin/TestUtils.kt
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
package bou.amine.apps.readerforselfossv2.repository
|
||||||
|
|
||||||
|
import bou.amine.apps.readerforselfossv2.dao.ITEM
|
||||||
|
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||||
|
|
||||||
|
|
||||||
|
fun generateTestDBItems(item: FakeItemParameters = FakeItemParameters()): List<ITEM> {
|
||||||
|
return listOf(
|
||||||
|
ITEM(
|
||||||
|
id = item.id,
|
||||||
|
datetime = item.datetime,
|
||||||
|
title = item.title,
|
||||||
|
content = item.content,
|
||||||
|
unread = item.unread,
|
||||||
|
starred = item.starred,
|
||||||
|
thumbnail = item.thumbnail,
|
||||||
|
icon = item.icon,
|
||||||
|
link = item.link,
|
||||||
|
sourcetitle = item.sourcetitle,
|
||||||
|
tags = item.tags
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun generateTestApiItem(item: FakeItemParameters = FakeItemParameters()): List<SelfossModel.Item> {
|
||||||
|
return listOf(
|
||||||
|
SelfossModel.Item(
|
||||||
|
id = item.id.toInt(),
|
||||||
|
datetime = item.datetime,
|
||||||
|
title = item.title,
|
||||||
|
content = item.content,
|
||||||
|
unread = item.unread,
|
||||||
|
starred = item.starred,
|
||||||
|
thumbnail = item.thumbnail,
|
||||||
|
icon = item.icon,
|
||||||
|
link = item.link,
|
||||||
|
sourcetitle = item.sourcetitle,
|
||||||
|
tags = item.tags.split(',')
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
class FakeItemParameters {
|
||||||
|
var id = "20"
|
||||||
|
var datetime = "2022-09-09T03:32:01-04:00"
|
||||||
|
val title = "Etica della ricerca sotto i riflettori."
|
||||||
|
val content =
|
||||||
|
"<p><strong>Luigi Campanella, già Presidente SCI</strong></p>\n<p>L’etica della scienza è di certo ambito di cui continuiamo a scoprire nuovi aspetti e risvolti.</p>\n<p>L’ultimo è quello delle intelligenze artificiali capaci di creare opere complesse basate su immagini e parole memorizzate con il rischio di fake news e di contenuti disturbanti.</p>\n<p>Per evitare che ciò accada si sta procedendo filtrando secondo criteri di autocensura i dati da cui l’intelligenza artificiale parte.</p>\n<p>Comincia ad intravedersi un futuro prossimo di competizione fra autori umani ed artificiali nel quale sarà importante, quando i loro prodotti saranno indistinguibili, dichiararne l’origine.</p>\n<p>Come si comprende, si conferma che gli aspetti etici dell’innovazione e della ricerca si diversificato sempre di più.</p>\n<p>La biologia molecolare e la genetica già in passato hanno posto all’attenzione comune aspetti di etica della scienza che hanno indotto a nuove riflessioni circa i limiti delle ricerche.</p>\n<p>L’argomento, sempre attuale, torna sulle prime pagine a seguito della pubblicazione di una ricerca della Università di Cambridge che ha sviluppato una struttura cellulare di un topo con un cuore che batte regolarmente.</p>\n<img src=\"https://ilblogdellasci.files.wordpress.com/2022/09/image002-1.png?w=481\" alt=\"\" width=\"697\" height=\"430\" /><img src=\"https://ilblogdellasci.files.wordpress.com/2022/09/image003-1.png?w=906\" alt=\"\" /><p>Magdalena Zernicka-Goetz</p>\n<img src=\"https://ilblogdellasci.files.wordpress.com/2022/09/image004.jpg?w=474\" alt=\"\" width=\"622\" height=\"465\" /><p>Gianluca Amadei</p>\n<p>Del gruppo fa parte anche uno scienziato italiano Gianluca Amadei,che dinnanzi alle obiezioni di natura etica sulla realizzazione della vita artificiale si è affrettato a sostenere che non è creare nuove vite il fine primario della ricerca, ma quello di salvare quelle esistenti, di dare contributi essenziali alla medicina citando il caso del fallimento tuttora non interpretato di alcune gravidanze e di superare la sperimentazione animale, così contribuendo positivamente alla soluzione di un altro dilemma etico.</p>\n<p>L’embrione sintetico ha ovviamente come primo traguardo il contributo ai trapianti oggi drammaticamente carenti nell’offerta rispetto alla domanda, con attese fino a 4 anni per i trapianti di cuore ed a 2 anni per quelli di fegato. Il lavoro dovrebbe adesso continuare presso l’Ateneo di Padova per creare nuovi organi e nuovi farmaci.</p>"
|
||||||
|
var unread = true
|
||||||
|
var starred = true
|
||||||
|
val thumbnail = null
|
||||||
|
val icon = "ba79e238383ce83c23a169929c8906ef.png"
|
||||||
|
val link =
|
||||||
|
"https://ilblogdellasci.wordpress.com/2022/09/09/etica-della-ricerca-sotto-i-riflettori/"
|
||||||
|
var sourcetitle = "La Chimica e la Società"
|
||||||
|
var tags = "Chimica, Testing"
|
||||||
|
}
|
@ -1,21 +1,20 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
|
||||||
gradlePluginPortal()
|
|
||||||
google()
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10")
|
|
||||||
classpath("com.android.tools.build:gradle:7.3.0")
|
|
||||||
|
|
||||||
// sonarquve
|
|
||||||
classpath("org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:3.4.0.2513")
|
|
||||||
|
|
||||||
// SqlDelight
|
// SqlDelight
|
||||||
classpath("com.squareup.sqldelight:gradle-plugin:1.5.3")
|
classpath("com.squareup.sqldelight:gradle-plugin:1.5.4")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
//trick: for the same plugin versions in all sub-modules
|
||||||
|
id("com.android.application").version("7.3.1").apply(false)
|
||||||
|
id("com.android.library").version("7.3.1").apply(false)
|
||||||
|
kotlin("android").version("1.7.20").apply(false)
|
||||||
|
kotlin("multiplatform").version("1.7.20").apply(false)
|
||||||
|
id("org.sonarqube").version("3.4.0.2513").apply(false)
|
||||||
|
id("com.mikepenz.aboutlibraries.plugin").version("10.5.1").apply(false)
|
||||||
|
}
|
||||||
|
|
||||||
apply(plugin = "org.sonarqube")
|
apply(plugin = "org.sonarqube")
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
@ -27,6 +26,7 @@ allprojects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tasks.register("clean", Delete::class) {
|
tasks.register("clean", Delete::class) {
|
||||||
delete(rootProject.buildDir)
|
delete(rootProject.buildDir)
|
||||||
}
|
}
|
||||||
|
@ -11,14 +11,26 @@
|
|||||||
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
|
||||||
# org.gradle.parallel=true
|
# org.gradle.parallel=true
|
||||||
#Tue Mar 22 16:50:00 CET 2022
|
#Tue Mar 22 16:50:00 CET 2022
|
||||||
|
#Gradle
|
||||||
|
org.gradle.jvmargs=-Xmx2048M -Dfile.encoding=UTF-8 -Dkotlin.daemon.jvm.options\="-Xmx2048M"
|
||||||
|
|
||||||
|
#Kotlin
|
||||||
kotlin.code.style=official
|
kotlin.code.style=official
|
||||||
kotlin.mpp.enableCInteropCommonization=true
|
|
||||||
org.gradle.jvmargs=-Xmx2048M -Dkotlin.daemon.jvm.options\="-Xmx2048M"
|
#Android
|
||||||
kotlin.native.enableDependencyPropagation=false
|
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
|
kotlin.native.enableDependencyPropagation=false
|
||||||
|
#android.nonTransitiveRClass=true
|
||||||
android.enableJetifier=true
|
android.enableJetifier=true
|
||||||
|
|
||||||
|
|
||||||
|
#MPP
|
||||||
|
kotlin.mpp.enableCInteropCommonization=true
|
||||||
kotlin.mpp.enableGranularSourceSetsMetadata=true
|
kotlin.mpp.enableGranularSourceSetsMetadata=true
|
||||||
|
|
||||||
|
|
||||||
org.gradle.parallel=true
|
org.gradle.parallel=true
|
||||||
org.gradle.caching=true
|
org.gradle.caching=true
|
||||||
ignoreGitVersion=false
|
ignoreGitVersion=false
|
||||||
|
kotlin.native.cacheKind.iosX64=none
|
||||||
pushCache=true
|
pushCache=true
|
||||||
|
@ -1,383 +1,383 @@
|
|||||||
// !$*UTF8*$!
|
// !$*UTF8*$!
|
||||||
{
|
{
|
||||||
archiveVersion = 1;
|
archiveVersion = 1;
|
||||||
classes = {
|
classes = {
|
||||||
};
|
};
|
||||||
objectVersion = 50;
|
objectVersion = 50;
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
058557BB273AAA24004C7B11 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 058557BA273AAA24004C7B11 /* Assets.xcassets */; };
|
058557BB273AAA24004C7B11 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 058557BA273AAA24004C7B11 /* Assets.xcassets */; };
|
||||||
058557D9273AAEEB004C7B11 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */; };
|
058557D9273AAEEB004C7B11 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */; };
|
||||||
2152FB042600AC8F00CF470E /* iOSApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2152FB032600AC8F00CF470E /* iOSApp.swift */; };
|
2152FB042600AC8F00CF470E /* iOSApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2152FB032600AC8F00CF470E /* iOSApp.swift */; };
|
||||||
7555FF83242A565900829871 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7555FF82242A565900829871 /* ContentView.swift */; };
|
7555FF83242A565900829871 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7555FF82242A565900829871 /* ContentView.swift */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
7555FFB4242A642300829871 /* Embed Frameworks */ = {
|
7555FFB4242A642300829871 /* Embed Frameworks */ = {
|
||||||
isa = PBXCopyFilesBuildPhase;
|
isa = PBXCopyFilesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
dstPath = "";
|
dstPath = "";
|
||||||
dstSubfolderSpec = 10;
|
dstSubfolderSpec = 10;
|
||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
name = "Embed Frameworks";
|
name = "Embed Frameworks";
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
058557BA273AAA24004C7B11 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
058557BA273AAA24004C7B11 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
|
058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
|
||||||
2152FB032600AC8F00CF470E /* iOSApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSApp.swift; sourceTree = "<group>"; };
|
2152FB032600AC8F00CF470E /* iOSApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = iOSApp.swift; sourceTree = "<group>"; };
|
||||||
7555FF7B242A565900829871 /* iosApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iosApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
7555FF7B242A565900829871 /* iosApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iosApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
7555FF82242A565900829871 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
7555FF82242A565900829871 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
|
||||||
7555FF8C242A565B00829871 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
7555FF8C242A565B00829871 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
7555FF78242A565900829871 /* Frameworks */ = {
|
7555FF78242A565900829871 /* Frameworks */ = {
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
058557D7273AAEEB004C7B11 /* Preview Content */ = {
|
058557D7273AAEEB004C7B11 /* Preview Content */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */,
|
058557D8273AAEEB004C7B11 /* Preview Assets.xcassets */,
|
||||||
);
|
);
|
||||||
path = "Preview Content";
|
path = "Preview Content";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
7555FF72242A565900829871 = {
|
7555FF72242A565900829871 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
7555FF7D242A565900829871 /* iosApp */,
|
7555FF7D242A565900829871 /* iosApp */,
|
||||||
7555FF7C242A565900829871 /* Products */,
|
7555FF7C242A565900829871 /* Products */,
|
||||||
7555FFB0242A642200829871 /* Frameworks */,
|
7555FFB0242A642200829871 /* Frameworks */,
|
||||||
);
|
);
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
7555FF7C242A565900829871 /* Products */ = {
|
7555FF7C242A565900829871 /* Products */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
7555FF7B242A565900829871 /* iosApp.app */,
|
7555FF7B242A565900829871 /* iosApp.app */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
7555FF7D242A565900829871 /* iosApp */ = {
|
7555FF7D242A565900829871 /* iosApp */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
058557BA273AAA24004C7B11 /* Assets.xcassets */,
|
058557BA273AAA24004C7B11 /* Assets.xcassets */,
|
||||||
7555FF82242A565900829871 /* ContentView.swift */,
|
7555FF82242A565900829871 /* ContentView.swift */,
|
||||||
7555FF8C242A565B00829871 /* Info.plist */,
|
7555FF8C242A565B00829871 /* Info.plist */,
|
||||||
2152FB032600AC8F00CF470E /* iOSApp.swift */,
|
2152FB032600AC8F00CF470E /* iOSApp.swift */,
|
||||||
058557D7273AAEEB004C7B11 /* Preview Content */,
|
058557D7273AAEEB004C7B11 /* Preview Content */,
|
||||||
);
|
);
|
||||||
path = iosApp;
|
path = iosApp;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
7555FFB0242A642200829871 /* Frameworks */ = {
|
7555FFB0242A642200829871 /* Frameworks */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget section */
|
/* Begin PBXNativeTarget section */
|
||||||
7555FF7A242A565900829871 /* iosApp */ = {
|
7555FF7A242A565900829871 /* iosApp */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 7555FFA5242A565B00829871 /* Build configuration list for PBXNativeTarget "iosApp" */;
|
buildConfigurationList = 7555FFA5242A565B00829871 /* Build configuration list for PBXNativeTarget "iosApp" */;
|
||||||
buildPhases = (
|
buildPhases = (
|
||||||
7555FFB5242A651A00829871 /* ShellScript */,
|
7555FFB5242A651A00829871 /* ShellScript */,
|
||||||
7555FF77242A565900829871 /* Sources */,
|
7555FF77242A565900829871 /* Sources */,
|
||||||
7555FF78242A565900829871 /* Frameworks */,
|
7555FF78242A565900829871 /* Frameworks */,
|
||||||
7555FF79242A565900829871 /* Resources */,
|
7555FF79242A565900829871 /* Resources */,
|
||||||
7555FFB4242A642300829871 /* Embed Frameworks */,
|
7555FFB4242A642300829871 /* Embed Frameworks */,
|
||||||
);
|
);
|
||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
);
|
);
|
||||||
name = iosApp;
|
name = iosApp;
|
||||||
productName = iosApp;
|
productName = iosApp;
|
||||||
productReference = 7555FF7B242A565900829871 /* iosApp.app */;
|
productReference = 7555FF7B242A565900829871 /* iosApp.app */;
|
||||||
productType = "com.apple.product-type.application";
|
productType = "com.apple.product-type.application";
|
||||||
};
|
};
|
||||||
/* End PBXNativeTarget section */
|
/* End PBXNativeTarget section */
|
||||||
|
|
||||||
/* Begin PBXProject section */
|
/* Begin PBXProject section */
|
||||||
7555FF73242A565900829871 /* Project object */ = {
|
7555FF73242A565900829871 /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastSwiftUpdateCheck = 1130;
|
LastSwiftUpdateCheck = 1130;
|
||||||
LastUpgradeCheck = 1130;
|
LastUpgradeCheck = 1130;
|
||||||
ORGANIZATIONNAME = orgName;
|
ORGANIZATIONNAME = orgName;
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
7555FF7A242A565900829871 = {
|
7555FF7A242A565900829871 = {
|
||||||
CreatedOnToolsVersion = 11.3.1;
|
CreatedOnToolsVersion = 11.3.1;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
buildConfigurationList = 7555FF76242A565900829871 /* Build configuration list for PBXProject "iosApp" */;
|
buildConfigurationList = 7555FF76242A565900829871 /* Build configuration list for PBXProject "iosApp" */;
|
||||||
compatibilityVersion = "Xcode 9.3";
|
compatibilityVersion = "Xcode 9.3";
|
||||||
developmentRegion = en;
|
developmentRegion = en;
|
||||||
hasScannedForEncodings = 0;
|
hasScannedForEncodings = 0;
|
||||||
knownRegions = (
|
knownRegions = (
|
||||||
en,
|
en,
|
||||||
Base,
|
Base,
|
||||||
);
|
);
|
||||||
mainGroup = 7555FF72242A565900829871;
|
mainGroup = 7555FF72242A565900829871;
|
||||||
productRefGroup = 7555FF7C242A565900829871 /* Products */;
|
productRefGroup = 7555FF7C242A565900829871 /* Products */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
targets = (
|
targets = (
|
||||||
7555FF7A242A565900829871 /* iosApp */,
|
7555FF7A242A565900829871 /* iosApp */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
|
|
||||||
/* Begin PBXResourcesBuildPhase section */
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
7555FF79242A565900829871 /* Resources */ = {
|
7555FF79242A565900829871 /* Resources */ = {
|
||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
058557D9273AAEEB004C7B11 /* Preview Assets.xcassets in Resources */,
|
058557D9273AAEEB004C7B11 /* Preview Assets.xcassets in Resources */,
|
||||||
058557BB273AAA24004C7B11 /* Assets.xcassets in Resources */,
|
058557BB273AAA24004C7B11 /* Assets.xcassets in Resources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXShellScriptBuildPhase section */
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
7555FFB5242A651A00829871 /* ShellScript */ = {
|
7555FFB5242A651A00829871 /* ShellScript */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
);
|
);
|
||||||
inputPaths = (
|
inputPaths = (
|
||||||
);
|
);
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
);
|
);
|
||||||
outputPaths = (
|
outputPaths = (
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "cd \"$SRCROOT/..\"\n./gradlew :shared:embedAndSignAppleFrameworkForXcode\n";
|
shellScript = "cd \"$SRCROOT/..\"\n./gradlew :shared:embedAndSignAppleFrameworkForXcode\n";
|
||||||
};
|
};
|
||||||
/* End PBXShellScriptBuildPhase section */
|
/* End PBXShellScriptBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
7555FF77242A565900829871 /* Sources */ = {
|
7555FF77242A565900829871 /* Sources */ = {
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
2152FB042600AC8F00CF470E /* iOSApp.swift in Sources */,
|
2152FB042600AC8F00CF470E /* iOSApp.swift in Sources */,
|
||||||
7555FF83242A565900829871 /* ContentView.swift in Sources */,
|
7555FF83242A565900829871 /* ContentView.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin XCBuildConfiguration section */
|
/* Begin XCBuildConfiguration section */
|
||||||
7555FFA3242A565B00829871 /* Debug */ = {
|
7555FFA3242A565B00829871 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
CLANG_WARN_COMMA = YES;
|
CLANG_WARN_COMMA = YES;
|
||||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
CLANG_WARN_EMPTY_BODY = YES;
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
ENABLE_TESTABILITY = YES;
|
ENABLE_TESTABILITY = YES;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
GCC_DYNAMIC_NO_PIC = NO;
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
GCC_NO_COMMON_BLOCKS = YES;
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
GCC_OPTIMIZATION_LEVEL = 0;
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
"DEBUG=1",
|
"DEBUG=1",
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
);
|
);
|
||||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
|
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
|
||||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
7555FFA4242A565B00829871 /* Release */ = {
|
7555FFA4242A565B00829871 /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||||
CLANG_ANALYZER_NONNULL = YES;
|
CLANG_ANALYZER_NONNULL = YES;
|
||||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
|
||||||
CLANG_CXX_LIBRARY = "libc++";
|
CLANG_CXX_LIBRARY = "libc++";
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CLANG_ENABLE_OBJC_ARC = YES;
|
CLANG_ENABLE_OBJC_ARC = YES;
|
||||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
|
||||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||||
CLANG_WARN_COMMA = YES;
|
CLANG_WARN_COMMA = YES;
|
||||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||||
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
|
||||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
CLANG_WARN_EMPTY_BODY = YES;
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
|
||||||
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
|
||||||
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
CLANG_WARN_STRICT_PROTOTYPES = YES;
|
||||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||||
GCC_NO_COMMON_BLOCKS = YES;
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
|
IPHONEOS_DEPLOYMENT_TARGET = 14.1;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
MTL_FAST_MATH = YES;
|
MTL_FAST_MATH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SWIFT_COMPILATION_MODE = wholemodule;
|
SWIFT_COMPILATION_MODE = wholemodule;
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
SWIFT_OPTIMIZATION_LEVEL = "-O";
|
||||||
VALIDATE_PRODUCT = YES;
|
VALIDATE_PRODUCT = YES;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
7555FFA6242A565B00829871 /* Debug */ = {
|
7555FFA6242A565B00829871 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\"";
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/../shared/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)";
|
FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/../shared/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)";
|
||||||
INFOPLIST_FILE = iosApp/Info.plist;
|
INFOPLIST_FILE = iosApp/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"-framework",
|
"-framework",
|
||||||
shared,
|
shared,
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = orgIdentifier.iosApp;
|
PRODUCT_BUNDLE_IDENTIFIER = orgIdentifier.iosApp;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
};
|
};
|
||||||
7555FFA7242A565B00829871 /* Release */ = {
|
7555FFA7242A565B00829871 /* Release */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"iosApp/Preview Content\"";
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/../shared/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)";
|
FRAMEWORK_SEARCH_PATHS = "$(SRCROOT)/../shared/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME)";
|
||||||
INFOPLIST_FILE = iosApp/Info.plist;
|
INFOPLIST_FILE = iosApp/Info.plist;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
);
|
);
|
||||||
OTHER_LDFLAGS = (
|
OTHER_LDFLAGS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"-framework",
|
"-framework",
|
||||||
shared,
|
shared,
|
||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = orgIdentifier.iosApp;
|
PRODUCT_BUNDLE_IDENTIFIER = orgIdentifier.iosApp;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
};
|
};
|
||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList section */
|
/* Begin XCConfigurationList section */
|
||||||
7555FF76242A565900829871 /* Build configuration list for PBXProject "iosApp" */ = {
|
7555FF76242A565900829871 /* Build configuration list for PBXProject "iosApp" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
7555FFA3242A565B00829871 /* Debug */,
|
7555FFA3242A565B00829871 /* Debug */,
|
||||||
7555FFA4242A565B00829871 /* Release */,
|
7555FFA4242A565B00829871 /* Release */,
|
||||||
);
|
);
|
||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
7555FFA5242A565B00829871 /* Build configuration list for PBXNativeTarget "iosApp" */ = {
|
7555FFA5242A565B00829871 /* Build configuration list for PBXNativeTarget "iosApp" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
7555FFA6242A565B00829871 /* Debug */,
|
7555FFA6242A565B00829871 /* Debug */,
|
||||||
7555FFA7242A565B00829871 /* Release */,
|
7555FFA7242A565B00829871 /* Release */,
|
||||||
);
|
);
|
||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
/* End XCConfigurationList section */
|
/* End XCConfigurationList section */
|
||||||
};
|
};
|
||||||
rootObject = 7555FF73242A565900829871 /* Project object */;
|
rootObject = 7555FF73242A565900829871 /* Project object */;
|
||||||
}
|
}
|
||||||
|
@ -2,12 +2,9 @@ import SwiftUI
|
|||||||
import shared
|
import shared
|
||||||
|
|
||||||
struct ContentView: View {
|
struct ContentView: View {
|
||||||
let greet = Greeting().greeting()
|
|
||||||
|
|
||||||
let toto = SelfossApi().getItems()
|
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Text(greet)
|
Text("ototot")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,14 @@ pluginManagement {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dependencyResolutionManagement {
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
buildCache {
|
buildCache {
|
||||||
remote<HttpBuildCache> {
|
remote<HttpBuildCache> {
|
||||||
url = uri("http://18.0.0.7:3071/cache/")
|
url = uri("http://18.0.0.7:3071/cache/")
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
object SqlDelight {
|
object SqlDelight {
|
||||||
const val runtime = "com.squareup.sqldelight:runtime:1.5.3"
|
const val runtime = "com.squareup.sqldelight:runtime:1.5.4"
|
||||||
const val android = "com.squareup.sqldelight:android-driver:1.5.3"
|
const val android = "com.squareup.sqldelight:android-driver:1.5.4"
|
||||||
const val native = "com.squareup.sqldelight:native-driver:1.5.3"
|
const val native = "com.squareup.sqldelight:native-driver:1.5.4"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -18,7 +18,7 @@ kotlin {
|
|||||||
listOf(
|
listOf(
|
||||||
iosX64(),
|
iosX64(),
|
||||||
iosArm64(),
|
iosArm64(),
|
||||||
//iosSimulatorArm64() sure all ios dependencies support this target
|
// iosSimulatorArm64()
|
||||||
).forEach {
|
).forEach {
|
||||||
it.binaries.framework {
|
it.binaries.framework {
|
||||||
baseName = "shared"
|
baseName = "shared"
|
||||||
@ -40,14 +40,11 @@ kotlin {
|
|||||||
implementation("org.kodein.di:kodein-di:7.12.0")
|
implementation("org.kodein.di:kodein-di:7.12.0")
|
||||||
|
|
||||||
//Settings
|
//Settings
|
||||||
implementation("com.russhwolf:multiplatform-settings-no-arg:0.9")
|
implementation("com.russhwolf:multiplatform-settings-no-arg:1.0.0-RC")
|
||||||
|
|
||||||
//Logging
|
//Logging
|
||||||
implementation("io.github.aakira:napier:2.6.1")
|
implementation("io.github.aakira:napier:2.6.1")
|
||||||
|
|
||||||
// Network information
|
|
||||||
implementation("com.github.ln-12:multiplatform-connectivity-status:1.3.0")
|
|
||||||
|
|
||||||
// Sql
|
// Sql
|
||||||
implementation(SqlDelight.runtime)
|
implementation(SqlDelight.runtime)
|
||||||
}
|
}
|
||||||
@ -61,6 +58,7 @@ kotlin {
|
|||||||
val androidMain by getting {
|
val androidMain by getting {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("io.ktor:ktor-client-okhttp:2.1.1")
|
implementation("io.ktor:ktor-client-okhttp:2.1.1")
|
||||||
|
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.4.0")
|
||||||
|
|
||||||
// Sql
|
// Sql
|
||||||
implementation(SqlDelight.android)
|
implementation(SqlDelight.android)
|
||||||
@ -74,39 +72,36 @@ kotlin {
|
|||||||
}
|
}
|
||||||
val iosX64Main by getting
|
val iosX64Main by getting
|
||||||
val iosArm64Main by getting
|
val iosArm64Main by getting
|
||||||
//val iosSimulatorArm64Main by getting
|
// val iosSimulatorArm64Main by getting
|
||||||
val iosMain by creating {
|
val iosMain by creating {
|
||||||
dependsOn(commonMain)
|
dependsOn(commonMain)
|
||||||
iosX64Main.dependsOn(this)
|
iosX64Main.dependsOn(this)
|
||||||
iosArm64Main.dependsOn(this)
|
iosArm64Main.dependsOn(this)
|
||||||
//iosSimulatorArm64Main.dependsOn(this)
|
// iosSimulatorArm64Main.dependsOn(this)
|
||||||
|
|
||||||
// Sql
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(SqlDelight.native)
|
implementation(SqlDelight.native)
|
||||||
|
implementation("io.ktor:ktor-client-ios:2.1.1")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val iosX64Test by getting
|
val iosX64Test by getting
|
||||||
val iosArm64Test by getting
|
val iosArm64Test by getting
|
||||||
//val iosSimulatorArm64Test by getting
|
// val iosSimulatorArm64Test by getting
|
||||||
val iosTest by creating {
|
val iosTest by creating {
|
||||||
dependsOn(commonTest)
|
dependsOn(commonTest)
|
||||||
iosX64Test.dependsOn(this)
|
iosX64Test.dependsOn(this)
|
||||||
iosArm64Test.dependsOn(this)
|
iosArm64Test.dependsOn(this)
|
||||||
dependencies {
|
// iosSimulatorArm64Test.dependsOn(this)
|
||||||
implementation("io.ktor:ktor-client-ios:2.1.1")
|
|
||||||
}
|
|
||||||
//iosSimulatorArm64Test.dependsOn(this)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdk = 31
|
compileSdk = 32
|
||||||
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
|
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk = 21
|
minSdk = 21
|
||||||
targetSdk = 31
|
targetSdk = 32
|
||||||
}
|
}
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
@ -115,10 +110,11 @@ android {
|
|||||||
namespace = "bou.amine.apps.readerforselfossv2"
|
namespace = "bou.amine.apps.readerforselfossv2"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
sqldelight {
|
sqldelight {
|
||||||
database("ReaderForSelfossDB") {
|
database("ReaderForSelfossDB") {
|
||||||
packageName = "bou.amine.apps.readerforselfossv2.dao"
|
packageName = "bou.amine.apps.readerforselfossv2.dao"
|
||||||
sourceFolders = listOf("sqldelight")
|
sourceFolders = listOf("sqldelight")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,36 +1,29 @@
|
|||||||
package bou.amine.apps.readerforselfossv2.utils
|
package bou.amine.apps.readerforselfossv2.utils
|
||||||
|
|
||||||
import android.text.format.DateUtils
|
import android.text.format.DateUtils
|
||||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
import kotlinx.datetime.*
|
||||||
import java.time.Instant
|
|
||||||
import java.time.LocalDateTime
|
|
||||||
import java.time.OffsetDateTime
|
|
||||||
import java.time.ZoneOffset
|
|
||||||
import java.time.format.DateTimeFormatter
|
|
||||||
|
|
||||||
actual class DateUtils actual constructor(actual val appSettingsService: AppSettingsService) {
|
|
||||||
|
|
||||||
actual fun parseDate(dateString: String): Long {
|
actual class DateUtils {
|
||||||
|
actual companion object {
|
||||||
|
actual fun parseDate(dateString: String): Long {
|
||||||
|
return try {
|
||||||
|
Instant.parse(dateString).toEpochMilliseconds()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
LocalDateTime.parse(dateString.replace(" ", "T")).toInstant(TimeZone.currentSystemDefault()).toEpochMilliseconds()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val FORMATTERV1 = "yyyy-MM-dd HH:mm:ss"
|
actual fun parseRelativeDate(dateString: String): String {
|
||||||
|
|
||||||
return if (appSettingsService.getApiVersion() >= 4) {
|
val date = parseDate(dateString)
|
||||||
OffsetDateTime.parse(dateString).toInstant().toEpochMilli()
|
|
||||||
} else {
|
return " " + DateUtils.getRelativeTimeSpanString(
|
||||||
LocalDateTime.parse(dateString, DateTimeFormatter.ofPattern(FORMATTERV1)).toInstant(
|
date,
|
||||||
ZoneOffset.UTC).toEpochMilli()
|
Clock.System.now().toEpochMilliseconds(),
|
||||||
|
DateUtils.MINUTE_IN_MILLIS,
|
||||||
|
DateUtils.FORMAT_ABBREV_RELATIVE
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun parseRelativeDate(dateString: String): String {
|
|
||||||
|
|
||||||
val date = parseDate(dateString)
|
|
||||||
|
|
||||||
return " " + DateUtils.getRelativeTimeSpanString(
|
|
||||||
date,
|
|
||||||
Instant.now().toEpochMilli(),
|
|
||||||
DateUtils.MINUTE_IN_MILLIS,
|
|
||||||
DateUtils.FORMAT_ABBREV_RELATIVE
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -108,8 +108,8 @@ class SelfossModel {
|
|||||||
return stringUrl
|
return stringUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sourceAndDateText(dateUtils: DateUtils): String =
|
fun sourceAndDateText(): String =
|
||||||
this.sourcetitle.getHtmlDecoded() + dateUtils.parseRelativeDate(this.datetime)
|
this.sourcetitle.getHtmlDecoded() + DateUtils.parseRelativeDate(this.datetime)
|
||||||
|
|
||||||
fun toggleStar(): Item {
|
fun toggleStar(): Item {
|
||||||
this.starred = !this.starred
|
this.starred = !this.starred
|
||||||
@ -138,7 +138,11 @@ class SelfossModel {
|
|||||||
object BooleanSerializer : KSerializer<Boolean> {
|
object BooleanSerializer : KSerializer<Boolean> {
|
||||||
override fun deserialize(decoder: Decoder): Boolean {
|
override fun deserialize(decoder: Decoder): Boolean {
|
||||||
val json = ((decoder as JsonDecoder).decodeJsonElement()).jsonPrimitive
|
val json = ((decoder as JsonDecoder).decodeJsonElement()).jsonPrimitive
|
||||||
return json.booleanOrNull ?: json.int == 1
|
return if (json.booleanOrNull != null) {
|
||||||
|
json.boolean
|
||||||
|
} else {
|
||||||
|
json.int == 1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override val descriptor: SerialDescriptor
|
override val descriptor: SerialDescriptor
|
||||||
|
@ -6,20 +6,19 @@ import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
|||||||
import bou.amine.apps.readerforselfossv2.rest.SelfossApi
|
import bou.amine.apps.readerforselfossv2.rest.SelfossApi
|
||||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
import bou.amine.apps.readerforselfossv2.utils.*
|
import bou.amine.apps.readerforselfossv2.utils.*
|
||||||
import com.github.ln_12.library.ConnectivityStatus
|
|
||||||
import io.github.aakira.napier.Napier
|
import io.github.aakira.napier.Napier
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class Repository(private val api: SelfossApi, private val appSettingsService: AppSettingsService, connectivityStatus: ConnectivityStatus, private val db: ReaderForSelfossDB) {
|
class Repository(private val api: SelfossApi, private val appSettingsService: AppSettingsService, val isConnectionAvailable: MutableStateFlow<Boolean>, private val db: ReaderForSelfossDB) {
|
||||||
|
|
||||||
var items = ArrayList<SelfossModel.Item>()
|
var items = ArrayList<SelfossModel.Item>()
|
||||||
val isConnectionAvailable = connectivityStatus.isNetworkConnected
|
|
||||||
var connectionMonitored = false
|
var connectionMonitored = false
|
||||||
|
|
||||||
var baseUrl = appSettingsService.getBaseUrl()
|
var baseUrl = appSettingsService.getBaseUrl()
|
||||||
lateinit var dateUtils: DateUtils
|
|
||||||
|
|
||||||
var displayedItems = ItemType.UNREAD
|
var displayedItems = ItemType.UNREAD
|
||||||
|
|
||||||
@ -29,21 +28,15 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
|
|
||||||
var offlineOverride = false
|
var offlineOverride = false
|
||||||
|
|
||||||
var badgeUnread = 0
|
private val _badgeUnread = MutableStateFlow(0)
|
||||||
set(value) {field = if (value < 0) { 0 } else { value } }
|
val badgeUnread = _badgeUnread.asStateFlow()
|
||||||
var badgeAll = 0
|
private val _badgeAll = MutableStateFlow(0)
|
||||||
set(value) {field = if (value < 0) { 0 } else { value } }
|
val badgeAll = _badgeAll.asStateFlow()
|
||||||
var badgeStarred = 0
|
private val _badgeStarred = MutableStateFlow(0)
|
||||||
set(value) {field = if (value < 0) { 0 } else { value } }
|
val badgeStarred = _badgeStarred.asStateFlow()
|
||||||
|
|
||||||
init {
|
private var fetchedSources = false
|
||||||
// TODO: Dispatchers.IO not available in KMM, an alternative solution should be found
|
private var fetchedTags = false
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
|
||||||
updateApiVersion()
|
|
||||||
dateUtils = DateUtils(appSettingsService)
|
|
||||||
reloadBadges()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun getNewerItems(): ArrayList<SelfossModel.Item> {
|
suspend fun getNewerItems(): ArrayList<SelfossModel.Item> {
|
||||||
// TODO: Use the updatedSince parameter
|
// TODO: Use the updatedSince parameter
|
||||||
@ -61,12 +54,19 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
} else {
|
} else {
|
||||||
if (appSettingsService.isItemCachingEnabled()) {
|
if (appSettingsService.isItemCachingEnabled()) {
|
||||||
fromDB = true
|
fromDB = true
|
||||||
|
var dbItems = getDBItems().filter {
|
||||||
|
displayedItems == ItemType.ALL ||
|
||||||
|
(it.unread && displayedItems == ItemType.UNREAD) ||
|
||||||
|
(it.starred && displayedItems == ItemType.STARRED)
|
||||||
|
}
|
||||||
|
if (tagFilter != null) {
|
||||||
|
dbItems = dbItems.filter { it.tags.split(',').contains(tagFilter!!.tag) }
|
||||||
|
}
|
||||||
|
if (sourceFilter != null) {
|
||||||
|
dbItems = dbItems.filter { it.sourcetitle == sourceFilter!!.title }
|
||||||
|
}
|
||||||
fetchedItems = SelfossModel.StatusAndData.succes(
|
fetchedItems = SelfossModel.StatusAndData.succes(
|
||||||
getDBItems().filter {
|
dbItems.map { it.toView() }
|
||||||
displayedItems == ItemType.ALL ||
|
|
||||||
(it.unread && displayedItems == ItemType.UNREAD) ||
|
|
||||||
(it.starred && displayedItems == ItemType.STARRED)
|
|
||||||
}.map { it.toView() }
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,7 +74,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
if (fetchedItems.success && fetchedItems.data != null) {
|
if (fetchedItems.success && fetchedItems.data != null) {
|
||||||
items = ArrayList(fetchedItems.data!!)
|
items = ArrayList(fetchedItems.data!!)
|
||||||
if (fromDB) {
|
if (fromDB) {
|
||||||
items.sortByDescending { dateUtils.parseDate(it.datetime) }
|
items.sortByDescending { DateUtils.parseDate(it.datetime) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return items
|
return items
|
||||||
@ -105,9 +105,9 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
val items = api.getItems(
|
val items = api.getItems(
|
||||||
itemType.type,
|
itemType.type,
|
||||||
0,
|
0,
|
||||||
tagFilter?.tag,
|
null,
|
||||||
sourceFilter?.id?.toLong(),
|
null,
|
||||||
searchFilter,
|
null,
|
||||||
null,
|
null,
|
||||||
200
|
200
|
||||||
)
|
)
|
||||||
@ -126,37 +126,45 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
if (isNetworkAvailable()) {
|
if (isNetworkAvailable()) {
|
||||||
val response = api.stats()
|
val response = api.stats()
|
||||||
if (response.success && response.data != null) {
|
if (response.success && response.data != null) {
|
||||||
badgeUnread = response.data.unread
|
_badgeUnread.value = response.data.unread
|
||||||
badgeAll = response.data.total
|
_badgeAll.value = response.data.total
|
||||||
badgeStarred = response.data.starred
|
_badgeStarred.value = response.data.starred
|
||||||
success = true
|
success = true
|
||||||
}
|
}
|
||||||
} else {
|
} else if (appSettingsService.isItemCachingEnabled()) {
|
||||||
// TODO: do this differently, because it's not efficient
|
// TODO: do this differently, because it's not efficient
|
||||||
val dbItems = getDBItems()
|
val dbItems = getDBItems()
|
||||||
badgeUnread = dbItems.filter { item -> item.unread }.size
|
_badgeUnread.value = dbItems.filter { item -> item.unread }.size
|
||||||
badgeStarred = dbItems.filter { item -> item.starred }.size
|
_badgeStarred.value = dbItems.filter { item -> item.starred }.size
|
||||||
badgeAll = items.size
|
_badgeAll.value = dbItems.size
|
||||||
|
success = true
|
||||||
}
|
}
|
||||||
return success
|
return success
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getTags(): List<SelfossModel.Tag>? {
|
suspend fun getTags(): List<SelfossModel.Tag> {
|
||||||
return if (isNetworkAvailable()) {
|
val isDatabaseEnabled = appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled()
|
||||||
|
return if (isNetworkAvailable() && !fetchedTags) {
|
||||||
val apiTags = api.tags()
|
val apiTags = api.tags()
|
||||||
if (apiTags.success && apiTags.data != null && (appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled())) {
|
if (apiTags.success && apiTags.data != null && isDatabaseEnabled) {
|
||||||
resetDBTagsWithData(apiTags.data)
|
resetDBTagsWithData(apiTags.data)
|
||||||
|
if (!appSettingsService.isUpdateSourcesEnabled()) {
|
||||||
|
fetchedTags = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
apiTags.data
|
apiTags.data ?: emptyList()
|
||||||
} else {
|
} else if (isDatabaseEnabled) {
|
||||||
getDBTags().map { it.toView() }
|
getDBTags().map { it.toView() }
|
||||||
|
} else {
|
||||||
|
emptyList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getSpouts(): Map<String, SelfossModel.Spout>? {
|
// TODO: Add tests
|
||||||
|
suspend fun getSpouts(): Map<String, SelfossModel.Spout> {
|
||||||
return if (isNetworkAvailable()) {
|
return if (isNetworkAvailable()) {
|
||||||
val spouts = api.spouts()
|
val spouts = api.spouts()
|
||||||
return if (spouts.success && spouts.data != null) {
|
if (spouts.success && spouts.data != null) {
|
||||||
spouts.data
|
spouts.data
|
||||||
} else {
|
} else {
|
||||||
emptyMap() // TODO: do something here
|
emptyMap() // TODO: do something here
|
||||||
@ -166,18 +174,25 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getSources(): ArrayList<SelfossModel.Source>? {
|
suspend fun getSources(): ArrayList<SelfossModel.Source> {
|
||||||
return if (isNetworkAvailable()) {
|
val isDatabaseEnabled = appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled()
|
||||||
|
return if (isNetworkAvailable() && !fetchedSources) {
|
||||||
val apiSources = api.sources()
|
val apiSources = api.sources()
|
||||||
if (apiSources.success && apiSources.data != null && (appSettingsService.isItemCachingEnabled() || !appSettingsService.isUpdateSourcesEnabled())) {
|
if (apiSources.success && apiSources.data != null && isDatabaseEnabled) {
|
||||||
resetDBSourcesWithData(apiSources.data)
|
resetDBSourcesWithData(apiSources.data)
|
||||||
|
if (!appSettingsService.isUpdateSourcesEnabled()) {
|
||||||
|
fetchedSources = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
apiSources.data
|
apiSources.data ?: ArrayList()
|
||||||
} else {
|
} else if (isDatabaseEnabled) {
|
||||||
ArrayList(getDBSources().map { it.toView() })
|
ArrayList(getDBSources().map { it.toView() })
|
||||||
|
} else {
|
||||||
|
ArrayList()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Add tests
|
||||||
suspend fun markAsRead(item: SelfossModel.Item): Boolean {
|
suspend fun markAsRead(item: SelfossModel.Item): Boolean {
|
||||||
val success = markAsReadById(item.id)
|
val success = markAsReadById(item.id)
|
||||||
|
|
||||||
@ -189,14 +204,14 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
|
|
||||||
private suspend fun markAsReadById(id: Int): Boolean {
|
private suspend fun markAsReadById(id: Int): Boolean {
|
||||||
return if (isNetworkAvailable()) {
|
return if (isNetworkAvailable()) {
|
||||||
api.markAsRead(id.toString())?.isSuccess
|
api.markAsRead(id.toString()).isSuccess
|
||||||
} else {
|
} else {
|
||||||
insertDBAction(id.toString(), read = true)
|
insertDBAction(id.toString(), read = true)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Add tests
|
||||||
suspend fun unmarkAsRead(item: SelfossModel.Item): Boolean {
|
suspend fun unmarkAsRead(item: SelfossModel.Item): Boolean {
|
||||||
val success = unmarkAsReadById(item.id)
|
val success = unmarkAsReadById(item.id)
|
||||||
|
|
||||||
@ -208,13 +223,14 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
|
|
||||||
private suspend fun unmarkAsReadById(id: Int): Boolean {
|
private suspend fun unmarkAsReadById(id: Int): Boolean {
|
||||||
return if (isNetworkAvailable()) {
|
return if (isNetworkAvailable()) {
|
||||||
api.unmarkAsRead(id.toString())?.isSuccess
|
api.unmarkAsRead(id.toString()).isSuccess
|
||||||
} else {
|
} else {
|
||||||
insertDBAction(id.toString(), unread = true)
|
insertDBAction(id.toString(), unread = true)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Add tests
|
||||||
suspend fun starr(item: SelfossModel.Item): Boolean {
|
suspend fun starr(item: SelfossModel.Item): Boolean {
|
||||||
val success = starrById(item.id)
|
val success = starrById(item.id)
|
||||||
|
|
||||||
@ -226,13 +242,14 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
|
|
||||||
private suspend fun starrById(id: Int): Boolean {
|
private suspend fun starrById(id: Int): Boolean {
|
||||||
return if (isNetworkAvailable()) {
|
return if (isNetworkAvailable()) {
|
||||||
api.starr(id.toString())?.isSuccess
|
api.starr(id.toString()).isSuccess
|
||||||
} else {
|
} else {
|
||||||
insertDBAction(id.toString(), starred = true)
|
insertDBAction(id.toString(), starred = true)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Add tests
|
||||||
suspend fun unstarr(item: SelfossModel.Item): Boolean {
|
suspend fun unstarr(item: SelfossModel.Item): Boolean {
|
||||||
val success = unstarrById(item.id)
|
val success = unstarrById(item.id)
|
||||||
|
|
||||||
@ -244,17 +261,18 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
|
|
||||||
private suspend fun unstarrById(id: Int): Boolean {
|
private suspend fun unstarrById(id: Int): Boolean {
|
||||||
return if (isNetworkAvailable()) {
|
return if (isNetworkAvailable()) {
|
||||||
api.unstarr(id.toString())?.isSuccess
|
api.unstarr(id.toString()).isSuccess
|
||||||
} else {
|
} else {
|
||||||
insertDBAction(id.toString(), starred = true)
|
insertDBAction(id.toString(), starred = true)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Add tests
|
||||||
suspend fun markAllAsRead(items: ArrayList<SelfossModel.Item>): Boolean {
|
suspend fun markAllAsRead(items: ArrayList<SelfossModel.Item>): Boolean {
|
||||||
var success = false
|
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
|
success = true
|
||||||
for (item in items) {
|
for (item in items) {
|
||||||
markAsReadLocally(item)
|
markAsReadLocally(item)
|
||||||
@ -266,7 +284,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
private fun markAsReadLocally(item: SelfossModel.Item) {
|
private fun markAsReadLocally(item: SelfossModel.Item) {
|
||||||
if (item.unread) {
|
if (item.unread) {
|
||||||
item.unread = false
|
item.unread = false
|
||||||
badgeUnread -= 1
|
_badgeUnread.value -= 1
|
||||||
}
|
}
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
@ -277,7 +295,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
private fun unmarkAsReadLocally(item: SelfossModel.Item) {
|
private fun unmarkAsReadLocally(item: SelfossModel.Item) {
|
||||||
if (!item.unread) {
|
if (!item.unread) {
|
||||||
item.unread = true
|
item.unread = true
|
||||||
badgeUnread += 1
|
_badgeUnread.value += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
@ -288,7 +306,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
private fun starrLocally(item: SelfossModel.Item) {
|
private fun starrLocally(item: SelfossModel.Item) {
|
||||||
if (!item.starred) {
|
if (!item.starred) {
|
||||||
item.starred = true
|
item.starred = true
|
||||||
badgeStarred += 1
|
_badgeStarred.value += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
@ -299,7 +317,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
private fun unstarrLocally(item: SelfossModel.Item) {
|
private fun unstarrLocally(item: SelfossModel.Item) {
|
||||||
if (item.starred) {
|
if (item.starred) {
|
||||||
item.starred = false
|
item.starred = false
|
||||||
badgeStarred -= 1
|
_badgeStarred.value -= 1
|
||||||
}
|
}
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
@ -323,7 +341,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
tags,
|
tags,
|
||||||
filter,
|
filter,
|
||||||
appSettingsService.getApiVersion()
|
appSettingsService.getApiVersion()
|
||||||
)?.isSuccess == true
|
).isSuccess == true
|
||||||
}
|
}
|
||||||
|
|
||||||
return response
|
return response
|
||||||
@ -333,9 +351,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
var success = false
|
var success = false
|
||||||
if (isNetworkAvailable()) {
|
if (isNetworkAvailable()) {
|
||||||
val response = api.deleteSource(id)
|
val response = api.deleteSource(id)
|
||||||
if (response != null) {
|
success = response.isSuccess
|
||||||
success = response.isSuccess
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return success
|
return success
|
||||||
@ -343,7 +359,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
|
|
||||||
suspend fun updateRemote(): Boolean {
|
suspend fun updateRemote(): Boolean {
|
||||||
return if (isNetworkAvailable()) {
|
return if (isNetworkAvailable()) {
|
||||||
api.update()?.equals("finished")
|
api.update().data.equals("finished")
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@ -354,10 +370,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
if (isNetworkAvailable()) {
|
if (isNetworkAvailable()) {
|
||||||
try {
|
try {
|
||||||
val response = api.login()
|
val response = api.login()
|
||||||
result = response?.isSuccess == true
|
result = response.isSuccess == true
|
||||||
if (result) {
|
|
||||||
updateApiVersion()
|
|
||||||
}
|
|
||||||
} catch (cause: Throwable) {
|
} catch (cause: Throwable) {
|
||||||
Napier.e(cause.stackTraceToString(), tag = "RepositoryImpl.updateRemote")
|
Napier.e(cause.stackTraceToString(), tag = "RepositoryImpl.updateRemote")
|
||||||
}
|
}
|
||||||
@ -390,9 +403,9 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
private fun deleteDBAction(action: ACTION) =
|
private fun deleteDBAction(action: ACTION) =
|
||||||
db.actionsQueries.deleteAction(action.id)
|
db.actionsQueries.deleteAction(action.id)
|
||||||
|
|
||||||
fun getDBTags(): List<TAG> = db.tagsQueries.tags().executeAsList()
|
private fun getDBTags(): List<TAG> = db.tagsQueries.tags().executeAsList()
|
||||||
|
|
||||||
fun getDBSources(): List<SOURCE> = db.sourcesQueries.sources().executeAsList()
|
private fun getDBSources(): List<SOURCE> = db.sourcesQueries.sources().executeAsList()
|
||||||
|
|
||||||
private fun resetDBTagsWithData(tagEntities: List<SelfossModel.Tag>) {
|
private fun resetDBTagsWithData(tagEntities: List<SelfossModel.Tag>) {
|
||||||
db.tagsQueries.deleteAllTags()
|
db.tagsQueries.deleteAllTags()
|
||||||
@ -430,8 +443,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
private fun updateDBItem(item: SelfossModel.Item) =
|
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())
|
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 {
|
try {
|
||||||
val newItems = getMaxItemsForBackground(ItemType.UNREAD)
|
val newItems = getMaxItemsForBackground(ItemType.UNREAD)
|
||||||
val allItems = getMaxItemsForBackground(ItemType.ALL)
|
val allItems = getMaxItemsForBackground(ItemType.ALL)
|
||||||
@ -444,6 +456,7 @@ class Repository(private val api: SelfossApi, private val appSettingsService: Ap
|
|||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Add tests
|
||||||
suspend fun handleDBActions() {
|
suspend fun handleDBActions() {
|
||||||
|
|
||||||
val actions: List<ACTION> = getDBActions()
|
val actions: List<ACTION> = getDBActions()
|
||||||
|
@ -54,8 +54,8 @@ class AppSettingsService {
|
|||||||
return _apiVersion
|
return _apiVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
fun refreshApiVersion() {
|
private fun refreshApiVersion() {
|
||||||
_apiVersion = settings.getInt("apiVersionMajor", -1)
|
_apiVersion = settings.getInt(API_VERSION_MAJOR, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getBaseUrl(): String {
|
fun getBaseUrl(): String {
|
||||||
@ -86,8 +86,8 @@ class AppSettingsService {
|
|||||||
return _itemsNumber!!
|
return _itemsNumber!!
|
||||||
}
|
}
|
||||||
|
|
||||||
fun refreshItemsNumber() {
|
private fun refreshItemsNumber() {
|
||||||
_itemsNumber = settings.getString("prefer_api_items_number", "20").toInt()
|
_itemsNumber = settings.getString(API_ITEMS_NUMBER, "20").toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getApiTimeout(): Long {
|
fun getApiTimeout(): Long {
|
||||||
@ -98,24 +98,24 @@ class AppSettingsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshApiTimeout() {
|
private fun refreshApiTimeout() {
|
||||||
val settingsTimeout = settings.getLong("api_timeout", HttpTimeout.INFINITE_TIMEOUT_MS)
|
val settingsTimeout = settings.getLong(API_TIMEOUT, HttpTimeout.INFINITE_TIMEOUT_MS)
|
||||||
_apiTimeout = if (settingsTimeout > 0) settingsTimeout else HttpTimeout.INFINITE_TIMEOUT_MS
|
_apiTimeout = if (settingsTimeout > 0) settingsTimeout else HttpTimeout.INFINITE_TIMEOUT_MS
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshBaseUrl() {
|
private fun refreshBaseUrl() {
|
||||||
_baseUrl = settings.getString("url", "")
|
_baseUrl = settings.getString(BASE_URL, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshUsername() {
|
private fun refreshUsername() {
|
||||||
_userName = settings.getString("login", "")
|
_userName = settings.getString(LOGIN, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshPassword() {
|
private fun refreshPassword() {
|
||||||
_password = settings.getString("password", "")
|
_password = settings.getString(PASSWORD, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshArticleViewerEnabled() {
|
private fun refreshArticleViewerEnabled() {
|
||||||
_articleViewer = settings.getBoolean("prefer_article_viewer", true)
|
_articleViewer = settings.getBoolean(PREFER_ARTICLE_VIEWER, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isArticleViewerEnabled(): Boolean {
|
fun isArticleViewerEnabled(): Boolean {
|
||||||
@ -125,7 +125,7 @@ class AppSettingsService {
|
|||||||
return _articleViewer == true
|
return _articleViewer == true
|
||||||
}
|
}
|
||||||
private fun refreshShouldBeCardViewEnabled() {
|
private fun refreshShouldBeCardViewEnabled() {
|
||||||
_shouldBeCardView = settings.getBoolean("card_view_active", false)
|
_shouldBeCardView = settings.getBoolean(CARD_VIEW_ACTIVE, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isCardViewEnabled(): Boolean {
|
fun isCardViewEnabled(): Boolean {
|
||||||
@ -135,7 +135,7 @@ class AppSettingsService {
|
|||||||
return _shouldBeCardView == true
|
return _shouldBeCardView == true
|
||||||
}
|
}
|
||||||
private fun refreshDisplayUnreadCountEnabled() {
|
private fun refreshDisplayUnreadCountEnabled() {
|
||||||
_displayUnreadCount = settings.getBoolean("display_unread_count", true)
|
_displayUnreadCount = settings.getBoolean(DISPLAY_UNREAD_COUNT, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isDisplayUnreadCountEnabled(): Boolean {
|
fun isDisplayUnreadCountEnabled(): Boolean {
|
||||||
@ -145,7 +145,7 @@ class AppSettingsService {
|
|||||||
return _displayUnreadCount == true
|
return _displayUnreadCount == true
|
||||||
}
|
}
|
||||||
private fun refreshDisplayAllCountEnabled() {
|
private fun refreshDisplayAllCountEnabled() {
|
||||||
_displayAllCount = settings.getBoolean("display_other_count", false)
|
_displayAllCount = settings.getBoolean(DISPLAY_OTHER_COUNT, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isDisplayAllCountEnabled(): Boolean {
|
fun isDisplayAllCountEnabled(): Boolean {
|
||||||
@ -155,7 +155,7 @@ class AppSettingsService {
|
|||||||
return _displayAllCount == true
|
return _displayAllCount == true
|
||||||
}
|
}
|
||||||
private fun refreshFullHeightCardsEnabled() {
|
private fun refreshFullHeightCardsEnabled() {
|
||||||
_fullHeightCards = settings.getBoolean("full_height_cards", false)
|
_fullHeightCards = settings.getBoolean(FULL_HEIGHT_CARDS, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isFullHeightCardsEnabled(): Boolean {
|
fun isFullHeightCardsEnabled(): Boolean {
|
||||||
@ -165,7 +165,7 @@ class AppSettingsService {
|
|||||||
return _fullHeightCards == true
|
return _fullHeightCards == true
|
||||||
}
|
}
|
||||||
private fun refreshUpdateSourcesEnabled() {
|
private fun refreshUpdateSourcesEnabled() {
|
||||||
_updateSources = settings.getBoolean("update_sources", true)
|
_updateSources = settings.getBoolean(UPDATE_SOURCES, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isUpdateSourcesEnabled(): Boolean {
|
fun isUpdateSourcesEnabled(): Boolean {
|
||||||
@ -175,7 +175,7 @@ class AppSettingsService {
|
|||||||
return _updateSources == true
|
return _updateSources == true
|
||||||
}
|
}
|
||||||
private fun refreshPeriodicRefreshEnabled() {
|
private fun refreshPeriodicRefreshEnabled() {
|
||||||
_periodicRefresh = settings.getBoolean("periodic_refresh", false)
|
_periodicRefresh = settings.getBoolean(PERIODIC_REFRESH, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isPeriodicRefreshEnabled(): Boolean {
|
fun isPeriodicRefreshEnabled(): Boolean {
|
||||||
@ -186,7 +186,7 @@ class AppSettingsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshRefreshWhenChargingOnlyEnabled() {
|
private fun refreshRefreshWhenChargingOnlyEnabled() {
|
||||||
_refreshWhenChargingOnly = settings.getBoolean("refresh_when_charging", false)
|
_refreshWhenChargingOnly = settings.getBoolean(REFRESH_WHEN_CHARGING, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isRefreshWhenChargingOnlyEnabled(): Boolean {
|
fun isRefreshWhenChargingOnlyEnabled(): Boolean {
|
||||||
@ -197,22 +197,22 @@ class AppSettingsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshRefreshMinutes() {
|
private fun refreshRefreshMinutes() {
|
||||||
_refreshMinutes = settings.getString("periodic_refresh_minutes", "360").toLong()
|
_refreshMinutes = settings.getString(PERIODIC_REFRESH_MINUTES, "360").toLong()
|
||||||
if (_refreshMinutes <= 15) {
|
if (_refreshMinutes <= 15) {
|
||||||
_refreshMinutes = 15
|
_refreshMinutes = 15
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getRefreshMinutes(): Long {
|
fun getRefreshMinutes(): Long {
|
||||||
if (_refreshMinutes != null) {
|
if (_refreshMinutes != 360L) {
|
||||||
refreshRefreshMinutes()
|
refreshRefreshMinutes()
|
||||||
}
|
}
|
||||||
return _refreshMinutes
|
return _refreshMinutes
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshHiddenTags() {
|
private fun refreshHiddenTags() {
|
||||||
if (settings.getString("hidden_tags", "").isNotEmpty()) {
|
if (settings.getString(HIDDEN_TAGS, "").isNotEmpty()) {
|
||||||
_hiddenTags = settings.getString("hidden_tags", "").replace("\\s".toRegex(), "").split(",")
|
_hiddenTags = settings.getString(HIDDEN_TAGS, "").replace("\\s".toRegex(), "").split(",")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,7 +224,7 @@ class AppSettingsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshInfiniteLoadingEnabled() {
|
private fun refreshInfiniteLoadingEnabled() {
|
||||||
_infiniteLoading = settings.getBoolean("infinite_loading", false)
|
_infiniteLoading = settings.getBoolean(INFINITE_LOADING, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isInfiniteLoadingEnabled(): Boolean {
|
fun isInfiniteLoadingEnabled(): Boolean {
|
||||||
@ -235,7 +235,7 @@ class AppSettingsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshItemCachingEnabled() {
|
private fun refreshItemCachingEnabled() {
|
||||||
_itemsCaching = settings.getBoolean("items_caching", false)
|
_itemsCaching = settings.getBoolean(ITEMS_CACHING, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isItemCachingEnabled(): Boolean {
|
fun isItemCachingEnabled(): Boolean {
|
||||||
@ -246,7 +246,7 @@ class AppSettingsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshNotifyNewItemsEnabled() {
|
private fun refreshNotifyNewItemsEnabled() {
|
||||||
_notifyNewItems = settings.getBoolean("notify_new_items", false)
|
_notifyNewItems = settings.getBoolean(NOTIFY_NEW_ITEMS, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isNotifyNewItemsEnabled(): Boolean {
|
fun isNotifyNewItemsEnabled(): Boolean {
|
||||||
@ -258,7 +258,7 @@ class AppSettingsService {
|
|||||||
|
|
||||||
|
|
||||||
private fun refreshMarkOnScrollEnabled() {
|
private fun refreshMarkOnScrollEnabled() {
|
||||||
_markOnScroll = settings.getBoolean("mark_on_scroll", false)
|
_markOnScroll = settings.getBoolean(MARK_ON_SCROLL, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isMarkOnScrollEnabled(): Boolean {
|
fun isMarkOnScrollEnabled(): Boolean {
|
||||||
@ -270,7 +270,7 @@ class AppSettingsService {
|
|||||||
|
|
||||||
|
|
||||||
private fun refreshActiveAllignment() {
|
private fun refreshActiveAllignment() {
|
||||||
_activeAlignment = settings.getInt("text_align", JUSTIFY)
|
_activeAlignment = settings.getInt(TEXT_ALIGN, JUSTIFY)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getActiveAllignment(): Int {
|
fun getActiveAllignment(): Int {
|
||||||
@ -281,12 +281,12 @@ class AppSettingsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun changeAllignment(allignment: Int) {
|
fun changeAllignment(allignment: Int) {
|
||||||
settings.putInt("text_align", allignment)
|
settings.putInt(TEXT_ALIGN, allignment)
|
||||||
_activeAlignment = allignment
|
_activeAlignment = allignment
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshFontSize() {
|
private fun refreshFontSize() {
|
||||||
_fontSize = settings.getString("reader_font_size", "16").toInt()
|
_fontSize = settings.getString(READER_FONT_SIZE, "16").toInt()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getFontSize(): Int {
|
fun getFontSize(): Int {
|
||||||
@ -297,7 +297,7 @@ class AppSettingsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshStaticBarEnabled() {
|
private fun refreshStaticBarEnabled() {
|
||||||
_staticBar = settings.getBoolean("reader_static_bar", false)
|
_staticBar = settings.getBoolean(READER_STATIC_BAR, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isStaticBarEnabled(): Boolean {
|
fun isStaticBarEnabled(): Boolean {
|
||||||
@ -308,11 +308,11 @@ class AppSettingsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshFont() {
|
private fun refreshFont() {
|
||||||
_font = settings.getString("reader_font", "")
|
_font = settings.getString(READER_FONT, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getFont(): String {
|
fun getFont(): String {
|
||||||
if (_font != null) {
|
if (_font.isEmpty()) {
|
||||||
refreshFont()
|
refreshFont()
|
||||||
}
|
}
|
||||||
return _font
|
return _font
|
||||||
@ -353,21 +353,21 @@ class AppSettingsService {
|
|||||||
login: String,
|
login: String,
|
||||||
password: String
|
password: String
|
||||||
) {
|
) {
|
||||||
settings.putString("url", url)
|
settings.putString(BASE_URL, url)
|
||||||
settings.putString("login", login)
|
settings.putString(LOGIN, login)
|
||||||
settings.putString("password", password)
|
settings.putString(PASSWORD, password)
|
||||||
refreshApiSettings()
|
refreshApiSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun resetLoginInformation() {
|
fun resetLoginInformation() {
|
||||||
settings.remove("url")
|
settings.remove(BASE_URL)
|
||||||
settings.remove("login")
|
settings.remove(LOGIN)
|
||||||
settings.remove("password")
|
settings.remove(PASSWORD)
|
||||||
refreshApiSettings()
|
refreshApiSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateApiVersion(apiMajorVersion: Int) {
|
fun updateApiVersion(apiMajorVersion: Int) {
|
||||||
settings.putInt("apiVersionMajor", apiMajorVersion)
|
settings.putInt(API_VERSION_MAJOR, apiMajorVersion)
|
||||||
refreshApiVersion()
|
refreshApiVersion()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,7 +378,7 @@ class AppSettingsService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun disableArticleViewer() {
|
fun disableArticleViewer() {
|
||||||
settings.putBoolean("prefer_article_viewer", false)
|
settings.putBoolean(PREFER_ARTICLE_VIEWER, false)
|
||||||
refreshArticleViewerEnabled()
|
refreshArticleViewerEnabled()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,5 +396,53 @@ class AppSettingsService {
|
|||||||
const val JUSTIFY = 1
|
const val JUSTIFY = 1
|
||||||
|
|
||||||
const val ALIGN_LEFT = 2
|
const val ALIGN_LEFT = 2
|
||||||
|
|
||||||
|
const val API_VERSION_MAJOR = "apiVersionMajor"
|
||||||
|
|
||||||
|
const val API_ITEMS_NUMBER = "prefer_api_items_number"
|
||||||
|
|
||||||
|
const val API_TIMEOUT = "api_timeout"
|
||||||
|
|
||||||
|
const val BASE_URL = "url"
|
||||||
|
|
||||||
|
const val LOGIN = "login"
|
||||||
|
|
||||||
|
const val PASSWORD = "password"
|
||||||
|
|
||||||
|
const val PREFER_ARTICLE_VIEWER = "prefer_article_viewer"
|
||||||
|
|
||||||
|
const val CARD_VIEW_ACTIVE = "card_view_active"
|
||||||
|
|
||||||
|
const val DISPLAY_UNREAD_COUNT = "display_unread_count"
|
||||||
|
|
||||||
|
const val DISPLAY_OTHER_COUNT = "display_other_count"
|
||||||
|
|
||||||
|
const val FULL_HEIGHT_CARDS = "full_height_cards"
|
||||||
|
|
||||||
|
const val UPDATE_SOURCES = "update_sources"
|
||||||
|
|
||||||
|
const val PERIODIC_REFRESH = "periodic_refresh"
|
||||||
|
|
||||||
|
const val REFRESH_WHEN_CHARGING = "refresh_when_charging"
|
||||||
|
|
||||||
|
const val READER_FONT = "reader_font"
|
||||||
|
|
||||||
|
const val READER_STATIC_BAR = "reader_static_bar"
|
||||||
|
|
||||||
|
const val READER_FONT_SIZE = "reader_font_size"
|
||||||
|
|
||||||
|
const val TEXT_ALIGN = "text_align"
|
||||||
|
|
||||||
|
const val MARK_ON_SCROLL = "mark_on_scroll"
|
||||||
|
|
||||||
|
const val NOTIFY_NEW_ITEMS = "notify_new_items"
|
||||||
|
|
||||||
|
const val PERIODIC_REFRESH_MINUTES = "periodic_refresh_minutes"
|
||||||
|
|
||||||
|
const val HIDDEN_TAGS = "hidden_tags"
|
||||||
|
|
||||||
|
const val INFINITE_LOADING = "infinite_loading"
|
||||||
|
|
||||||
|
const val ITEMS_CACHING = "items_caching"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,27 +0,0 @@
|
|||||||
package bou.amine.apps.readerforselfossv2.service
|
|
||||||
|
|
||||||
import bou.amine.apps.readerforselfossv2.utils.DateUtils
|
|
||||||
|
|
||||||
class SearchService(val dateUtils: DateUtils) {
|
|
||||||
var displayedItems: String = "unread"
|
|
||||||
set(value) {
|
|
||||||
field = when (value) {
|
|
||||||
"all" -> "all"
|
|
||||||
"unread" -> "unread"
|
|
||||||
"read" -> "read"
|
|
||||||
"starred" -> "starred"
|
|
||||||
else -> "all"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var position = 0
|
|
||||||
var searchFilter: String? = null
|
|
||||||
var sourceIDFilter: Long? = null
|
|
||||||
var sourceFilter: String? = null
|
|
||||||
var tagFilter: String? = null
|
|
||||||
var itemsCaching = false
|
|
||||||
|
|
||||||
var badgeUnread = -1
|
|
||||||
var badgeAll = -1
|
|
||||||
var badgeStarred = -1
|
|
||||||
}
|
|
@ -1,16 +1,9 @@
|
|||||||
package bou.amine.apps.readerforselfossv2.utils
|
package bou.amine.apps.readerforselfossv2.utils
|
||||||
|
|
||||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
expect class DateUtils() {
|
||||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
companion object {
|
||||||
|
fun parseDate(dateString: String): Long
|
||||||
|
|
||||||
|
fun parseRelativeDate(dateString: String): String
|
||||||
fun SelfossModel.Item.parseDate(dateUtils: DateUtils): Long =
|
}
|
||||||
dateUtils.parseDate(this.datetime)
|
|
||||||
|
|
||||||
expect class DateUtils constructor(appSettingsService: AppSettingsService) {
|
|
||||||
val appSettingsService: AppSettingsService // This is needed because of https://stackoverflow.com/a/65249085
|
|
||||||
|
|
||||||
fun parseDate(dateString: String): Long
|
|
||||||
|
|
||||||
fun parseRelativeDate(dateString: String): String
|
|
||||||
}
|
}
|
||||||
|
@ -65,6 +65,6 @@ fun SelfossModel.Item.toEntity(): ITEM =
|
|||||||
this.thumbnail,
|
this.thumbnail,
|
||||||
this.icon,
|
this.icon,
|
||||||
this.link,
|
this.link,
|
||||||
this.title.getHtmlDecoded(),
|
this.sourcetitle.getHtmlDecoded(),
|
||||||
this.tags.joinToString(",")
|
this.tags.joinToString(",")
|
||||||
)
|
)
|
@ -1,14 +1,13 @@
|
|||||||
package bou.amine.apps.readerforselfossv2.utils
|
package bou.amine.apps.readerforselfossv2.utils
|
||||||
|
|
||||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
actual class DateUtils {
|
||||||
|
actual companion object {
|
||||||
|
actual fun parseDate(dateString: String): Long {
|
||||||
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
actual class DateUtils actual constructor(actual val appSettingsService: AppSettingsService) {
|
actual fun parseRelativeDate(dateString: String): String {
|
||||||
actual fun parseDate(dateString: String): Long {
|
TODO("Not yet implemented")
|
||||||
TODO("Not yet implemented")
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun parseRelativeDate(dateString: String): String {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,12 +0,0 @@
|
|||||||
package bou.amine.apps.readerforselfossv2
|
|
||||||
|
|
||||||
import kotlin.test.Test
|
|
||||||
import kotlin.test.assertTrue
|
|
||||||
|
|
||||||
class IosGreetingTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testExample() {
|
|
||||||
assertTrue(Greeting().greeting().contains("iOS"), "Check iOS is mentioned")
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,13 +2,15 @@ package bou.amine.apps.readerforselfossv2.utils
|
|||||||
|
|
||||||
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
|
|
||||||
actual class DateUtils actual constructor(actual val appSettingsService: AppSettingsService) {
|
actual class DateUtils {
|
||||||
actual fun parseDate(dateString: String): Long {
|
actual companion object {
|
||||||
TODO("Not yet implemented")
|
actual fun parseDate(dateString: String): Long {
|
||||||
}
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
|
|
||||||
actual fun parseRelativeDate(dateString: String): String {
|
actual fun parseRelativeDate(dateString: String): String {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Reference in New Issue
Block a user