Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions app/src/main/java/com/capyreader/app/common/Connectivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.capyreader.app.common

import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities

fun Context.isOnWifi(): Boolean {
val manager = getSystemService(ConnectivityManager::class.java) ?: return false
val network = manager.activeNetwork ?: return false
val capabilities = manager.getNetworkCapabilities(network) ?: return false
return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)
}
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ class AppPreferences(context: Context) {
val enableStickyFullContent: Preference<Boolean>
get() = preferenceStore.getBoolean("enable_sticky_full_content", false)

val refreshOnWiFiOnly: Preference<Boolean>
get() = preferenceStore.getBoolean("refresh_on_wifi_only", false)

val paneExpansionIndex: Preference<Int>
get() = preferenceStore.getInt("pane_expansion_index", DefaultPaneExpansionIndex)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package com.capyreader.app.refresher

import android.content.Context
import com.capyreader.app.common.isOnWifi
import com.capyreader.app.notifications.NotificationHelper
import com.capyreader.app.preferences.AppPreferences
import com.capyreader.app.ui.widget.WidgetUpdater
import com.jocmp.capy.Account
import com.jocmp.capy.common.TimeHelpers
import com.jocmp.capy.logging.CapyLog
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.koin.core.component.KoinComponent
Expand All @@ -13,8 +16,14 @@ class FeedRefresher(
private val account: Account,
private val appContext: Context,
private val notificationHelper: NotificationHelper,
private val appPreferences: AppPreferences,
): KoinComponent {
suspend fun refresh() {
if (appPreferences.refreshOnWiFiOnly.get() && !appContext.isOnWifi()) {
CapyLog.info("refresh_skipped_mobile", mapOf("type" to "background"))
return
}

val since = TimeHelpers.nowUTC()

return withContext(Dispatchers.IO) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import org.koin.androidx.workmanager.dsl.worker
import org.koin.dsl.module

val refresherModule = module {
single { FeedRefresher(account = get(), get(), get()) }
single { FeedRefresher(account = get(), get(), get(), get()) }
single { RefreshScheduler(get(), get()) }
worker { RefreshFeedsWorker(get(), get()) }
}
13 changes: 13 additions & 0 deletions app/src/main/java/com/capyreader/app/ui/articles/ArticleScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,19 @@ fun ArticleScreen(
saver = ArticleFilter.Saver
) { mutableStateOf(null) }

LaunchedEffect(viewModel.refreshSkipReason) {
val reason = viewModel.refreshSkipReason ?: return@LaunchedEffect
val message = when (reason) {
RefreshSkipReason.Mobile -> context.getString(R.string.refresh_skipped_mobile)
}
snackbarHostState.showSnackbar(
message = message,
withDismissAction = true,
duration = SnackbarDuration.Short,
)
viewModel.clearRefreshSkipReason()
}

LaunchedEffect(filter, articles.loadState.refresh) {
val refreshComplete = articles.loadState.refresh is LoadState.NotLoading
if (refreshComplete && filter != scrolledFilter) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.PagingData
import com.capyreader.app.R
import com.capyreader.app.common.isOnWifi
import com.capyreader.app.common.toast
import com.capyreader.app.notifications.NotificationHelper
import com.capyreader.app.preferences.AfterReadAllBehavior
Expand Down Expand Up @@ -67,6 +68,13 @@ class ArticleScreenViewModel(

private var fullContentJob: Job? = null

var refreshSkipReason by mutableStateOf<RefreshSkipReason?>(null)
private set

fun clearRefreshSkipReason() {
refreshSkipReason = null
}

val filter = appPreferences.filter.stateIn(viewModelScope)

val listSwipeBottom =
Expand Down Expand Up @@ -434,6 +442,13 @@ class ArticleScreenViewModel(
refreshJob?.cancel()

refreshJob = viewModelScope.launch(ioDispatcher) {
if (appPreferences.refreshOnWiFiOnly.get() && !application.isOnWifi()) {
CapyLog.info("refresh_skipped_mobile", mapOf("type" to "foreground"))
refreshSkipReason = RefreshSkipReason.Mobile
onComplete()
return@launch
}

account.refresh(filter).onFailure { throwable ->
if (throwable is UnauthorizedError && _showUnauthorizedMessage == UnauthorizedMessageState.HIDE) {
_showUnauthorizedMessage = UnauthorizedMessageState.SHOW
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.capyreader.app.ui.articles

enum class RefreshSkipReason {
Mobile,
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ fun GeneralSettingsPanel(
onNavigateToNotifications = onNavigateToNotifications,
refreshInterval = viewModel.refreshInterval,
updateRefreshInterval = viewModel::updateRefreshInterval,
refreshOnWiFiOnly = viewModel.refreshOnWiFiOnly,
updateRefreshOnWiFiOnly = viewModel::updateRefreshOnWiFiOnly,
canOpenLinksInternally = viewModel.canOpenLinksInternally,
updateOpenLinksInternally = viewModel::updateOpenLinksInternally,
updateAutoDelete = viewModel::updateAutoDelete,
Expand All @@ -111,6 +113,8 @@ fun GeneralSettingsPanelView(
onClearArticles: () -> Unit,
refreshInterval: RefreshInterval,
updateRefreshInterval: (RefreshInterval) -> Unit,
refreshOnWiFiOnly: Boolean,
updateRefreshOnWiFiOnly: (enabled: Boolean) -> Unit,
canOpenLinksInternally: Boolean,
updateOpenLinksInternally: (canOpenLinksInternally: Boolean) -> Unit,
updateAutoDelete: (AutoDelete) -> Unit,
Expand Down Expand Up @@ -152,6 +156,13 @@ fun GeneralSettingsPanelView(
refreshInterval = refreshInterval,
updateRefreshInterval = updateRefreshInterval,
)
RowItem {
TextSwitch(
checked = refreshOnWiFiOnly,
onCheckedChange = updateRefreshOnWiFiOnly,
title = stringResource(R.string.settings_refresh_on_wifi_only),
)
}
NotificationsListItem(
onNavigate = onNavigateToNotifications,
refreshInterval = refreshInterval,
Expand Down Expand Up @@ -354,6 +365,8 @@ private fun GeneralSettingsPanelPreview() {
source = Source.LOCAL,
refreshInterval = RefreshInterval.EVERY_HOUR,
updateRefreshInterval = {},
refreshOnWiFiOnly = false,
updateRefreshOnWiFiOnly = {},
canOpenLinksInternally = false,
onClearArticles = {},
updateOpenLinksInternally = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ class GeneralSettingsViewModel(
var markReadOnScroll by mutableStateOf(appPreferences.articleListOptions.markReadOnScroll.get())
private set

var refreshOnWiFiOnly by mutableStateOf(appPreferences.refreshOnWiFiOnly.get())
private set

fun updateRefreshOnWiFiOnly(enabled: Boolean) {
appPreferences.refreshOnWiFiOnly.set(enabled)
refreshOnWiFiOnly = enabled
}

val filterKeywords = account
.preferences
.filterKeywords
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@
<string name="notification_mark_as_read_action">Mark as read</string>
<string name="settings_section_privacy">Privacy</string>
<string name="settings_section_refresh">Last Updated</string>
<string name="settings_refresh_on_wifi_only">Refresh on Wi-Fi only</string>
<string name="refresh_skipped_mobile">Refresh skipped on mobile network</string>
<string name="opml_import_button_text">Import from File</string>
<string name="opml_export_button_text">Export to OPML</string>
<string name="opml_import_progress_content_text_start">Starting import</string>
Expand Down
Loading