Really big settings cleaning.
This commit is contained in:
parent
5531034086
commit
a99286a9b7
@ -68,10 +68,6 @@
|
|||||||
android:name=".ImageActivity">
|
android:name=".ImageActivity">
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<meta-data
|
|
||||||
android:name="bou.amine.apps.readerforselfossv2.android.utils.glide.SelfSignedGlideModule"
|
|
||||||
android:value="GlideModule" />
|
|
||||||
|
|
||||||
<meta-data android:name="android.webkit.WebView.MetricsOptOut"
|
<meta-data android:name="android.webkit.WebView.MetricsOptOut"
|
||||||
android:value="true" />
|
android:value="true" />
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import bou.amine.apps.readerforselfossv2.android.themes.Toppings
|
|||||||
import bou.amine.apps.readerforselfossv2.android.utils.isBaseUrlValid
|
import bou.amine.apps.readerforselfossv2.android.utils.isBaseUrlValid
|
||||||
import bou.amine.apps.readerforselfossv2.model.NetworkUnavailableException
|
import bou.amine.apps.readerforselfossv2.model.NetworkUnavailableException
|
||||||
import bou.amine.apps.readerforselfossv2.repository.Repository
|
import bou.amine.apps.readerforselfossv2.repository.Repository
|
||||||
import bou.amine.apps.readerforselfossv2.service.ApiDetailsService
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
import com.ftinc.scoop.Scoop
|
import com.ftinc.scoop.Scoop
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -31,7 +31,7 @@ class AddSourceActivity : AppCompatActivity(), DIAware {
|
|||||||
|
|
||||||
override val di by closestDI()
|
override val di by closestDI()
|
||||||
private val repository : Repository by instance()
|
private val repository : Repository by instance()
|
||||||
private val apiDetailsService : ApiDetailsService by instance()
|
private val appSettingsService : AppSettingsService by instance()
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
appColors = AppColors(this@AddSourceActivity)
|
appColors = AppColors(this@AddSourceActivity)
|
||||||
@ -83,7 +83,7 @@ class AddSourceActivity : AppCompatActivity(), DIAware {
|
|||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
||||||
val baseUrl = apiDetailsService.getBaseUrl()
|
val baseUrl = appSettingsService.getBaseUrl()
|
||||||
if (baseUrl.isEmpty() || !baseUrl.isBaseUrlValid(this@AddSourceActivity)) {
|
if (baseUrl.isEmpty() || !baseUrl.isBaseUrlValid(this@AddSourceActivity)) {
|
||||||
mustLoginToAddSource()
|
mustLoginToAddSource()
|
||||||
} else {
|
} else {
|
||||||
|
@ -35,7 +35,7 @@ import bou.amine.apps.readerforselfossv2.android.utils.bottombar.removeBadge
|
|||||||
import bou.amine.apps.readerforselfossv2.android.utils.customtabs.CustomTabActivityHelper
|
import bou.amine.apps.readerforselfossv2.android.utils.customtabs.CustomTabActivityHelper
|
||||||
import bou.amine.apps.readerforselfossv2.repository.Repository
|
import bou.amine.apps.readerforselfossv2.repository.Repository
|
||||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||||
import bou.amine.apps.readerforselfossv2.service.ApiDetailsService
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
import bou.amine.apps.readerforselfossv2.utils.*
|
import bou.amine.apps.readerforselfossv2.utils.*
|
||||||
import com.ashokvarma.bottomnavigation.BottomNavigationBar
|
import com.ashokvarma.bottomnavigation.BottomNavigationBar
|
||||||
import com.ashokvarma.bottomnavigation.BottomNavigationItem
|
import com.ashokvarma.bottomnavigation.BottomNavigationItem
|
||||||
@ -69,7 +69,6 @@ import kotlin.concurrent.thread
|
|||||||
|
|
||||||
class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAware {
|
class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAware {
|
||||||
|
|
||||||
private val MENU_PREFERENCES = 12302
|
|
||||||
private val DRAWER_ID_TAGS = 100101L
|
private val DRAWER_ID_TAGS = 100101L
|
||||||
private val DRAWER_ID_HIDDEN_TAGS = 101100L
|
private val DRAWER_ID_HIDDEN_TAGS = 101100L
|
||||||
private val DRAWER_ID_SOURCES = 100110L
|
private val DRAWER_ID_SOURCES = 100110L
|
||||||
@ -77,21 +76,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
|
|
||||||
private var items: ArrayList<SelfossModel.Item> = ArrayList()
|
private var items: ArrayList<SelfossModel.Item> = ArrayList()
|
||||||
|
|
||||||
private var internalBrowser = false
|
|
||||||
private var articleViewer = false
|
|
||||||
private var shouldBeCardView = false
|
|
||||||
private var displayUnreadCount = false
|
|
||||||
private var displayAllCount = false
|
|
||||||
private var fullHeightCards: Boolean = false
|
|
||||||
private var elementsShown: ItemType = ItemType.UNREAD
|
private var elementsShown: ItemType = ItemType.UNREAD
|
||||||
private var lastFetchDone: Boolean = false
|
private var lastFetchDone: Boolean = false
|
||||||
private var updateSources: Boolean = true
|
|
||||||
private var markOnScroll: Boolean = false
|
|
||||||
private var hiddenTags: List<String> = emptyList()
|
|
||||||
|
|
||||||
private var periodicRefresh = false
|
|
||||||
private var refreshMinutes: Long = 360L
|
|
||||||
private var refreshWhenChargingOnly = false
|
|
||||||
|
|
||||||
private lateinit var tabNewBadge: TextBadgeItem
|
private lateinit var tabNewBadge: TextBadgeItem
|
||||||
private lateinit var tabArchiveBadge: TextBadgeItem
|
private lateinit var tabArchiveBadge: TextBadgeItem
|
||||||
@ -101,7 +87,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
private var offset: Int = 0
|
private var offset: Int = 0
|
||||||
private var firstVisible: Int = 0
|
private var firstVisible: Int = 0
|
||||||
private lateinit var recyclerViewScrollListener: RecyclerView.OnScrollListener
|
private lateinit var recyclerViewScrollListener: RecyclerView.OnScrollListener
|
||||||
private var settings = Settings()
|
|
||||||
private lateinit var binding: ActivityHomeBinding
|
private lateinit var binding: ActivityHomeBinding
|
||||||
|
|
||||||
private var recyclerAdapter: RecyclerView.Adapter<*>? = null
|
private var recyclerAdapter: RecyclerView.Adapter<*>? = null
|
||||||
@ -112,6 +97,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
|
|
||||||
override val di by closestDI()
|
override val di by closestDI()
|
||||||
private val repository : Repository by instance()
|
private val repository : Repository by instance()
|
||||||
|
private val appSettingsService : AppSettingsService by instance()
|
||||||
|
|
||||||
data class DrawerData(val tags: List<SelfossModel.Tag>?, val sources: List<SelfossModel.Source>?)
|
data class DrawerData(val tags: List<SelfossModel.Tag>?, val sources: List<SelfossModel.Source>?)
|
||||||
|
|
||||||
@ -121,6 +107,8 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
|
||||||
|
// Add appcolors to DI
|
||||||
appColors = AppColors(this@HomeActivity)
|
appColors = AppColors(this@HomeActivity)
|
||||||
|
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@ -152,8 +140,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
|
|
||||||
handleSwipeRefreshLayout()
|
handleSwipeRefreshLayout()
|
||||||
|
|
||||||
handleSettings()
|
|
||||||
|
|
||||||
getElementsAccordingToTab()
|
getElementsAccordingToTab()
|
||||||
|
|
||||||
|
|
||||||
@ -292,7 +278,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
|
||||||
// TODO: Make this the only appcolors init
|
|
||||||
appColors = AppColors(this@HomeActivity)
|
appColors = AppColors(this@HomeActivity)
|
||||||
|
|
||||||
handleDrawerItems()
|
handleDrawerItems()
|
||||||
@ -301,10 +286,10 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
|
|
||||||
reloadLayoutManager()
|
reloadLayoutManager()
|
||||||
|
|
||||||
if (!settings.getBoolean("infinite_loading", false)) {
|
if (appSettingsService.isInfiniteLoadingEnabled()) {
|
||||||
binding.recyclerView.setHasFixedSize(true)
|
|
||||||
} else {
|
|
||||||
handleInfiniteScroll()
|
handleInfiniteScroll()
|
||||||
|
} else {
|
||||||
|
binding.recyclerView.setHasFixedSize(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleBottomBarActions()
|
handleBottomBarActions()
|
||||||
@ -323,31 +308,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
customTabActivityHelper.unbindCustomTabsService(this)
|
customTabActivityHelper.unbindCustomTabsService(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleSettings() {
|
|
||||||
// TODO : clean this
|
|
||||||
internalBrowser = settings.getBoolean("prefer_internal_browser", true)
|
|
||||||
articleViewer = settings.getBoolean("prefer_article_viewer", true)
|
|
||||||
shouldBeCardView = settings.getBoolean("card_view_active", false)
|
|
||||||
displayUnreadCount = settings.getBoolean("display_unread_count", true)
|
|
||||||
displayAllCount = settings.getBoolean("display_other_count", false)
|
|
||||||
fullHeightCards = settings.getBoolean("full_height_cards", false)
|
|
||||||
|
|
||||||
updateSources = settings.getBoolean("update_sources", true)
|
|
||||||
markOnScroll = settings.getBoolean("mark_on_scroll", false)
|
|
||||||
hiddenTags = if (settings.getString("hidden_tags", "").isNotEmpty()) {
|
|
||||||
settings.getString("hidden_tags", "").replace("\\s".toRegex(), "").split(",")
|
|
||||||
} else {
|
|
||||||
emptyList()
|
|
||||||
}
|
|
||||||
periodicRefresh = settings.getBoolean("periodic_refresh", false)
|
|
||||||
refreshWhenChargingOnly = settings.getBoolean("refresh_when_charging", false)
|
|
||||||
refreshMinutes = settings.getString("periodic_refresh_minutes", "360").toLong()
|
|
||||||
|
|
||||||
if (refreshMinutes <= 15) {
|
|
||||||
refreshMinutes = 15
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun handleThemeBinding() {
|
private fun handleThemeBinding() {
|
||||||
val scoop = Scoop.getInstance()
|
val scoop = Scoop.getInstance()
|
||||||
scoop.bind(this, Toppings.PRIMARY.value, binding.toolBar)
|
scoop.bind(this, Toppings.PRIMARY.value, binding.toolBar)
|
||||||
@ -401,16 +361,13 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
|
|
||||||
binding.drawerContainer.addDrawerListener(drawerListener)
|
binding.drawerContainer.addDrawerListener(drawerListener)
|
||||||
|
|
||||||
val displayAccountHeader =
|
|
||||||
settings.getBoolean("account_header_displaying", false)
|
|
||||||
|
|
||||||
binding.mainDrawer.addStickyFooterItem(
|
binding.mainDrawer.addStickyFooterItem(
|
||||||
PrimaryDrawerItem().apply {
|
PrimaryDrawerItem().apply {
|
||||||
nameRes = R.string.drawer_report_bug
|
nameRes = R.string.drawer_report_bug
|
||||||
iconRes = R.drawable.ic_bug_report_black_24dp
|
iconRes = R.drawable.ic_bug_report_black_24dp
|
||||||
isIconTinted = true
|
isIconTinted = true
|
||||||
onDrawerItemClickListener = { _, _, _ ->
|
onDrawerItemClickListener = { _, _, _ ->
|
||||||
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(ApiDetailsService.trackerUrl))
|
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(AppSettingsService.trackerUrl))
|
||||||
startActivity(browserIntent)
|
startActivity(browserIntent)
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
@ -427,12 +384,12 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (displayAccountHeader) {
|
if (appSettingsService.isDisplayAccountHeaderEnabled()) {
|
||||||
AccountHeaderView(this).apply {
|
AccountHeaderView(this).apply {
|
||||||
attachToSliderView(binding.mainDrawer)
|
attachToSliderView(binding.mainDrawer)
|
||||||
addProfiles(
|
addProfiles(
|
||||||
ProfileDrawerItem().apply {
|
ProfileDrawerItem().apply {
|
||||||
nameText = settings.getString("url", "")
|
nameText = appSettingsService.getBaseUrl()
|
||||||
setBackgroundResource(R.drawable.bg)
|
setBackgroundResource(R.drawable.bg)
|
||||||
iconRes = R.mipmap.ic_launcher
|
iconRes = R.mipmap.ic_launcher
|
||||||
selectionListEnabledForSingleProfile = false
|
selectionListEnabledForSingleProfile = false
|
||||||
@ -496,7 +453,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val filteredTags = maybeTags
|
val filteredTags = maybeTags
|
||||||
.filterNot { hiddenTags.contains(it.tag) }
|
.filterNot { appSettingsService.getHiddenTags().contains(it.tag) }
|
||||||
.sortedBy { it.unread == 0 }
|
.sortedBy { it.unread == 0 }
|
||||||
tagsBadge = filteredTags.map {
|
tagsBadge = filteredTags.map {
|
||||||
createDrawerItem(it)
|
createDrawerItem(it)
|
||||||
@ -518,7 +475,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val filteredHiddenTags: List<SelfossModel.Tag> =
|
val filteredHiddenTags: List<SelfossModel.Tag> =
|
||||||
maybeTags.filter { hiddenTags.contains(it.tag) }
|
maybeTags.filter { appSettingsService.getHiddenTags().contains(it.tag) }
|
||||||
tagsBadge = filteredHiddenTags.map {
|
tagsBadge = filteredHiddenTags.map {
|
||||||
createDrawerItem(it)
|
createDrawerItem(it)
|
||||||
|
|
||||||
@ -574,7 +531,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if (hiddenTags.isNotEmpty()) {
|
if (appSettingsService.getHiddenTags().isNotEmpty()) {
|
||||||
binding.mainDrawer.itemAdapter.add(
|
binding.mainDrawer.itemAdapter.add(
|
||||||
DividerDrawerItem(),
|
DividerDrawerItem(),
|
||||||
SecondaryDrawerItem().apply {
|
SecondaryDrawerItem().apply {
|
||||||
@ -707,7 +664,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
// This will only update the layout manager if settings changed
|
// This will only update the layout manager if settings changed
|
||||||
when (currentManager) {
|
when (currentManager) {
|
||||||
is StaggeredGridLayoutManager ->
|
is StaggeredGridLayoutManager ->
|
||||||
if (!shouldBeCardView) {
|
if (!appSettingsService.isCardViewEnabled()) {
|
||||||
layoutManager = GridLayoutManager(
|
layoutManager = GridLayoutManager(
|
||||||
this,
|
this,
|
||||||
calculateNoOfColumns()
|
calculateNoOfColumns()
|
||||||
@ -715,7 +672,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
binding.recyclerView.layoutManager = layoutManager
|
binding.recyclerView.layoutManager = layoutManager
|
||||||
}
|
}
|
||||||
is GridLayoutManager ->
|
is GridLayoutManager ->
|
||||||
if (shouldBeCardView) {
|
if (appSettingsService.isCardViewEnabled()) {
|
||||||
layoutManager = StaggeredGridLayoutManager(
|
layoutManager = StaggeredGridLayoutManager(
|
||||||
calculateNoOfColumns(),
|
calculateNoOfColumns(),
|
||||||
StaggeredGridLayoutManager.VERTICAL
|
StaggeredGridLayoutManager.VERTICAL
|
||||||
@ -726,7 +683,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
}
|
}
|
||||||
else ->
|
else ->
|
||||||
if (currentManager == null) {
|
if (currentManager == null) {
|
||||||
if (!shouldBeCardView) {
|
if (!appSettingsService.isCardViewEnabled()) {
|
||||||
layoutManager = GridLayoutManager(
|
layoutManager = GridLayoutManager(
|
||||||
this,
|
this,
|
||||||
calculateNoOfColumns()
|
calculateNoOfColumns()
|
||||||
@ -862,15 +819,12 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (recyclerAdapter == null) {
|
if (recyclerAdapter == null) {
|
||||||
if (shouldBeCardView) {
|
if (appSettingsService.isCardViewEnabled()) {
|
||||||
recyclerAdapter =
|
recyclerAdapter =
|
||||||
ItemCardAdapter(
|
ItemCardAdapter(
|
||||||
this,
|
this,
|
||||||
items,
|
items,
|
||||||
customTabActivityHelper,
|
customTabActivityHelper,
|
||||||
internalBrowser, // TODO remove and use from apidetailsservice
|
|
||||||
articleViewer, // TODO remove and use from apidetailsservice
|
|
||||||
fullHeightCards, // TODO remove and use from apidetailsservice
|
|
||||||
appColors,
|
appColors,
|
||||||
) {
|
) {
|
||||||
updateItems(it)
|
updateItems(it)
|
||||||
@ -881,8 +835,6 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
this,
|
this,
|
||||||
items,
|
items,
|
||||||
customTabActivityHelper,
|
customTabActivityHelper,
|
||||||
internalBrowser, // TODO remove and use from apidetailsservice
|
|
||||||
articleViewer, // TODO remove and use from apidetailsservice
|
|
||||||
appColors,
|
appColors,
|
||||||
) {
|
) {
|
||||||
updateItems(it)
|
updateItems(it)
|
||||||
@ -905,7 +857,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun reloadBadges() {
|
private fun reloadBadges() {
|
||||||
if (displayUnreadCount || displayAllCount) {
|
if (appSettingsService.isDisplayUnreadCountEnabled() || appSettingsService.isDisplayAllCountEnabled()) {
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
repository.reloadBadges()
|
repository.reloadBadges()
|
||||||
reloadBadgeContent()
|
reloadBadgeContent()
|
||||||
@ -914,12 +866,12 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun reloadBadgeContent() {
|
private fun reloadBadgeContent() {
|
||||||
if (displayUnreadCount) {
|
if (appSettingsService.isDisplayUnreadCountEnabled()) {
|
||||||
tabNewBadge
|
tabNewBadge
|
||||||
.setText(repository.badgeUnread.toString())
|
.setText(repository.badgeUnread.toString())
|
||||||
.maybeShow()
|
.maybeShow()
|
||||||
}
|
}
|
||||||
if (displayAllCount) {
|
if (appSettingsService.isDisplayAllCountEnabled()) {
|
||||||
tabArchiveBadge
|
tabArchiveBadge
|
||||||
.setText(repository.badgeAll.toString())
|
.setText(repository.badgeAll.toString())
|
||||||
.maybeShow()
|
.maybeShow()
|
||||||
@ -1038,8 +990,7 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
R.id.action_disconnect -> {
|
R.id.action_disconnect -> {
|
||||||
val settings = Settings()
|
appSettingsService.clearAll()
|
||||||
settings.clear()
|
|
||||||
val intent = Intent(this, LoginActivity::class.java)
|
val intent = Intent(this, LoginActivity::class.java)
|
||||||
this.startActivity(intent)
|
this.startActivity(intent)
|
||||||
this@HomeActivity.finish()
|
this@HomeActivity.finish()
|
||||||
@ -1062,15 +1013,15 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun handleRecurringTask() {
|
private fun handleRecurringTask() {
|
||||||
if (periodicRefresh) {
|
if (appSettingsService.isPeriodicRefreshEnabled()) {
|
||||||
val myConstraints = Constraints.Builder()
|
val myConstraints = Constraints.Builder()
|
||||||
.setRequiresBatteryNotLow(true)
|
.setRequiresBatteryNotLow(true)
|
||||||
.setRequiresCharging(refreshWhenChargingOnly)
|
.setRequiresCharging(appSettingsService.isRefreshWhenChargingOnlyEnabled())
|
||||||
.setRequiresStorageNotLow(true)
|
.setRequiresStorageNotLow(true)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
val backgroundWork =
|
val backgroundWork =
|
||||||
PeriodicWorkRequestBuilder<LoadingWorker>(refreshMinutes, TimeUnit.MINUTES)
|
PeriodicWorkRequestBuilder<LoadingWorker>(appSettingsService.getRefreshMinutes(), TimeUnit.MINUTES)
|
||||||
.setConstraints(myConstraints)
|
.setConstraints(myConstraints)
|
||||||
.addTag("selfoss-loading")
|
.addTag("selfoss-loading")
|
||||||
.build()
|
.build()
|
||||||
@ -1078,9 +1029,5 @@ class HomeActivity : AppCompatActivity(), SearchView.OnQueryTextListener, DIAwar
|
|||||||
WorkManager.getInstance(baseContext).enqueueUniquePeriodicWork("selfoss-loading", ExistingPeriodicWorkPolicy.KEEP, backgroundWork)
|
WorkManager.getInstance(baseContext).enqueueUniquePeriodicWork("selfoss-loading", ExistingPeriodicWorkPolicy.KEEP, backgroundWork)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleOfflineActions() {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,8 +16,8 @@ import bou.amine.apps.readerforselfossv2.android.databinding.ActivityLoginBindin
|
|||||||
import bou.amine.apps.readerforselfossv2.android.themes.AppColors
|
import bou.amine.apps.readerforselfossv2.android.themes.AppColors
|
||||||
import bou.amine.apps.readerforselfossv2.android.utils.isBaseUrlValid
|
import bou.amine.apps.readerforselfossv2.android.utils.isBaseUrlValid
|
||||||
import bou.amine.apps.readerforselfossv2.repository.Repository
|
import bou.amine.apps.readerforselfossv2.repository.Repository
|
||||||
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
import com.mikepenz.aboutlibraries.LibsBuilder
|
import com.mikepenz.aboutlibraries.LibsBuilder
|
||||||
import com.russhwolf.settings.Settings
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -25,19 +25,19 @@ import org.kodein.di.DIAware
|
|||||||
import org.kodein.di.android.closestDI
|
import org.kodein.di.android.closestDI
|
||||||
import org.kodein.di.instance
|
import org.kodein.di.instance
|
||||||
|
|
||||||
class LoginActivity() : AppCompatActivity(), DIAware {
|
class LoginActivity : AppCompatActivity(), DIAware {
|
||||||
|
|
||||||
private var inValidCount: Int = 0
|
private var inValidCount: Int = 0
|
||||||
private var isWithSelfSignedCert = false
|
private var isWithSelfSignedCert = false
|
||||||
private var isWithLogin = false
|
private var isWithLogin = false
|
||||||
private var isWithHTTPLogin = false
|
private var isWithHTTPLogin = false
|
||||||
|
|
||||||
private val settings = Settings()
|
|
||||||
private lateinit var appColors: AppColors
|
private lateinit var appColors: AppColors
|
||||||
private lateinit var binding: ActivityLoginBinding
|
private lateinit var binding: ActivityLoginBinding
|
||||||
|
|
||||||
override val di by closestDI()
|
override val di by closestDI()
|
||||||
private val repository : Repository by instance()
|
private val repository : Repository by instance()
|
||||||
|
private val appSettingsService : AppSettingsService by instance()
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
appColors = AppColors(this@LoginActivity)
|
appColors = AppColors(this@LoginActivity)
|
||||||
@ -52,7 +52,7 @@ class LoginActivity() : AppCompatActivity(), DIAware {
|
|||||||
|
|
||||||
handleBaseUrlFail()
|
handleBaseUrlFail()
|
||||||
|
|
||||||
if (settings.getString("url", "").isNotEmpty()) {
|
if (appSettingsService.getBaseUrl().isNotEmpty()) {
|
||||||
goToMain()
|
goToMain()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,11 +117,8 @@ class LoginActivity() : AppCompatActivity(), DIAware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun preferenceError(t: Throwable) {
|
private fun preferenceError(t: Throwable) {
|
||||||
settings.remove("url")
|
appSettingsService.resetLoginInformation()
|
||||||
settings.remove("login")
|
|
||||||
settings.remove("httpUserName")
|
|
||||||
settings.remove("password")
|
|
||||||
settings.remove("httpPassword")
|
|
||||||
binding.urlView.error = getString(R.string.wrong_infos)
|
binding.urlView.error = getString(R.string.wrong_infos)
|
||||||
binding.loginView.error = getString(R.string.wrong_infos)
|
binding.loginView.error = getString(R.string.wrong_infos)
|
||||||
binding.passwordView.error = getString(R.string.wrong_infos)
|
binding.passwordView.error = getString(R.string.wrong_infos)
|
||||||
@ -199,7 +196,7 @@ class LoginActivity() : AppCompatActivity(), DIAware {
|
|||||||
} else {
|
} else {
|
||||||
showProgress(true)
|
showProgress(true)
|
||||||
|
|
||||||
repository.refreshLoginInformation(url, login, password, httpLogin, httpPassword, isWithSelfSignedCert)
|
repository.refreshLoginInformation(url, login, password, isWithSelfSignedCert)
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
val result = repository.login()
|
val result = repository.login()
|
||||||
|
@ -18,7 +18,7 @@ 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
|
||||||
import bou.amine.apps.readerforselfossv2.repository.Repository
|
import bou.amine.apps.readerforselfossv2.repository.Repository
|
||||||
import bou.amine.apps.readerforselfossv2.service.ApiDetailsService
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.request.RequestOptions
|
import com.bumptech.glide.request.RequestOptions
|
||||||
import com.ftinc.scoop.Scoop
|
import com.ftinc.scoop.Scoop
|
||||||
@ -48,12 +48,10 @@ class MyApp : MultiDexApplication(), DIAware {
|
|||||||
private val viewModel: AppViewModel by instance()
|
private val viewModel: AppViewModel by instance()
|
||||||
private val connectivityStatus: ConnectivityStatus by instance()
|
private val connectivityStatus: ConnectivityStatus by instance()
|
||||||
private val driverFactory: DriverFactory by instance()
|
private val driverFactory: DriverFactory by instance()
|
||||||
private lateinit var settings : Settings
|
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
Napier.base(DebugAntilog())
|
Napier.base(DebugAntilog())
|
||||||
settings = Settings()
|
|
||||||
|
|
||||||
initDrawerImageLoader()
|
initDrawerImageLoader()
|
||||||
|
|
||||||
@ -90,11 +88,11 @@ class MyApp : MultiDexApplication(), DIAware {
|
|||||||
|
|
||||||
val name = getString(R.string.notification_channel_sync)
|
val name = getString(R.string.notification_channel_sync)
|
||||||
val importance = NotificationManager.IMPORTANCE_LOW
|
val importance = NotificationManager.IMPORTANCE_LOW
|
||||||
val mChannel = NotificationChannel(ApiDetailsService.syncChannelId, name, importance)
|
val mChannel = NotificationChannel(AppSettingsService.syncChannelId, name, importance)
|
||||||
|
|
||||||
val newItemsChannelname = getString(R.string.new_items_channel_sync)
|
val newItemsChannelname = getString(R.string.new_items_channel_sync)
|
||||||
val newItemsChannelimportance = NotificationManager.IMPORTANCE_DEFAULT
|
val newItemsChannelimportance = NotificationManager.IMPORTANCE_DEFAULT
|
||||||
val newItemsChannelmChannel = NotificationChannel(ApiDetailsService.newItemsChannelId, newItemsChannelname, newItemsChannelimportance)
|
val newItemsChannelmChannel = NotificationChannel(AppSettingsService.newItemsChannelId, newItemsChannelname, newItemsChannelimportance)
|
||||||
|
|
||||||
notificationManager.createNotificationChannel(mChannel)
|
notificationManager.createNotificationChannel(mChannel)
|
||||||
notificationManager.createNotificationChannel(newItemsChannelmChannel)
|
notificationManager.createNotificationChannel(newItemsChannelmChannel)
|
||||||
|
@ -16,8 +16,8 @@ import bou.amine.apps.readerforselfossv2.android.themes.AppColors
|
|||||||
import bou.amine.apps.readerforselfossv2.android.themes.Toppings
|
import bou.amine.apps.readerforselfossv2.android.themes.Toppings
|
||||||
import bou.amine.apps.readerforselfossv2.repository.Repository
|
import bou.amine.apps.readerforselfossv2.repository.Repository
|
||||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||||
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
import com.ftinc.scoop.Scoop
|
import com.ftinc.scoop.Scoop
|
||||||
import com.russhwolf.settings.Settings
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -27,7 +27,6 @@ import org.kodein.di.instance
|
|||||||
|
|
||||||
class ReaderActivity : AppCompatActivity(), DIAware {
|
class ReaderActivity : AppCompatActivity(), DIAware {
|
||||||
|
|
||||||
private var markOnScroll: Boolean = false
|
|
||||||
private var currentItem: Int = 0
|
private var currentItem: Int = 0
|
||||||
private lateinit var appColors: AppColors
|
private lateinit var appColors: AppColors
|
||||||
|
|
||||||
@ -35,12 +34,9 @@ class ReaderActivity : AppCompatActivity(), DIAware {
|
|||||||
|
|
||||||
private lateinit var binding: ActivityReaderBinding
|
private lateinit var binding: ActivityReaderBinding
|
||||||
|
|
||||||
private var activeAlignment: Int = 1
|
|
||||||
private val JUSTIFY = 1
|
|
||||||
private val ALIGN_LEFT = 2
|
|
||||||
|
|
||||||
override val di by closestDI()
|
override val di by closestDI()
|
||||||
private val repository: Repository by instance()
|
private val repository: Repository by instance()
|
||||||
|
private val appSettingsService: AppSettingsService by instance()
|
||||||
|
|
||||||
private fun showMenuItem(willAddToFavorite: Boolean) {
|
private fun showMenuItem(willAddToFavorite: Boolean) {
|
||||||
if (willAddToFavorite) {
|
if (willAddToFavorite) {
|
||||||
@ -58,8 +54,6 @@ class ReaderActivity : AppCompatActivity(), DIAware {
|
|||||||
showMenuItem(false)
|
showMenuItem(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var settings = Settings()
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
appColors = AppColors(this)
|
appColors = AppColors(this)
|
||||||
@ -76,9 +70,6 @@ class ReaderActivity : AppCompatActivity(), DIAware {
|
|||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
supportActionBar?.setDisplayShowHomeEnabled(true)
|
supportActionBar?.setDisplayShowHomeEnabled(true)
|
||||||
|
|
||||||
markOnScroll = settings.getBoolean("mark_on_scroll", false)
|
|
||||||
activeAlignment = settings.getInt("text_align", JUSTIFY)
|
|
||||||
|
|
||||||
if (allItems.isEmpty()) {
|
if (allItems.isEmpty()) {
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
@ -98,10 +89,9 @@ class ReaderActivity : AppCompatActivity(), DIAware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun readItem(item: SelfossModel.Item) {
|
private fun readItem(item: SelfossModel.Item) {
|
||||||
if (markOnScroll) {
|
if (appSettingsService.isMarkOnScrollEnabled()) {
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
repository.markAsRead(item)
|
repository.markAsRead(item)
|
||||||
// TODO: Handle failure
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -142,7 +132,7 @@ class ReaderActivity : AppCompatActivity(), DIAware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun alignmentMenu() {
|
private fun alignmentMenu() {
|
||||||
val showJustify = activeAlignment == ALIGN_LEFT
|
val showJustify = appSettingsService.getActiveAllignment() == AppSettingsService.ALIGN_LEFT
|
||||||
toolbarMenu.findItem(R.id.align_left).isVisible = !showJustify
|
toolbarMenu.findItem(R.id.align_left).isVisible = !showJustify
|
||||||
toolbarMenu.findItem(R.id.align_justify).isVisible = showJustify
|
toolbarMenu.findItem(R.id.align_justify).isVisible = showJustify
|
||||||
}
|
}
|
||||||
@ -211,21 +201,19 @@ class ReaderActivity : AppCompatActivity(), DIAware {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
R.id.align_left -> {
|
R.id.align_left -> {
|
||||||
activeAlignment = ALIGN_LEFT
|
switchAlignmentSetting(AppSettingsService.ALIGN_LEFT)
|
||||||
switchAlignmentSetting()
|
|
||||||
refreshFragment()
|
refreshFragment()
|
||||||
}
|
}
|
||||||
R.id.align_justify -> {
|
R.id.align_justify -> {
|
||||||
activeAlignment = JUSTIFY
|
switchAlignmentSetting(AppSettingsService.JUSTIFY)
|
||||||
switchAlignmentSetting()
|
|
||||||
refreshFragment()
|
refreshFragment()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item)
|
return super.onOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun switchAlignmentSetting() {
|
private fun switchAlignmentSetting(allignment: Int) {
|
||||||
settings.putInt("text_align", activeAlignment)
|
appSettingsService.changeAllignment(allignment)
|
||||||
alignmentMenu()
|
alignmentMenu()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ 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.repository.Repository
|
import bou.amine.apps.readerforselfossv2.repository.Repository
|
||||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||||
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded
|
import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded
|
||||||
import bou.amine.apps.readerforselfossv2.utils.getIcon
|
import bou.amine.apps.readerforselfossv2.utils.getIcon
|
||||||
import bou.amine.apps.readerforselfossv2.utils.getThumbnail
|
import bou.amine.apps.readerforselfossv2.utils.getThumbnail
|
||||||
@ -34,9 +35,6 @@ class ItemCardAdapter(
|
|||||||
override val app: Activity,
|
override val app: Activity,
|
||||||
override var items: ArrayList<SelfossModel.Item>,
|
override var items: ArrayList<SelfossModel.Item>,
|
||||||
private val helper: CustomTabActivityHelper,
|
private val helper: CustomTabActivityHelper,
|
||||||
private val internalBrowser: Boolean,
|
|
||||||
private val articleViewer: Boolean,
|
|
||||||
private val fullHeightCards: Boolean,
|
|
||||||
override val appColors: AppColors,
|
override val appColors: AppColors,
|
||||||
override val updateItems: (ArrayList<SelfossModel.Item>) -> Unit
|
override val updateItems: (ArrayList<SelfossModel.Item>) -> Unit
|
||||||
) : ItemsAdapter<ItemCardAdapter.ViewHolder>() {
|
) : ItemsAdapter<ItemCardAdapter.ViewHolder>() {
|
||||||
@ -47,6 +45,7 @@ class ItemCardAdapter(
|
|||||||
|
|
||||||
override val di: DI by closestDI(app)
|
override val di: DI by closestDI(app)
|
||||||
override val repository : Repository by instance()
|
override val repository : Repository by instance()
|
||||||
|
override val appSettingsService : AppSettingsService by instance()
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
val binding = CardItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
val binding = CardItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||||
@ -66,7 +65,7 @@ class ItemCardAdapter(
|
|||||||
|
|
||||||
binding.sourceTitleAndDate.text = itm.sourceAndDateText(repository.dateUtils)
|
binding.sourceTitleAndDate.text = itm.sourceAndDateText(repository.dateUtils)
|
||||||
|
|
||||||
if (!fullHeightCards) {
|
if (!appSettingsService.isFullHeightCardsEnabled()) {
|
||||||
binding.itemImage.maxHeight = imageMaxHeight
|
binding.itemImage.maxHeight = imageMaxHeight
|
||||||
binding.itemImage.scaleType = ScaleType.CENTER_CROP
|
binding.itemImage.scaleType = ScaleType.CENTER_CROP
|
||||||
}
|
}
|
||||||
@ -146,8 +145,8 @@ class ItemCardAdapter(
|
|||||||
bindingAdapterPosition,
|
bindingAdapterPosition,
|
||||||
items[bindingAdapterPosition].getLinkDecoded(),
|
items[bindingAdapterPosition].getLinkDecoded(),
|
||||||
customTabsIntent,
|
customTabsIntent,
|
||||||
internalBrowser,
|
appSettingsService.isInternalBrowserEnabled(),
|
||||||
articleViewer,
|
appSettingsService.isArticleViewerEnabled(),
|
||||||
app
|
app
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ 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.repository.Repository
|
import bou.amine.apps.readerforselfossv2.repository.Repository
|
||||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||||
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded
|
import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded
|
||||||
import bou.amine.apps.readerforselfossv2.utils.getIcon
|
import bou.amine.apps.readerforselfossv2.utils.getIcon
|
||||||
import bou.amine.apps.readerforselfossv2.utils.getThumbnail
|
import bou.amine.apps.readerforselfossv2.utils.getThumbnail
|
||||||
@ -27,8 +28,6 @@ class ItemListAdapter(
|
|||||||
override val app: Activity,
|
override val app: Activity,
|
||||||
override var items: ArrayList<SelfossModel.Item>,
|
override var items: ArrayList<SelfossModel.Item>,
|
||||||
private val helper: CustomTabActivityHelper,
|
private val helper: CustomTabActivityHelper,
|
||||||
private val internalBrowser: Boolean,
|
|
||||||
private val articleViewer: Boolean,
|
|
||||||
override val appColors: AppColors,
|
override val appColors: AppColors,
|
||||||
override val updateItems: (ArrayList<SelfossModel.Item>) -> Unit
|
override val updateItems: (ArrayList<SelfossModel.Item>) -> Unit
|
||||||
) : ItemsAdapter<ItemListAdapter.ViewHolder>() {
|
) : ItemsAdapter<ItemListAdapter.ViewHolder>() {
|
||||||
@ -37,6 +36,7 @@ class ItemListAdapter(
|
|||||||
|
|
||||||
override val di: DI by closestDI(app)
|
override val di: DI by closestDI(app)
|
||||||
override val repository : Repository by instance()
|
override val repository : Repository by instance()
|
||||||
|
override val appSettingsService : AppSettingsService by instance()
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
val binding = ListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
val binding = ListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||||
@ -94,8 +94,8 @@ class ItemListAdapter(
|
|||||||
bindingAdapterPosition,
|
bindingAdapterPosition,
|
||||||
items[bindingAdapterPosition].getLinkDecoded(),
|
items[bindingAdapterPosition].getLinkDecoded(),
|
||||||
customTabsIntent,
|
customTabsIntent,
|
||||||
internalBrowser,
|
appSettingsService.isInternalBrowserEnabled(),
|
||||||
articleViewer,
|
appSettingsService.isArticleViewerEnabled(),
|
||||||
app
|
app
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import bou.amine.apps.readerforselfossv2.android.R
|
|||||||
import bou.amine.apps.readerforselfossv2.android.themes.AppColors
|
import bou.amine.apps.readerforselfossv2.android.themes.AppColors
|
||||||
import bou.amine.apps.readerforselfossv2.repository.Repository
|
import bou.amine.apps.readerforselfossv2.repository.Repository
|
||||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||||
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
import bou.amine.apps.readerforselfossv2.utils.ItemType
|
import bou.amine.apps.readerforselfossv2.utils.ItemType
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
@ -18,6 +19,7 @@ import org.kodein.di.DIAware
|
|||||||
abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapter<VH>(), DIAware {
|
abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapter<VH>(), DIAware {
|
||||||
abstract var items: ArrayList<SelfossModel.Item>
|
abstract var items: ArrayList<SelfossModel.Item>
|
||||||
abstract val repository: Repository
|
abstract val repository: Repository
|
||||||
|
abstract val appSettingsService: AppSettingsService
|
||||||
abstract val app: Activity
|
abstract val app: Activity
|
||||||
abstract val appColors: AppColors
|
abstract val appColors: AppColors
|
||||||
abstract val updateItems: (ArrayList<SelfossModel.Item>) -> Unit
|
abstract val updateItems: (ArrayList<SelfossModel.Item>) -> Unit
|
||||||
@ -92,8 +94,6 @@ abstract class ItemsAdapter<VH : RecyclerView.ViewHolder?> : RecyclerView.Adapte
|
|||||||
private fun unreadItemAtIndex(position: Int, showSnackbar: Boolean = true) {
|
private fun unreadItemAtIndex(position: Int, showSnackbar: Boolean = true) {
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
repository.unmarkAsRead(items[position])
|
repository.unmarkAsRead(items[position])
|
||||||
// Todo: SharedItems.unreadItem(app, api, db, items[position])
|
|
||||||
// TODO: update db
|
|
||||||
|
|
||||||
}
|
}
|
||||||
notifyItemChanged(position)
|
notifyItemChanged(position)
|
||||||
|
@ -17,7 +17,7 @@ import bou.amine.apps.readerforselfossv2.android.model.preloadImages
|
|||||||
import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAccessible
|
import bou.amine.apps.readerforselfossv2.android.utils.network.isNetworkAccessible
|
||||||
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.ApiDetailsService
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
import com.russhwolf.settings.Settings
|
import com.russhwolf.settings.Settings
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@ -31,33 +31,32 @@ class LoadingWorker(val context: Context, params: WorkerParameters) : Worker(con
|
|||||||
|
|
||||||
override val di by lazy { (applicationContext as MyApp).di }
|
override val di by lazy { (applicationContext as MyApp).di }
|
||||||
private val repository : Repository by instance()
|
private val repository : Repository by instance()
|
||||||
|
private val appSettingsService : AppSettingsService by instance()
|
||||||
|
|
||||||
override fun doWork(): Result {
|
override fun doWork(): Result {
|
||||||
val settings = Settings()
|
if (appSettingsService.isPeriodicRefreshEnabled() && isNetworkAccessible(context)) {
|
||||||
val periodicRefresh = settings.getBoolean("periodic_refresh", false)
|
|
||||||
if (periodicRefresh && isNetworkAccessible(context)) {
|
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
val notificationManager =
|
val notificationManager =
|
||||||
applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
|
|
||||||
val notification =
|
val notification =
|
||||||
NotificationCompat.Builder(applicationContext, ApiDetailsService.syncChannelId)
|
NotificationCompat.Builder(applicationContext, AppSettingsService.syncChannelId)
|
||||||
.setContentTitle(context.getString(R.string.loading_notification_title))
|
.setContentTitle(context.getString(R.string.loading_notification_title))
|
||||||
.setContentText(context.getString(R.string.loading_notification_text))
|
.setContentText(context.getString(R.string.loading_notification_text))
|
||||||
.setOngoing(true)
|
.setOngoing(true)
|
||||||
.setPriority(PRIORITY_LOW)
|
.setPriority(PRIORITY_LOW)
|
||||||
.setChannelId(ApiDetailsService.syncChannelId)
|
.setChannelId(AppSettingsService.syncChannelId)
|
||||||
.setSmallIcon(R.drawable.ic_stat_cloud_download_black_24dp)
|
.setSmallIcon(R.drawable.ic_stat_cloud_download_black_24dp)
|
||||||
|
|
||||||
notificationManager.notify(1, notification.build())
|
notificationManager.notify(1, notification.build())
|
||||||
|
|
||||||
val notifyNewItems = settings.getBoolean("notify_new_items", false)
|
|
||||||
|
|
||||||
repository.handleDBActions()
|
repository.handleDBActions()
|
||||||
|
|
||||||
|
if (appSettingsService.isNotifyNewItemsEnabled()) {
|
||||||
launch {
|
launch {
|
||||||
handleNewItemsNotification(repository.tryToCacheItemsAndGetNewOnes(), notifyNewItems, notificationManager)
|
handleNewItemsNotification(repository.tryToCacheItemsAndGetNewOnes(), notificationManager)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,7 +65,6 @@ override fun doWork(): Result {
|
|||||||
|
|
||||||
private fun handleNewItemsNotification(
|
private fun handleNewItemsNotification(
|
||||||
newItems: List<SelfossModel.Item>?,
|
newItems: List<SelfossModel.Item>?,
|
||||||
notifyNewItems: Boolean,
|
|
||||||
notificationManager: NotificationManager
|
notificationManager: NotificationManager
|
||||||
) {
|
) {
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
@ -74,7 +72,7 @@ override fun doWork(): Result {
|
|||||||
|
|
||||||
|
|
||||||
val newSize = apiItems.filter { it.unread }.size
|
val newSize = apiItems.filter { it.unread }.size
|
||||||
if (notifyNewItems && newSize > 0) {
|
if (newSize > 0) {
|
||||||
|
|
||||||
val intent = Intent(context, MainActivity::class.java).apply {
|
val intent = Intent(context, MainActivity::class.java).apply {
|
||||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||||
@ -87,7 +85,7 @@ override fun doWork(): Result {
|
|||||||
val pendingIntent: PendingIntent = PendingIntent.getActivity(context, 0, intent, pflags)
|
val pendingIntent: PendingIntent = PendingIntent.getActivity(context, 0, intent, pflags)
|
||||||
|
|
||||||
val newItemsNotification =
|
val newItemsNotification =
|
||||||
NotificationCompat.Builder(applicationContext, ApiDetailsService.newItemsChannelId)
|
NotificationCompat.Builder(applicationContext, AppSettingsService.newItemsChannelId)
|
||||||
.setContentTitle(context.getString(R.string.new_items_notification_title))
|
.setContentTitle(context.getString(R.string.new_items_notification_title))
|
||||||
.setContentText(
|
.setContentText(
|
||||||
context.getString(
|
context.getString(
|
||||||
@ -96,7 +94,7 @@ override fun doWork(): Result {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
.setPriority(PRIORITY_DEFAULT)
|
.setPriority(PRIORITY_DEFAULT)
|
||||||
.setChannelId(ApiDetailsService.newItemsChannelId)
|
.setChannelId(AppSettingsService.newItemsChannelId)
|
||||||
.setContentIntent(pendingIntent)
|
.setContentIntent(pendingIntent)
|
||||||
.setAutoCancel(true)
|
.setAutoCancel(true)
|
||||||
.setSmallIcon(R.drawable.ic_tab_fiber_new_black_24dp)
|
.setSmallIcon(R.drawable.ic_tab_fiber_new_black_24dp)
|
||||||
|
@ -31,6 +31,7 @@ import bou.amine.apps.readerforselfossv2.android.utils.customtabs.CustomTabActiv
|
|||||||
import bou.amine.apps.readerforselfossv2.android.utils.glide.getBitmapInputStream
|
import bou.amine.apps.readerforselfossv2.android.utils.glide.getBitmapInputStream
|
||||||
import bou.amine.apps.readerforselfossv2.repository.Repository
|
import bou.amine.apps.readerforselfossv2.repository.Repository
|
||||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||||
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded
|
import bou.amine.apps.readerforselfossv2.utils.getHtmlDecoded
|
||||||
import bou.amine.apps.readerforselfossv2.utils.getImages
|
import bou.amine.apps.readerforselfossv2.utils.getImages
|
||||||
import bou.amine.apps.readerforselfossv2.utils.getThumbnail
|
import bou.amine.apps.readerforselfossv2.utils.getThumbnail
|
||||||
@ -74,8 +75,7 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
|
|
||||||
override val di : DI by closestDI()
|
override val di : DI by closestDI()
|
||||||
private val repository: Repository by instance()
|
private val repository: Repository by instance()
|
||||||
|
private val appSettingsService: AppSettingsService by instance()
|
||||||
private var settings = Settings()
|
|
||||||
|
|
||||||
private var typeface: Typeface? = null
|
private var typeface: Typeface? = null
|
||||||
private var resId: Int = 0
|
private var resId: Int = 0
|
||||||
@ -114,10 +114,10 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
contentSource = item.sourceAndDateText(repository.dateUtils)
|
contentSource = item.sourceAndDateText(repository.dateUtils)
|
||||||
allImages = item.getImages()
|
allImages = item.getImages()
|
||||||
|
|
||||||
fontSize = settings.getString("reader_font_size", "16").toInt()
|
fontSize = appSettingsService.getFontSize()
|
||||||
staticBar = settings.getBoolean("reader_static_bar", false)
|
staticBar = appSettingsService.isStaticBarEnabled()
|
||||||
|
font = appSettingsService.getFont()
|
||||||
|
|
||||||
font = settings.getString("reader_font", "")
|
|
||||||
if (font.isNotEmpty()) {
|
if (font.isNotEmpty()) {
|
||||||
resId = requireContext().resources.getIdentifier(font, "font", requireContext().packageName)
|
resId = requireContext().resources.getIdentifier(font, "font", requireContext().packageName)
|
||||||
typeface = try {
|
typeface = try {
|
||||||
@ -239,7 +239,7 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
.setTitle(requireContext().getString(R.string.webview_dialog_issue_title))
|
.setTitle(requireContext().getString(R.string.webview_dialog_issue_title))
|
||||||
.setPositiveButton(android.R.string.ok
|
.setPositiveButton(android.R.string.ok
|
||||||
) { _, _ ->
|
) { _, _ ->
|
||||||
settings.putBoolean("prefer_article_viewer", false)
|
appSettingsService.disableArticleViewer()
|
||||||
requireActivity().finish()
|
requireActivity().finish()
|
||||||
}
|
}
|
||||||
.create()
|
.create()
|
||||||
@ -255,7 +255,7 @@ class ArticleFragment : Fragment(), DIAware {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun refreshAlignment() {
|
private fun refreshAlignment() {
|
||||||
textAlignment = when (settings.getInt("text_align", 1)) {
|
textAlignment = when (appSettingsService.getActiveAllignment()) {
|
||||||
1 -> "justify"
|
1 -> "justify"
|
||||||
2 -> "left"
|
2 -> "left"
|
||||||
else -> "justify"
|
else -> "justify"
|
||||||
|
@ -14,8 +14,9 @@ import androidx.preference.Preference
|
|||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import bou.amine.apps.readerforselfossv2.android.R
|
import bou.amine.apps.readerforselfossv2.android.R
|
||||||
import bou.amine.apps.readerforselfossv2.android.databinding.ActivitySettingsBinding
|
import bou.amine.apps.readerforselfossv2.android.databinding.ActivitySettingsBinding
|
||||||
|
import bou.amine.apps.readerforselfossv2.android.themes.AppColors
|
||||||
import bou.amine.apps.readerforselfossv2.android.themes.Toppings
|
import bou.amine.apps.readerforselfossv2.android.themes.Toppings
|
||||||
import bou.amine.apps.readerforselfossv2.service.ApiDetailsService
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
import com.ftinc.scoop.Scoop
|
import com.ftinc.scoop.Scoop
|
||||||
import com.russhwolf.settings.Settings
|
import com.russhwolf.settings.Settings
|
||||||
import java.lang.NumberFormatException
|
import java.lang.NumberFormatException
|
||||||
@ -174,12 +175,7 @@ class SettingsActivity : AppCompatActivity(),
|
|||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
val id = item.itemId
|
val id = item.itemId
|
||||||
if (id == R.id.clear) {
|
if (id == R.id.clear) {
|
||||||
val settings = Settings()
|
AppColors.resetColors()
|
||||||
settings.remove("color_primary")
|
|
||||||
settings.remove("color_primary_dark")
|
|
||||||
settings.remove("color_accent")
|
|
||||||
settings.remove("color_accent_dark")
|
|
||||||
settings.remove("dark_theme")
|
|
||||||
requireActivity().recreate()
|
requireActivity().recreate()
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item)
|
return super.onOptionsItemSelected(item)
|
||||||
@ -196,17 +192,17 @@ class SettingsActivity : AppCompatActivity(),
|
|||||||
setPreferencesFromResource(R.xml.pref_links, rootKey)
|
setPreferencesFromResource(R.xml.pref_links, rootKey)
|
||||||
|
|
||||||
preferenceManager.findPreference<Preference>("trackerLink")?.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
preferenceManager.findPreference<Preference>("trackerLink")?.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||||
openUrl(Uri.parse(ApiDetailsService.trackerUrl))
|
openUrl(Uri.parse(AppSettingsService.trackerUrl))
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
preferenceManager.findPreference<Preference>("sourceLink")?.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
preferenceManager.findPreference<Preference>("sourceLink")?.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||||
openUrl(Uri.parse(ApiDetailsService.sourceUrl))
|
openUrl(Uri.parse(AppSettingsService.sourceUrl))
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
preferenceManager.findPreference<Preference>("translation")?.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
preferenceManager.findPreference<Preference>("translation")?.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||||
openUrl(Uri.parse(ApiDetailsService.translationUrl))
|
openUrl(Uri.parse(AppSettingsService.translationUrl))
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,4 +58,15 @@ class AppColors(a: Activity) {
|
|||||||
a.resources.getColor(R.color.grey_900)
|
a.resources.getColor(R.color.grey_900)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun resetColors() {
|
||||||
|
val settings = Settings()
|
||||||
|
settings.remove("color_primary")
|
||||||
|
settings.remove("color_primary_dark")
|
||||||
|
settings.remove("color_accent")
|
||||||
|
settings.remove("color_accent_dark")
|
||||||
|
settings.remove("dark_theme")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
package bou.amine.apps.readerforselfossv2.android.utils.glide
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import bou.amine.apps.readerforselfossv2.android.utils.getUnsafeHttpClient
|
|
||||||
import com.bumptech.glide.Glide
|
|
||||||
import com.bumptech.glide.GlideBuilder
|
|
||||||
import com.bumptech.glide.Registry
|
|
||||||
import com.bumptech.glide.load.model.GlideUrl
|
|
||||||
import com.bumptech.glide.module.GlideModule
|
|
||||||
import com.russhwolf.settings.Settings
|
|
||||||
import java.io.InputStream
|
|
||||||
|
|
||||||
class SelfSignedGlideModule : GlideModule {
|
|
||||||
|
|
||||||
override fun applyOptions(context: Context?, builder: GlideBuilder?) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun registerComponents(context: Context?, glide: Glide?, registry: Registry?) {
|
|
||||||
|
|
||||||
if (context != null) {
|
|
||||||
val settings = Settings()
|
|
||||||
if (settings.getBoolean("isSelfSignedCert", false)) {
|
|
||||||
val client = getUnsafeHttpClient().build()
|
|
||||||
|
|
||||||
registry?.append(
|
|
||||||
GlideUrl::class.java,
|
|
||||||
InputStream::class.java,
|
|
||||||
com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader.Factory(client)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,15 +1,15 @@
|
|||||||
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.ApiDetailsService
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.OffsetDateTime
|
import java.time.OffsetDateTime
|
||||||
import java.time.ZoneOffset
|
import java.time.ZoneOffset
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
actual class DateUtils actual constructor(apiDetailsService: ApiDetailsService) {
|
actual class DateUtils actual constructor(appSettingsService: AppSettingsService) {
|
||||||
val ads: ApiDetailsService = apiDetailsService // TODO: why is this needed now ?
|
val ads: AppSettingsService = appSettingsService // TODO: why is this needed now ?
|
||||||
|
|
||||||
actual fun parseDate(dateString: String): Long {
|
actual fun parseDate(dateString: String): Long {
|
||||||
|
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
package bou.amine.apps.readerforselfossv2.DI
|
package bou.amine.apps.readerforselfossv2.DI
|
||||||
|
|
||||||
import bou.amine.apps.readerforselfossv2.rest.SelfossApi
|
import bou.amine.apps.readerforselfossv2.rest.SelfossApi
|
||||||
import bou.amine.apps.readerforselfossv2.service.ApiDetailsService
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
import org.kodein.di.DI
|
import org.kodein.di.DI
|
||||||
import org.kodein.di.bind
|
import org.kodein.di.bind
|
||||||
import org.kodein.di.instance
|
import org.kodein.di.instance
|
||||||
import org.kodein.di.singleton
|
import org.kodein.di.singleton
|
||||||
|
|
||||||
val networkModule by DI.Module {
|
val networkModule by DI.Module {
|
||||||
bind<ApiDetailsService>() with singleton { ApiDetailsService() }
|
bind<AppSettingsService>() with singleton { AppSettingsService() }
|
||||||
bind<SelfossApi>() with singleton { SelfossApi(instance()) }
|
bind<SelfossApi>() with singleton { SelfossApi(instance()) }
|
||||||
}
|
}
|
@ -4,7 +4,7 @@ import bou.amine.apps.readerforselfossv2.dao.*
|
|||||||
import bou.amine.apps.readerforselfossv2.model.NetworkUnavailableException
|
import bou.amine.apps.readerforselfossv2.model.NetworkUnavailableException
|
||||||
import bou.amine.apps.readerforselfossv2.rest.SelfossApi
|
import bou.amine.apps.readerforselfossv2.rest.SelfossApi
|
||||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||||
import bou.amine.apps.readerforselfossv2.service.ApiDetailsService
|
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 com.github.ln_12.library.ConnectivityStatus
|
||||||
import com.russhwolf.settings.Settings
|
import com.russhwolf.settings.Settings
|
||||||
@ -13,14 +13,13 @@ import kotlinx.coroutines.CoroutineScope
|
|||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class Repository(private val api: SelfossApi, private val apiDetails: ApiDetailsService, private val connectivityStatus: ConnectivityStatus, private val db: ReaderForSelfossDB) {
|
class Repository(private val api: SelfossApi, private val appSettingsService: AppSettingsService, connectivityStatus: ConnectivityStatus, private val db: ReaderForSelfossDB) {
|
||||||
val settings = Settings()
|
|
||||||
|
|
||||||
var items = ArrayList<SelfossModel.Item>()
|
var items = ArrayList<SelfossModel.Item>()
|
||||||
val isConnectionAvailable = connectivityStatus.isNetworkConnected
|
val isConnectionAvailable = connectivityStatus.isNetworkConnected
|
||||||
var connectionMonitored = false
|
var connectionMonitored = false
|
||||||
|
|
||||||
var baseUrl = apiDetails.getBaseUrl()
|
var baseUrl = appSettingsService.getBaseUrl()
|
||||||
lateinit var dateUtils: DateUtils
|
lateinit var dateUtils: DateUtils
|
||||||
|
|
||||||
var displayedItems = ItemType.UNREAD
|
var displayedItems = ItemType.UNREAD
|
||||||
@ -29,7 +28,6 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
|
|||||||
var sourceFilter: SelfossModel.Source? = null
|
var sourceFilter: SelfossModel.Source? = null
|
||||||
var searchFilter: String? = null
|
var searchFilter: String? = null
|
||||||
|
|
||||||
var itemsCaching = settings.getBoolean("items_caching", false)
|
|
||||||
var offlineOverride = false
|
var offlineOverride = false
|
||||||
|
|
||||||
var badgeUnread = 0
|
var badgeUnread = 0
|
||||||
@ -43,7 +41,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
|
|||||||
// TODO: Dispatchers.IO not available in KMM, an alternative solution should be found
|
// TODO: Dispatchers.IO not available in KMM, an alternative solution should be found
|
||||||
CoroutineScope(Dispatchers.Main).launch {
|
CoroutineScope(Dispatchers.Main).launch {
|
||||||
updateApiVersion()
|
updateApiVersion()
|
||||||
dateUtils = DateUtils(apiDetails)
|
dateUtils = DateUtils(appSettingsService)
|
||||||
reloadBadges()
|
reloadBadges()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -61,7 +59,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
|
|||||||
null
|
null
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
if (itemsCaching) {
|
if (appSettingsService.isItemCachingEnabled()) {
|
||||||
fetchedItems = getDBItems().filter {
|
fetchedItems = getDBItems().filter {
|
||||||
displayedItems == ItemType.ALL ||
|
displayedItems == ItemType.ALL ||
|
||||||
(it.unread && displayedItems == ItemType.UNREAD) ||
|
(it.unread && displayedItems == ItemType.UNREAD) ||
|
||||||
@ -98,7 +96,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
|
|||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getMaxItemsForBackground(itemType: ItemType): List<SelfossModel.Item>? {
|
private suspend fun getMaxItemsForBackground(itemType: ItemType): List<SelfossModel.Item>? {
|
||||||
return if (isNetworkAvailable()) {
|
return if (isNetworkAvailable()) {
|
||||||
api.getItems(
|
api.getItems(
|
||||||
itemType.type,
|
itemType.type,
|
||||||
@ -172,7 +170,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
|
|||||||
return success
|
return success
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun markAsReadById(id: Int): Boolean {
|
private suspend fun markAsReadById(id: Int): Boolean {
|
||||||
return if (isNetworkAvailable()) {
|
return if (isNetworkAvailable()) {
|
||||||
api.markAsRead(id.toString())?.isSuccess == true
|
api.markAsRead(id.toString())?.isSuccess == true
|
||||||
} else {
|
} else {
|
||||||
@ -191,7 +189,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
|
|||||||
return success
|
return success
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun unmarkAsReadById(id: Int): Boolean {
|
private suspend fun unmarkAsReadById(id: Int): Boolean {
|
||||||
return if (isNetworkAvailable()) {
|
return if (isNetworkAvailable()) {
|
||||||
api.unmarkAsRead(id.toString())?.isSuccess == true
|
api.unmarkAsRead(id.toString())?.isSuccess == true
|
||||||
} else {
|
} else {
|
||||||
@ -209,7 +207,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
|
|||||||
return success
|
return success
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun starrById(id: Int): Boolean {
|
private suspend fun starrById(id: Int): Boolean {
|
||||||
return if (isNetworkAvailable()) {
|
return if (isNetworkAvailable()) {
|
||||||
api.starr(id.toString())?.isSuccess == true
|
api.starr(id.toString())?.isSuccess == true
|
||||||
} else {
|
} else {
|
||||||
@ -227,7 +225,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
|
|||||||
return success
|
return success
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun unstarrById(id: Int): Boolean {
|
private suspend fun unstarrById(id: Int): Boolean {
|
||||||
return if (isNetworkAvailable()) {
|
return if (isNetworkAvailable()) {
|
||||||
api.unstarr(id.toString())?.isSuccess == true
|
api.unstarr(id.toString())?.isSuccess == true
|
||||||
} else {
|
} else {
|
||||||
@ -307,7 +305,7 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
|
|||||||
spout,
|
spout,
|
||||||
tags,
|
tags,
|
||||||
filter,
|
filter,
|
||||||
apiDetails.getApiVersion()
|
appSettingsService.getApiVersion()
|
||||||
)?.isSuccess == true
|
)?.isSuccess == true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,27 +348,19 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun refreshLoginInformation(url: String, login: String, password: String,
|
fun refreshLoginInformation(url: String, login: String, password: String, isSelfSignedCert: Boolean) {
|
||||||
httpLogin: String, httpPassword: String,
|
appSettingsService.refreshLoginInformation(url, login, password, isSelfSignedCert)
|
||||||
isSelfSignedCert: Boolean) {
|
|
||||||
settings.putString("url", url)
|
|
||||||
settings.putString("login", login)
|
|
||||||
settings.putString("httpUserName", httpLogin)
|
|
||||||
settings.putString("password", password)
|
|
||||||
settings.putString("httpPassword", httpPassword)
|
|
||||||
settings.putBoolean("isSelfSignedCert", isSelfSignedCert)
|
|
||||||
baseUrl = url
|
baseUrl = url
|
||||||
api.refreshLoginInformation()
|
api.refreshLoginInformation()
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun updateApiVersion() {
|
private suspend fun updateApiVersion() {
|
||||||
val apiMajorVersion = apiDetails.getApiVersion()
|
val apiMajorVersion = appSettingsService.getApiVersion()
|
||||||
|
|
||||||
if (isNetworkAvailable()) {
|
if (isNetworkAvailable()) {
|
||||||
val fetchedVersion = api.version()
|
val fetchedVersion = api.version()
|
||||||
if (fetchedVersion != null && fetchedVersion.getApiMajorVersion() != apiMajorVersion) {
|
if (fetchedVersion != null && fetchedVersion.getApiMajorVersion() != apiMajorVersion) {
|
||||||
settings.putInt("apiVersionMajor", fetchedVersion.getApiMajorVersion())
|
appSettingsService.updateApiVersion(fetchedVersion.getApiMajorVersion())
|
||||||
apiDetails.refreshApiVersion()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dateUtils = DateUtils(apiMajorVersion)
|
dateUtils = DateUtils(apiMajorVersion)
|
||||||
@ -378,10 +368,10 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
|
|||||||
|
|
||||||
fun isNetworkAvailable() = isConnectionAvailable.value && !offlineOverride
|
fun isNetworkAvailable() = isConnectionAvailable.value && !offlineOverride
|
||||||
|
|
||||||
fun getDBActions(): List<ACTION> =
|
private fun getDBActions(): List<ACTION> =
|
||||||
db.actionsQueries.actions().executeAsList()
|
db.actionsQueries.actions().executeAsList()
|
||||||
|
|
||||||
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()
|
fun getDBTags(): List<TAG> = db.tagsQueries.tags().executeAsList()
|
||||||
@ -432,7 +422,9 @@ class Repository(private val api: SelfossApi, private val apiDetails: ApiDetails
|
|||||||
val starredItems = getMaxItemsForBackground(ItemType.STARRED)
|
val starredItems = getMaxItemsForBackground(ItemType.STARRED)
|
||||||
insertDBItems(newItems.orEmpty() + allItems.orEmpty() + starredItems.orEmpty())
|
insertDBItems(newItems.orEmpty() + allItems.orEmpty() + starredItems.orEmpty())
|
||||||
return newItems
|
return newItems
|
||||||
} catch (e: Throwable) {}
|
} catch (e: Throwable) {
|
||||||
|
// We do nothing
|
||||||
|
}
|
||||||
return emptyList()
|
return emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package bou.amine.apps.readerforselfossv2.rest
|
package bou.amine.apps.readerforselfossv2.rest
|
||||||
|
|
||||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||||
import bou.amine.apps.readerforselfossv2.service.ApiDetailsService
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
import io.ktor.client.*
|
import io.ktor.client.*
|
||||||
import io.ktor.client.call.*
|
import io.ktor.client.call.*
|
||||||
import io.ktor.client.plugins.*
|
import io.ktor.client.plugins.*
|
||||||
@ -14,7 +14,7 @@ import io.ktor.client.plugins.logging.*
|
|||||||
import io.ktor.serialization.kotlinx.json.*
|
import io.ktor.serialization.kotlinx.json.*
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
class SelfossApi(private val apiDetailsService: ApiDetailsService) {
|
class SelfossApi(private val appSettingsService: AppSettingsService) {
|
||||||
|
|
||||||
var client = createHttpClient()
|
var client = createHttpClient()
|
||||||
|
|
||||||
@ -31,13 +31,13 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) {
|
|||||||
install(Logging) {
|
install(Logging) {
|
||||||
logger = object : Logger {
|
logger = object : Logger {
|
||||||
override fun log(message: String) {
|
override fun log(message: String) {
|
||||||
apiDetailsService.logApiCalls(message)
|
appSettingsService.logApiCalls(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
level = LogLevel.ALL
|
level = LogLevel.ALL
|
||||||
}
|
}
|
||||||
install(HttpTimeout) {
|
install(HttpTimeout) {
|
||||||
requestTimeoutMillis = apiDetailsService.getApiTimeout()
|
requestTimeoutMillis = appSettingsService.getApiTimeout()
|
||||||
}
|
}
|
||||||
/* TODO: Auth as basic
|
/* TODO: Auth as basic
|
||||||
if (apiDetailsService.getUserName().isNotEmpty() && apiDetailsService.getPassword().isNotEmpty()) {
|
if (apiDetailsService.getUserName().isNotEmpty() && apiDetailsService.getPassword().isNotEmpty()) {
|
||||||
@ -58,17 +58,17 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun url(path: String) =
|
fun url(path: String) =
|
||||||
"${apiDetailsService.getBaseUrl()}$path"
|
"${appSettingsService.getBaseUrl()}$path"
|
||||||
|
|
||||||
fun refreshLoginInformation() {
|
fun refreshLoginInformation() {
|
||||||
apiDetailsService.refresh()
|
appSettingsService.refreshApiSettings()
|
||||||
client = createHttpClient()
|
client = createHttpClient()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun login(): SelfossModel.SuccessResponse? =
|
suspend fun login(): SelfossModel.SuccessResponse? =
|
||||||
client.get(url("/login")) {
|
client.get(url("/login")) {
|
||||||
parameter("username", apiDetailsService.getUserName())
|
parameter("username", appSettingsService.getUserName())
|
||||||
parameter("password", apiDetailsService.getPassword())
|
parameter("password", appSettingsService.getPassword())
|
||||||
}.body()
|
}.body()
|
||||||
|
|
||||||
suspend fun getItems(
|
suspend fun getItems(
|
||||||
@ -81,45 +81,45 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) {
|
|||||||
items: Int? = null
|
items: Int? = null
|
||||||
): List<SelfossModel.Item>? =
|
): List<SelfossModel.Item>? =
|
||||||
client.get(url("/items")) {
|
client.get(url("/items")) {
|
||||||
parameter("username", apiDetailsService.getUserName())
|
parameter("username", appSettingsService.getUserName())
|
||||||
parameter("password", apiDetailsService.getPassword())
|
parameter("password", appSettingsService.getPassword())
|
||||||
parameter("type", type)
|
parameter("type", type)
|
||||||
parameter("tag", tag)
|
parameter("tag", tag)
|
||||||
parameter("source", source)
|
parameter("source", source)
|
||||||
parameter("search", search)
|
parameter("search", search)
|
||||||
parameter("updatedsince", updatedSince)
|
parameter("updatedsince", updatedSince)
|
||||||
parameter("items", items ?: apiDetailsService.getItemsNumber())
|
parameter("items", items ?: appSettingsService.getItemsNumber())
|
||||||
parameter("offset", offset)
|
parameter("offset", offset)
|
||||||
}.body()
|
}.body()
|
||||||
|
|
||||||
suspend fun stats(): SelfossModel.Stats? =
|
suspend fun stats(): SelfossModel.Stats? =
|
||||||
client.get(url("/stats")) {
|
client.get(url("/stats")) {
|
||||||
parameter("username", apiDetailsService.getUserName())
|
parameter("username", appSettingsService.getUserName())
|
||||||
parameter("password", apiDetailsService.getPassword())
|
parameter("password", appSettingsService.getPassword())
|
||||||
}.body()
|
}.body()
|
||||||
|
|
||||||
suspend fun tags(): List<SelfossModel.Tag>? =
|
suspend fun tags(): List<SelfossModel.Tag>? =
|
||||||
client.get(url("/tags")) {
|
client.get(url("/tags")) {
|
||||||
parameter("username", apiDetailsService.getUserName())
|
parameter("username", appSettingsService.getUserName())
|
||||||
parameter("password", apiDetailsService.getPassword())
|
parameter("password", appSettingsService.getPassword())
|
||||||
}.body()
|
}.body()
|
||||||
|
|
||||||
suspend fun update(): String? =
|
suspend fun update(): String? =
|
||||||
client.get(url("/update")) {
|
client.get(url("/update")) {
|
||||||
parameter("username", apiDetailsService.getUserName())
|
parameter("username", appSettingsService.getUserName())
|
||||||
parameter("password", apiDetailsService.getPassword())
|
parameter("password", appSettingsService.getPassword())
|
||||||
}.body()
|
}.body()
|
||||||
|
|
||||||
suspend fun spouts(): Map<String, SelfossModel.Spout>? =
|
suspend fun spouts(): Map<String, SelfossModel.Spout>? =
|
||||||
client.get(url("/sources/spouts")) {
|
client.get(url("/sources/spouts")) {
|
||||||
parameter("username", apiDetailsService.getUserName())
|
parameter("username", appSettingsService.getUserName())
|
||||||
parameter("password", apiDetailsService.getPassword())
|
parameter("password", appSettingsService.getPassword())
|
||||||
}.body()
|
}.body()
|
||||||
|
|
||||||
suspend fun sources(): ArrayList<SelfossModel.Source>? =
|
suspend fun sources(): ArrayList<SelfossModel.Source>? =
|
||||||
client.get(url("/sources/list")) {
|
client.get(url("/sources/list")) {
|
||||||
parameter("username", apiDetailsService.getUserName())
|
parameter("username", appSettingsService.getUserName())
|
||||||
parameter("password", apiDetailsService.getPassword())
|
parameter("password", appSettingsService.getPassword())
|
||||||
}.body()
|
}.body()
|
||||||
|
|
||||||
suspend fun version(): SelfossModel.ApiVersion? =
|
suspend fun version(): SelfossModel.ApiVersion? =
|
||||||
@ -127,34 +127,34 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) {
|
|||||||
|
|
||||||
suspend fun markAsRead(id: String): SelfossModel.SuccessResponse? =
|
suspend fun markAsRead(id: String): SelfossModel.SuccessResponse? =
|
||||||
client.post(url("/mark/$id")) {
|
client.post(url("/mark/$id")) {
|
||||||
parameter("username", apiDetailsService.getUserName())
|
parameter("username", appSettingsService.getUserName())
|
||||||
parameter("password", apiDetailsService.getPassword())
|
parameter("password", appSettingsService.getPassword())
|
||||||
}.body()
|
}.body()
|
||||||
|
|
||||||
suspend fun unmarkAsRead(id: String): SelfossModel.SuccessResponse? =
|
suspend fun unmarkAsRead(id: String): SelfossModel.SuccessResponse? =
|
||||||
client.post(url("/unmark/$id")) {
|
client.post(url("/unmark/$id")) {
|
||||||
parameter("username", apiDetailsService.getUserName())
|
parameter("username", appSettingsService.getUserName())
|
||||||
parameter("password", apiDetailsService.getPassword())
|
parameter("password", appSettingsService.getPassword())
|
||||||
}.body()
|
}.body()
|
||||||
|
|
||||||
suspend fun starr(id: String): SelfossModel.SuccessResponse? =
|
suspend fun starr(id: String): SelfossModel.SuccessResponse? =
|
||||||
client.post(url("/starr/$id")) {
|
client.post(url("/starr/$id")) {
|
||||||
parameter("username", apiDetailsService.getUserName())
|
parameter("username", appSettingsService.getUserName())
|
||||||
parameter("password", apiDetailsService.getPassword())
|
parameter("password", appSettingsService.getPassword())
|
||||||
}.body()
|
}.body()
|
||||||
|
|
||||||
suspend fun unstarr(id: String): SelfossModel.SuccessResponse? =
|
suspend fun unstarr(id: String): SelfossModel.SuccessResponse? =
|
||||||
client.post(url("/unstarr/$id")) {
|
client.post(url("/unstarr/$id")) {
|
||||||
parameter("username", apiDetailsService.getUserName())
|
parameter("username", appSettingsService.getUserName())
|
||||||
parameter("password", apiDetailsService.getPassword())
|
parameter("password", appSettingsService.getPassword())
|
||||||
}.body()
|
}.body()
|
||||||
|
|
||||||
suspend fun markAllAsRead(ids: List<String>): SelfossModel.SuccessResponse? =
|
suspend fun markAllAsRead(ids: List<String>): SelfossModel.SuccessResponse? =
|
||||||
client.submitForm(
|
client.submitForm(
|
||||||
url = url("/mark"),
|
url = url("/mark"),
|
||||||
formParameters = Parameters.build {
|
formParameters = Parameters.build {
|
||||||
append("username", apiDetailsService.getUserName())
|
append("username", appSettingsService.getUserName())
|
||||||
append("password", apiDetailsService.getPassword())
|
append("password", appSettingsService.getPassword())
|
||||||
ids.map { append("ids[]", it) }
|
ids.map { append("ids[]", it) }
|
||||||
}
|
}
|
||||||
).body()
|
).body()
|
||||||
@ -181,7 +181,7 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) {
|
|||||||
filter: String
|
filter: String
|
||||||
): SelfossModel.SuccessResponse? =
|
): SelfossModel.SuccessResponse? =
|
||||||
client.submitForm(
|
client.submitForm(
|
||||||
url = url("/source?username=${apiDetailsService.getUserName()}&password=${apiDetailsService.getPassword()}"),
|
url = url("/source?username=${appSettingsService.getUserName()}&password=${appSettingsService.getPassword()}"),
|
||||||
formParameters = Parameters.build {
|
formParameters = Parameters.build {
|
||||||
append("title", title)
|
append("title", title)
|
||||||
append("url", url)
|
append("url", url)
|
||||||
@ -199,7 +199,7 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) {
|
|||||||
filter: String
|
filter: String
|
||||||
): SelfossModel.SuccessResponse? =
|
): SelfossModel.SuccessResponse? =
|
||||||
client.submitForm(
|
client.submitForm(
|
||||||
url = url("/source?username=${apiDetailsService.getUserName()}&password=${apiDetailsService.getPassword()}"),
|
url = url("/source?username=${appSettingsService.getUserName()}&password=${appSettingsService.getPassword()}"),
|
||||||
formParameters = Parameters.build {
|
formParameters = Parameters.build {
|
||||||
append("title", title)
|
append("title", title)
|
||||||
append("url", url)
|
append("url", url)
|
||||||
@ -211,7 +211,7 @@ class SelfossApi(private val apiDetailsService: ApiDetailsService) {
|
|||||||
|
|
||||||
suspend fun deleteSource(id: Int): SelfossModel.SuccessResponse? =
|
suspend fun deleteSource(id: Int): SelfossModel.SuccessResponse? =
|
||||||
client.delete(url("/source/$id")) {
|
client.delete(url("/source/$id")) {
|
||||||
parameter("username", apiDetailsService.getUserName())
|
parameter("username", appSettingsService.getUserName())
|
||||||
parameter("password", apiDetailsService.getPassword())
|
parameter("password", appSettingsService.getPassword())
|
||||||
}.body()
|
}.body()
|
||||||
}
|
}
|
@ -1,97 +0,0 @@
|
|||||||
package bou.amine.apps.readerforselfossv2.service
|
|
||||||
|
|
||||||
import com.russhwolf.settings.Settings
|
|
||||||
import io.github.aakira.napier.Napier
|
|
||||||
import io.ktor.client.plugins.*
|
|
||||||
|
|
||||||
class ApiDetailsService {
|
|
||||||
val settings: Settings = Settings()
|
|
||||||
private var _apiVersion: Int = -1
|
|
||||||
private var _baseUrl: String = ""
|
|
||||||
private var _userName: String = ""
|
|
||||||
private var _password: String = ""
|
|
||||||
private var _itemsNumber: Int? = null
|
|
||||||
private var _apiTimeout: Long? = null
|
|
||||||
|
|
||||||
fun logApiCalls(message: String) {
|
|
||||||
Napier.d(message, tag = "LogApiCalls")
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun getApiVersion(): Int {
|
|
||||||
if (_apiVersion == -1) {
|
|
||||||
refreshApiVersion()
|
|
||||||
return _apiVersion
|
|
||||||
}
|
|
||||||
return _apiVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
fun refreshApiVersion() {
|
|
||||||
_apiVersion = settings.getInt("apiVersionMajor", -1)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getBaseUrl(): String {
|
|
||||||
if (_baseUrl.isEmpty()) {
|
|
||||||
_baseUrl = settings.getString("url", "")
|
|
||||||
}
|
|
||||||
return _baseUrl
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getUserName(): String {
|
|
||||||
if (_userName.isEmpty()) {
|
|
||||||
_userName = settings.getString("login", "")
|
|
||||||
}
|
|
||||||
return _userName
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getPassword(): String {
|
|
||||||
if (_password.isEmpty()) {
|
|
||||||
_password = settings.getString("password", "")
|
|
||||||
}
|
|
||||||
return _password
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getItemsNumber(): Int {
|
|
||||||
if (_itemsNumber == null) {
|
|
||||||
refreshItemsNumber()
|
|
||||||
}
|
|
||||||
return _itemsNumber!!
|
|
||||||
}
|
|
||||||
|
|
||||||
fun refreshItemsNumber() {
|
|
||||||
_itemsNumber = settings.getString("prefer_api_items_number", "200").toInt()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getApiTimeout(): Long {
|
|
||||||
if (_apiTimeout == null) {
|
|
||||||
refreshApiTimeout()
|
|
||||||
}
|
|
||||||
return _apiTimeout!!
|
|
||||||
}
|
|
||||||
|
|
||||||
fun refreshApiTimeout() {
|
|
||||||
val settingsTimeout = settings.getLong("api_timeout", HttpTimeout.INFINITE_TIMEOUT_MS)
|
|
||||||
_apiTimeout = if (settingsTimeout > 0) settingsTimeout else HttpTimeout.INFINITE_TIMEOUT_MS
|
|
||||||
}
|
|
||||||
|
|
||||||
fun refresh() {
|
|
||||||
_password = settings.getString("password", "")
|
|
||||||
_userName = settings.getString("login", "")
|
|
||||||
_baseUrl = settings.getString("url", "")
|
|
||||||
refreshApiVersion()
|
|
||||||
refreshItemsNumber()
|
|
||||||
refreshApiTimeout()
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val translationUrl = "https://crwd.in/readerforselfoss"
|
|
||||||
|
|
||||||
const val sourceUrl = "https://gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform"
|
|
||||||
|
|
||||||
const val trackerUrl = "https://gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform/issues"
|
|
||||||
|
|
||||||
const val syncChannelId = "sync-channel-id"
|
|
||||||
|
|
||||||
const val newItemsChannelId = "new-items-channel-id"
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,428 @@
|
|||||||
|
package bou.amine.apps.readerforselfossv2.service
|
||||||
|
|
||||||
|
import com.russhwolf.settings.Settings
|
||||||
|
import io.github.aakira.napier.Napier
|
||||||
|
import io.ktor.client.plugins.*
|
||||||
|
|
||||||
|
class AppSettingsService {
|
||||||
|
val settings: Settings = Settings()
|
||||||
|
|
||||||
|
// Api related
|
||||||
|
private var _apiVersion: Int = -1
|
||||||
|
private var _baseUrl: String = ""
|
||||||
|
private var _userName: String = ""
|
||||||
|
private var _password: String = ""
|
||||||
|
|
||||||
|
// User settings related
|
||||||
|
private var _itemsCaching: Boolean? = null
|
||||||
|
private var _internalBrowser: Boolean? = null
|
||||||
|
private var _articleViewer: Boolean? = null
|
||||||
|
private var _shouldBeCardView: Boolean? = null
|
||||||
|
private var _displayUnreadCount: Boolean? = null
|
||||||
|
private var _displayAllCount: Boolean? = null
|
||||||
|
private var _fullHeightCards: Boolean? = null
|
||||||
|
private var _updateSources: Boolean? = null
|
||||||
|
private var _periodicRefresh: Boolean? = null
|
||||||
|
private var _refreshWhenChargingOnly: Boolean? = null
|
||||||
|
private var _infiniteLoading: Boolean? = null
|
||||||
|
private var _displayAccountHeader: Boolean? = null
|
||||||
|
private var _notifyNewItems: Boolean? = null
|
||||||
|
private var _itemsNumber: Int? = null
|
||||||
|
private var _apiTimeout: Long? = null
|
||||||
|
private var _hiddenTags: List<String>? = null
|
||||||
|
private var _refreshMinutes: Long = 360
|
||||||
|
private var _markOnScroll: Boolean? = null
|
||||||
|
private var _activeAlignment: Int? = null
|
||||||
|
|
||||||
|
private var _fontSize: Int? = null // settings.getString("reader_font_size", "16").toInt()
|
||||||
|
private var _staticBar: Boolean? = null // settings.getBoolean("reader_static_bar", false)
|
||||||
|
private var _font: String = "" // settings.getString("reader_font", "")
|
||||||
|
|
||||||
|
|
||||||
|
init {
|
||||||
|
refreshApiSettings()
|
||||||
|
refreshUserSettings()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun logApiCalls(message: String) {
|
||||||
|
Napier.d(message, tag = "LogApiCalls")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getApiVersion(): Int {
|
||||||
|
if (_apiVersion == -1) {
|
||||||
|
refreshApiVersion()
|
||||||
|
return _apiVersion
|
||||||
|
}
|
||||||
|
return _apiVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
fun refreshApiVersion() {
|
||||||
|
_apiVersion = settings.getInt("apiVersionMajor", -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getBaseUrl(): String {
|
||||||
|
if (_baseUrl.isEmpty()) {
|
||||||
|
refreshBaseUrl()
|
||||||
|
}
|
||||||
|
return _baseUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getUserName(): String {
|
||||||
|
if (_userName.isEmpty()) {
|
||||||
|
refrershUsername()
|
||||||
|
}
|
||||||
|
return _userName
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getPassword(): String {
|
||||||
|
if (_password.isEmpty()) {
|
||||||
|
refreshPassword()
|
||||||
|
}
|
||||||
|
return _password
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getItemsNumber(): Int {
|
||||||
|
if (_itemsNumber == null) {
|
||||||
|
refreshItemsNumber()
|
||||||
|
}
|
||||||
|
return _itemsNumber!!
|
||||||
|
}
|
||||||
|
|
||||||
|
fun refreshItemsNumber() {
|
||||||
|
_itemsNumber = settings.getString("prefer_api_items_number", "200").toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getApiTimeout(): Long {
|
||||||
|
if (_apiTimeout == null) {
|
||||||
|
refreshApiTimeout()
|
||||||
|
}
|
||||||
|
return _apiTimeout!!
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshApiTimeout() {
|
||||||
|
val settingsTimeout = settings.getLong("api_timeout", HttpTimeout.INFINITE_TIMEOUT_MS)
|
||||||
|
_apiTimeout = if (settingsTimeout > 0) settingsTimeout else HttpTimeout.INFINITE_TIMEOUT_MS
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshBaseUrl() {
|
||||||
|
_baseUrl = settings.getString("url", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refrershUsername() {
|
||||||
|
_userName = settings.getString("login", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshPassword() {
|
||||||
|
_password = settings.getString("password", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshInternalBrowserEnabled() {
|
||||||
|
_internalBrowser = settings.getBoolean("prefer_internal_browser", true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isInternalBrowserEnabled(): Boolean {
|
||||||
|
if (_internalBrowser != null) {
|
||||||
|
refreshInternalBrowserEnabled()
|
||||||
|
}
|
||||||
|
return _internalBrowser == true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshArticleViewerEnabled() {
|
||||||
|
_articleViewer = settings.getBoolean("prefer_article_viewer", true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isArticleViewerEnabled(): Boolean {
|
||||||
|
if (_articleViewer != null) {
|
||||||
|
refreshArticleViewerEnabled()
|
||||||
|
}
|
||||||
|
return _articleViewer == true
|
||||||
|
}
|
||||||
|
private fun refreshShouldBeCardViewEnabled() {
|
||||||
|
_shouldBeCardView = settings.getBoolean("card_view_active", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isCardViewEnabled(): Boolean {
|
||||||
|
if (_shouldBeCardView != null) {
|
||||||
|
refreshShouldBeCardViewEnabled()
|
||||||
|
}
|
||||||
|
return _shouldBeCardView == true
|
||||||
|
}
|
||||||
|
private fun refreshDisplayUnreadCountEnabled() {
|
||||||
|
_displayUnreadCount = settings.getBoolean("display_unread_count", true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isDisplayUnreadCountEnabled(): Boolean {
|
||||||
|
if (_displayUnreadCount != null) {
|
||||||
|
refreshDisplayUnreadCountEnabled()
|
||||||
|
}
|
||||||
|
return _displayUnreadCount == true
|
||||||
|
}
|
||||||
|
private fun refreshDisplayAllCountEnabled() {
|
||||||
|
_displayAllCount = settings.getBoolean("display_other_count", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isDisplayAllCountEnabled(): Boolean {
|
||||||
|
if (_displayAllCount != null) {
|
||||||
|
refreshDisplayAllCountEnabled()
|
||||||
|
}
|
||||||
|
return _displayAllCount == true
|
||||||
|
}
|
||||||
|
private fun refreshFullHeightCardsEnabled() {
|
||||||
|
_fullHeightCards = settings.getBoolean("full_height_cards", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isFullHeightCardsEnabled(): Boolean {
|
||||||
|
if (_fullHeightCards != null) {
|
||||||
|
refreshFullHeightCardsEnabled()
|
||||||
|
}
|
||||||
|
return _fullHeightCards == true
|
||||||
|
}
|
||||||
|
private fun refreshUpdateSourcesEnabled() {
|
||||||
|
_updateSources = settings.getBoolean("update_sources", true)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isUpdateSourcesEnabled(): Boolean {
|
||||||
|
if (_updateSources != null) {
|
||||||
|
refreshUpdateSourcesEnabled()
|
||||||
|
}
|
||||||
|
return _updateSources == true
|
||||||
|
}
|
||||||
|
private fun refreshPeriodicRefreshEnabled() {
|
||||||
|
_periodicRefresh = settings.getBoolean("periodic_refresh", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isPeriodicRefreshEnabled(): Boolean {
|
||||||
|
if (_periodicRefresh != null) {
|
||||||
|
refreshPeriodicRefreshEnabled()
|
||||||
|
}
|
||||||
|
return _periodicRefresh == true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshRefreshWhenChargingOnlyEnabled() {
|
||||||
|
_refreshWhenChargingOnly = settings.getBoolean("refresh_when_charging", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isRefreshWhenChargingOnlyEnabled(): Boolean {
|
||||||
|
if (_refreshWhenChargingOnly != null) {
|
||||||
|
refreshRefreshWhenChargingOnlyEnabled()
|
||||||
|
}
|
||||||
|
return _refreshWhenChargingOnly == true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshRefreshMinutes() {
|
||||||
|
_refreshMinutes = settings.getString("periodic_refresh_minutes", "360").toLong()
|
||||||
|
if (_refreshMinutes <= 15) {
|
||||||
|
_refreshMinutes = 15
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getRefreshMinutes(): Long {
|
||||||
|
if (_refreshMinutes != null) {
|
||||||
|
refreshRefreshMinutes()
|
||||||
|
}
|
||||||
|
return _refreshMinutes
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshHiddenTags() {
|
||||||
|
if (settings.getString("hidden_tags", "").isNotEmpty()) {
|
||||||
|
_hiddenTags = settings.getString("hidden_tags", "").replace("\\s".toRegex(), "").split(",")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getHiddenTags(): List<String> {
|
||||||
|
if (_hiddenTags != null) {
|
||||||
|
refreshHiddenTags()
|
||||||
|
}
|
||||||
|
return _hiddenTags.orEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshInfiniteLoadingEnabled() {
|
||||||
|
_infiniteLoading = settings.getBoolean("infinite_loading", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isInfiniteLoadingEnabled(): Boolean {
|
||||||
|
if (_infiniteLoading != null) {
|
||||||
|
refreshInfiniteLoadingEnabled()
|
||||||
|
}
|
||||||
|
return _infiniteLoading == true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshDisplayAccountHeaderEnabled() {
|
||||||
|
_displayAccountHeader = settings.getBoolean("account_header_displaying", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isDisplayAccountHeaderEnabled(): Boolean {
|
||||||
|
if (_displayAccountHeader != null) {
|
||||||
|
refreshDisplayAccountHeaderEnabled()
|
||||||
|
}
|
||||||
|
return _displayAccountHeader == true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshItemCachingEnabled() {
|
||||||
|
_itemsCaching = settings.getBoolean("items_caching", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isItemCachingEnabled(): Boolean {
|
||||||
|
if (_itemsCaching != null) {
|
||||||
|
refreshItemCachingEnabled()
|
||||||
|
}
|
||||||
|
return _itemsCaching == true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshNotifyNewItemsEnabled() {
|
||||||
|
_notifyNewItems = settings.getBoolean("notify_new_items", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isNotifyNewItemsEnabled(): Boolean {
|
||||||
|
if (_notifyNewItems != null) {
|
||||||
|
refreshNotifyNewItemsEnabled()
|
||||||
|
}
|
||||||
|
return _notifyNewItems == true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun refreshMarkOnScrollEnabled() {
|
||||||
|
_markOnScroll = settings.getBoolean("mark_on_scroll", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isMarkOnScrollEnabled(): Boolean {
|
||||||
|
if (_markOnScroll != null) {
|
||||||
|
refreshMarkOnScrollEnabled()
|
||||||
|
}
|
||||||
|
return _markOnScroll == true
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun refreshActiveAllignment() {
|
||||||
|
_activeAlignment = settings.getInt("text_align", JUSTIFY)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getActiveAllignment(): Int {
|
||||||
|
if (_activeAlignment != null) {
|
||||||
|
refreshActiveAllignment()
|
||||||
|
}
|
||||||
|
return _activeAlignment ?: JUSTIFY
|
||||||
|
}
|
||||||
|
|
||||||
|
fun changeAllignment(allignment: Int) {
|
||||||
|
settings.putInt("text_align", allignment)
|
||||||
|
_activeAlignment = allignment
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshFontSize() {
|
||||||
|
_fontSize = settings.getString("reader_font_size", "16").toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getFontSize(): Int {
|
||||||
|
if (_fontSize != null) {
|
||||||
|
refreshFontSize()
|
||||||
|
}
|
||||||
|
return _fontSize ?: 16
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshStaticBarEnabled() {
|
||||||
|
_staticBar = settings.getBoolean("reader_static_bar", false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isStaticBarEnabled(): Boolean {
|
||||||
|
if (_staticBar != null) {
|
||||||
|
refreshStaticBarEnabled()
|
||||||
|
}
|
||||||
|
return _staticBar == true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refreshFont() {
|
||||||
|
_font = settings.getString("reader_font", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getFont(): String {
|
||||||
|
if (_font != null) {
|
||||||
|
refreshFont()
|
||||||
|
}
|
||||||
|
return _font
|
||||||
|
}
|
||||||
|
|
||||||
|
fun refreshApiSettings() {
|
||||||
|
refreshPassword()
|
||||||
|
refrershUsername()
|
||||||
|
refreshBaseUrl()
|
||||||
|
refreshApiVersion()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun refreshUserSettings() {
|
||||||
|
refreshItemsNumber()
|
||||||
|
refreshApiTimeout()
|
||||||
|
refreshInternalBrowserEnabled()
|
||||||
|
refreshArticleViewerEnabled()
|
||||||
|
refreshShouldBeCardViewEnabled()
|
||||||
|
refreshDisplayUnreadCountEnabled()
|
||||||
|
refreshDisplayAllCountEnabled()
|
||||||
|
refreshFullHeightCardsEnabled()
|
||||||
|
refreshUpdateSourcesEnabled()
|
||||||
|
refreshPeriodicRefreshEnabled()
|
||||||
|
refreshRefreshWhenChargingOnlyEnabled()
|
||||||
|
refreshRefreshMinutes()
|
||||||
|
refreshHiddenTags()
|
||||||
|
refreshInfiniteLoadingEnabled()
|
||||||
|
refreshDisplayAccountHeaderEnabled()
|
||||||
|
refreshItemCachingEnabled()
|
||||||
|
refreshNotifyNewItemsEnabled()
|
||||||
|
refreshMarkOnScrollEnabled()
|
||||||
|
refreshActiveAllignment()
|
||||||
|
refreshFontSize()
|
||||||
|
refreshFont()
|
||||||
|
refreshStaticBarEnabled()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun refreshLoginInformation(
|
||||||
|
url: String,
|
||||||
|
login: String,
|
||||||
|
password: String,
|
||||||
|
selfSignedCert: Boolean
|
||||||
|
) {
|
||||||
|
settings.putString("url", url)
|
||||||
|
settings.putString("login", login)
|
||||||
|
settings.putString("password", password)
|
||||||
|
settings.putBoolean("isSelfSignedCert", selfSignedCert)
|
||||||
|
refreshApiSettings()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun resetLoginInformation() {
|
||||||
|
settings.remove("url")
|
||||||
|
settings.remove("login")
|
||||||
|
settings.remove("password")
|
||||||
|
refreshApiSettings()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateApiVersion(apiMajorVersion: Int) {
|
||||||
|
settings.putInt("apiVersionMajor", apiMajorVersion)
|
||||||
|
refreshApiVersion()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun clearAll() {
|
||||||
|
settings.clear()
|
||||||
|
refreshApiSettings()
|
||||||
|
refreshUserSettings()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun disableArticleViewer() {
|
||||||
|
settings.putBoolean("prefer_article_viewer", false)
|
||||||
|
refreshArticleViewerEnabled()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val translationUrl = "https://crwd.in/readerforselfoss"
|
||||||
|
|
||||||
|
const val sourceUrl = "https://gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform"
|
||||||
|
|
||||||
|
const val trackerUrl = "https://gitea.amine-louveau.fr/Louvorg/ReaderForSelfoss-multiplatform/issues"
|
||||||
|
|
||||||
|
const val syncChannelId = "sync-channel-id"
|
||||||
|
|
||||||
|
const val newItemsChannelId = "new-items-channel-id"
|
||||||
|
|
||||||
|
const val JUSTIFY = 1
|
||||||
|
|
||||||
|
const val ALIGN_LEFT = 2
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,13 @@
|
|||||||
package bou.amine.apps.readerforselfossv2.utils
|
package bou.amine.apps.readerforselfossv2.utils
|
||||||
|
|
||||||
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
import bou.amine.apps.readerforselfossv2.model.SelfossModel
|
||||||
import bou.amine.apps.readerforselfossv2.service.ApiDetailsService
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
|
|
||||||
|
|
||||||
fun SelfossModel.Item.parseDate(dateUtils: DateUtils): Long =
|
fun SelfossModel.Item.parseDate(dateUtils: DateUtils): Long =
|
||||||
dateUtils.parseDate(this.datetime)
|
dateUtils.parseDate(this.datetime)
|
||||||
|
|
||||||
expect class DateUtils(apiDetailsService: ApiDetailsService) {
|
expect class DateUtils(appSettingsService: AppSettingsService) {
|
||||||
fun parseDate(dateString: String): Long
|
fun parseDate(dateString: String): Long
|
||||||
|
|
||||||
fun parseRelativeDate(dateString: String): String
|
fun parseRelativeDate(dateString: String): String
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package bou.amine.apps.readerforselfossv2.utils
|
package bou.amine.apps.readerforselfossv2.utils
|
||||||
|
|
||||||
import bou.amine.apps.readerforselfossv2.service.ApiDetailsService
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
|
|
||||||
actual class DateUtils actual constructor(apiDetailsService: ApiDetailsService) {
|
actual class DateUtils actual constructor(appSettingsService: AppSettingsService) {
|
||||||
actual fun parseDate(dateString: String): Long {
|
actual fun parseDate(dateString: String): Long {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package bou.amine.apps.readerforselfossv2.utils
|
package bou.amine.apps.readerforselfossv2.utils
|
||||||
|
|
||||||
import bou.amine.apps.readerforselfossv2.service.ApiDetailsService
|
import bou.amine.apps.readerforselfossv2.service.AppSettingsService
|
||||||
|
|
||||||
actual class DateUtils actual constructor(apiDetailsService: ApiDetailsService) {
|
actual class DateUtils actual constructor(appSettingsService: AppSettingsService) {
|
||||||
actual fun parseDate(dateString: String): Long {
|
actual fun parseDate(dateString: String): Long {
|
||||||
TODO("Not yet implemented")
|
TODO("Not yet implemented")
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user