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
Original file line number Diff line number Diff line change
Expand Up @@ -758,6 +758,7 @@ class OPMLTest : DIAware {
UserSettings.SETTING_IMG_ONLY_WIFI -> "true"
UserSettings.SETTING_IMG_SHOW_THUMBNAILS -> "false"
UserSettings.SETTING_DEFAULT_OPEN_ITEM_WITH -> PREF_VAL_OPEN_WITH_CUSTOM_TAB
UserSettings.SETTING_OPEN_ITEM_IN_READER_WITH -> PREF_VAL_OPEN_WITH_CUSTOM_TAB
UserSettings.SETTING_TEXT_SCALE -> "1.6"
UserSettings.SETTING_IS_MARK_AS_READ_ON_SCROLL -> "true"
UserSettings.SETTING_READALOUD_USE_DETECT_LANGUAGE -> "true"
Expand Down Expand Up @@ -838,6 +839,7 @@ private val sampleFile: List<String> =
<feeder:setting key="pref_img_show_thumbnails" value="false"/>
<feeder:setting key="pref_default_open_item_with" value="3"/>
<feeder:setting key="pref_open_links_with" value="3"/>
<feeder:setting key="pref_open_item_in_reader_with" value="3"/>
<feeder:setting key="pref_open_adjacent" value="true"/>
<feeder:setting key="pref_paging_mode" value="true"/>
<feeder:setting key="pref_animated_paging" value="true"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,10 @@ class Repository(

fun setLinkOpener(value: LinkOpener) = settingsStore.setLinkOpener(value)

val itemInReaderOpener = settingsStore.itemInReaderOpener

fun setItemInReaderOpener(value: LinkOpener) = settingsStore.setItemInReaderOpener(value)

val syncFrequency = settingsStore.syncFrequency

fun setSyncFrequency(value: SyncFrequency) = settingsStore.setSyncFrequency(value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,30 @@ class SettingsStore(
).apply()
}

private val _itemInReaderOpener =
MutableStateFlow(
linkOpenerFromString(
sp.getStringNonNull(
PREF_OPEN_ITEM_IN_READER_WITH,
PREF_VAL_OPEN_WITH_CUSTOM_TAB,
),
),
)
val itemInReaderOpener = _itemInReaderOpener.asStateFlow()

fun setItemInReaderOpener(value: LinkOpener) {
_itemInReaderOpener.value = value
sp
.edit()
.putString(
PREF_OPEN_ITEM_IN_READER_WITH,
when (value) {
LinkOpener.CUSTOM_TAB -> PREF_VAL_OPEN_WITH_CUSTOM_TAB
LinkOpener.DEFAULT_BROWSER -> PREF_VAL_OPEN_WITH_BROWSER
},
).apply()
}

private val _openAdjacent = MutableStateFlow(sp.getBoolean(PREF_OPEN_ADJACENT, true))
val openAdjacent = _openAdjacent.asStateFlow()

Expand Down Expand Up @@ -626,6 +650,7 @@ const val PREF_IMG_SHOW_THUMBNAILS = "pref_img_show_thumbnails"
*/
const val PREF_DEFAULT_OPEN_ITEM_WITH = "pref_default_open_item_with"
const val PREF_OPEN_LINKS_WITH = "pref_open_links_with"
const val PREF_OPEN_ITEM_IN_READER_WITH = "pref_open_item_in_reader_with"
const val PREF_OPEN_ADJACENT = "pref_open_adjacent"

const val PREF_PAGING_MODE = "pref_paging_mode"
Expand Down Expand Up @@ -695,6 +720,7 @@ enum class UserSettings(
SETTING_IMG_SHOW_THUMBNAILS(key = PREF_IMG_SHOW_THUMBNAILS),
SETTING_DEFAULT_OPEN_ITEM_WITH(key = PREF_DEFAULT_OPEN_ITEM_WITH),
SETTING_OPEN_LINKS_WITH(key = PREF_OPEN_LINKS_WITH),
SETTING_OPEN_ITEM_IN_READER_WITH(key = PREF_OPEN_ITEM_IN_READER_WITH),
SETTING_OPEN_ADJACENT(key = PREF_OPEN_ADJACENT),
SETTING_PAGING_MODE(key = PREF_PAGING_MODE),
SETTING_ANIMATED_PAGING(key = PREF_ANIMATED_PAGING),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ open class OPMLImporter(
settingsStore.setLinkOpener(
linkOpenerFromString(value),
)
UserSettings.SETTING_OPEN_ITEM_IN_READER_WITH ->
settingsStore.setItemInReaderOpener(
linkOpenerFromString(value),
)
UserSettings.SETTING_TEXT_SCALE -> settingsStore.setTextScale(value.toFloatOrNull() ?: 1.0f)
UserSettings.SETTING_IS_MARK_AS_READ_ON_SCROLL -> settingsStore.setIsMarkAsReadOnScroll(value.toBoolean())
UserSettings.SETTING_READALOUD_USE_DETECT_LANGUAGE -> settingsStore.setUseDetectLanguage(value.toBoolean())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import androidx.compose.ui.semantics.role
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.nononsenseapps.feeder.R
import com.nononsenseapps.feeder.archmodel.LinkOpener
import com.nononsenseapps.feeder.archmodel.TextToDisplay
import com.nononsenseapps.feeder.db.room.ID_UNSET
import com.nononsenseapps.feeder.model.LocaleOverride
Expand Down Expand Up @@ -159,6 +160,11 @@ fun ArticleScreen(
activityLauncher.openLinkInCustomTab(link, toolbarColor)
}
},
onOpenInBrowser = {
viewState.articleLink?.let { link ->
activityLauncher.openLinkInBrowser(link)
}
},
onFeedTitleClick = {
onNavigateToFeed(viewState.articleFeedId)
},
Expand Down Expand Up @@ -192,6 +198,7 @@ fun ArticleScreen(
onMarkAsUnread: () -> Unit,
onShare: () -> Unit,
onOpenInCustomTab: () -> Unit,
onOpenInBrowser: () -> Unit,
onFeedTitleClick: () -> Unit,
onShowToolbarMenu: (Boolean) -> Unit,
ttsOnPlay: () -> Unit,
Expand Down Expand Up @@ -256,13 +263,35 @@ fun ArticleScreen(
}
}

PlainTooltipBox(tooltip = { Text(stringResource(id = R.string.open_in_web_view)) }) {
PlainTooltipBox(
tooltip = {
Text(
stringResource(
when (viewState.itemInReaderOpener) {
LinkOpener.DEFAULT_BROWSER -> R.string.open_article_in_default_browser
else -> R.string.open_article_in_custom_tab
},
),
)
},
) {
IconButton(
onClick = onOpenInCustomTab,
onClick = {
when (viewState.itemInReaderOpener) {
LinkOpener.DEFAULT_BROWSER -> onOpenInBrowser()
else -> onOpenInCustomTab()
}
},
) {
Icon(
Icons.Default.OpenInBrowser,
contentDescription = stringResource(id = R.string.open_in_web_view),
contentDescription =
stringResource(
when (viewState.itemInReaderOpener) {
LinkOpener.DEFAULT_BROWSER -> R.string.open_article_in_default_browser
else -> R.string.open_article_in_custom_tab
},
),
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ class ArticleViewModel(
ttsStateHolder.availableLanguages,
repository.openAISettings,
openAiSummary,
repository.itemInReaderOpener,
) { params ->
val article = params[0] as Article?
val textToDisplay = params[1] as TextToDisplay
Expand All @@ -144,6 +145,7 @@ class ArticleViewModel(

val showSummarize = (params[8] as OpenAISettings).isValid && !article?.link.isNullOrEmpty()
val openAiSummary = (params[9] as OpenAISummaryState)
val itemInReaderOpener = params[10] as LinkOpener

ArticleState(
useDetectLanguage = useDetectLanguage,
Expand All @@ -156,6 +158,7 @@ class ArticleViewModel(
articleFeedId = article?.feedId ?: ID_UNSET,
textToDisplay = textToDisplay,
linkOpener = linkOpener,
itemInReaderOpener = itemInReaderOpener,
pubDate = article?.pubDate,
author = article?.author,
enclosure = article?.enclosure ?: Enclosure(),
Expand Down Expand Up @@ -481,6 +484,7 @@ private data class ArticleState(
override val articleFeedId: Long = ID_UNSET,
override val textToDisplay: TextToDisplay = TextToDisplay.CONTENT,
override val linkOpener: LinkOpener = LinkOpener.CUSTOM_TAB,
override val itemInReaderOpener: LinkOpener = LinkOpener.CUSTOM_TAB,
override val pubDate: ZonedDateTime? = null,
override val author: String? = null,
override val enclosure: Enclosure = Enclosure(),
Expand Down Expand Up @@ -508,6 +512,7 @@ interface ArticleScreenViewState {
val articleFeedId: Long
val textToDisplay: TextToDisplay
val linkOpener: LinkOpener
val itemInReaderOpener: LinkOpener
val pubDate: ZonedDateTime?
val author: String?
val enclosure: Enclosure
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ fun SettingsScreen(
onItemOpenerChange = settingsViewModel::setItemOpener,
currentLinkOpenerValue = viewState.linkOpener,
onLinkOpenerChange = settingsViewModel::setLinkOpener,
currentItemInReaderOpenerValue = viewState.itemInReaderOpener,
onItemInReaderOpenerChange = settingsViewModel::setItemInReaderOpener,
currentSyncFrequencyValue = viewState.syncFrequency,
onSyncFrequencyChange = settingsViewModel::setSyncFrequency,
batteryOptimizationIgnoredValue = viewState.batteryOptimizationIgnored,
Expand Down Expand Up @@ -265,6 +267,8 @@ private fun SettingsScreenPreview() {
onItemOpenerChange = {},
currentLinkOpenerValue = LinkOpener.DEFAULT_BROWSER,
onLinkOpenerChange = {},
currentItemInReaderOpenerValue = LinkOpener.DEFAULT_BROWSER,
onItemInReaderOpenerChange = {},
currentSyncFrequencyValue = SyncFrequency.EVERY_12_HOURS,
onSyncFrequencyChange = {},
batteryOptimizationIgnoredValue = false,
Expand Down Expand Up @@ -339,6 +343,8 @@ fun SettingsList(
onItemOpenerChange: (ItemOpener) -> Unit,
currentLinkOpenerValue: LinkOpener,
onLinkOpenerChange: (LinkOpener) -> Unit,
currentItemInReaderOpenerValue: LinkOpener,
onItemInReaderOpenerChange: (LinkOpener) -> Unit,
currentSyncFrequencyValue: SyncFrequency,
onSyncFrequencyChange: (SyncFrequency) -> Unit,
batteryOptimizationIgnoredValue: Boolean,
Expand Down Expand Up @@ -703,6 +709,22 @@ fun SettingsList(
.width(dimens.maxContentWidth),
)

MenuSetting(
title = stringResource(id = R.string.open_item_in_reader_with),
currentValue = currentItemInReaderOpenerValue.asLinkOpenerOption(),
values =
immutableListHolderOf(
LinkOpener.CUSTOM_TAB.asLinkOpenerOption(),
LinkOpener.DEFAULT_BROWSER.asLinkOpenerOption(),
),
onSelection = {
onItemInReaderOpenerChange(it.linkOpener)
},
modifier =
Modifier
.width(dimens.maxContentWidth),
)

val notCompactScreen = LocalConfiguration.current.smallestScreenWidthDp >= 600

if (notCompactScreen) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ class SettingsViewModel(
repository.setLinkOpener(value)
}

fun setItemInReaderOpener(value: LinkOpener) {
repository.setItemInReaderOpener(value)
}

fun setSyncFrequency(value: SyncFrequency) =
applicationCoroutineScope.launch {
repository.setSyncFrequency(value)
Expand Down Expand Up @@ -248,6 +252,7 @@ class SettingsViewModel(
repository.font,
repository.isPagingMode,
repository.isAnimatedPaging,
repository.itemInReaderOpener,
) { params: Array<Any> ->
@Suppress("UNCHECKED_CAST")
SettingsViewState(
Expand Down Expand Up @@ -287,6 +292,7 @@ class SettingsViewModel(
font = params[30] as FontSelection,
isPagingMode = params[31] as Boolean,
isAnimatedPaging = params[32] as Boolean,
itemInReaderOpener = params[33] as LinkOpener,
)
}.collect {
_viewState.value = it
Expand Down Expand Up @@ -350,6 +356,7 @@ data class SettingsViewState(
val font: FontSelection = SystemDefault,
val isPagingMode: Boolean = false,
val isAnimatedPaging: Boolean = false,
val itemInReaderOpener: LinkOpener = LinkOpener.CUSTOM_TAB,
)

data class UIFeedSettings(
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@
<string name="no_article_link_custom_tab">Unable to open article in custom tab</string>
<string name="use_app_default">Use app default</string>
<string name="open_item_by_default_with">Open items by default with</string>
<string name="open_links_with">Open links with</string>
<string name="open_links_with">Open links in reader with</string>
<string name="open_item_in_reader_with">Open articles via button in reader with</string>
<string name="reader_settings">Reader</string>
<string name="article_list_settings">Article list</string>
<string name="open_link_in_web_view">Open link in web view</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,17 @@ class SettingsStoreTest : DIAware {
assertEquals(LinkOpener.DEFAULT_BROWSER, store.linkOpener.value)
}

@Test
fun itemInReaderOpener() {
store.setItemInReaderOpener(LinkOpener.DEFAULT_BROWSER)

verify {
sp.edit().putString(PREF_OPEN_ITEM_IN_READER_WITH, PREF_VAL_OPEN_WITH_BROWSER).apply()
}

assertEquals(LinkOpener.DEFAULT_BROWSER, store.itemInReaderOpener.value)
}

@Ignore("scheduling of jobs is not mocked")
@Test
fun syncFrequency() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ class OpmlParserTest : DIAware {
UserSettings.SETTING_IMG_ONLY_WIFI -> "true"
UserSettings.SETTING_IMG_SHOW_THUMBNAILS -> "false"
UserSettings.SETTING_DEFAULT_OPEN_ITEM_WITH -> PREF_VAL_OPEN_WITH_CUSTOM_TAB
UserSettings.SETTING_OPEN_ITEM_IN_READER_WITH -> PREF_VAL_OPEN_WITH_CUSTOM_TAB
UserSettings.SETTING_TEXT_SCALE -> "1.6"
UserSettings.SETTING_IS_MARK_AS_READ_ON_SCROLL -> "true"
UserSettings.SETTING_READALOUD_USE_DETECT_LANGUAGE -> "true"
Expand Down Expand Up @@ -116,6 +117,7 @@ class OpmlParserTest : DIAware {
settingsStore.setLoadImageOnlyOnWifi(true)
settingsStore.setShowThumbnails(false)
settingsStore.setItemOpener(ItemOpener.CUSTOM_TAB)
settingsStore.setItemInReaderOpener(LinkOpener.CUSTOM_TAB)
settingsStore.setTextScale(1.6f)
settingsStore.setIsMarkAsReadOnScroll(true)
settingsStore.setUseDetectLanguage(true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ class OpmlWriterKtTest {
<feeder:setting key="pref_img_show_thumbnails" value="false"/>
<feeder:setting key="pref_default_open_item_with" value="3"/>
<feeder:setting key="pref_open_links_with" value="3"/>
<feeder:setting key="pref_open_item_in_reader_with" value="3"/>
<feeder:setting key="pref_open_adjacent" value="true"/>
<feeder:setting key="pref_paging_mode" value="true"/>
<feeder:setting key="pref_animated_paging" value="true"/>
Expand Down Expand Up @@ -195,6 +196,7 @@ class OpmlWriterKtTest {
UserSettings.SETTING_SHOW_TITLE_UNREAD_COUNT -> "true"
UserSettings.SETTING_MAX_ITEM_COUNT_PER_FEED -> "200"
UserSettings.SETTING_DEFAULT_OPEN_ITEM_WITH -> PREF_VAL_OPEN_WITH_CUSTOM_TAB
UserSettings.SETTING_OPEN_ITEM_IN_READER_WITH -> PREF_VAL_OPEN_WITH_CUSTOM_TAB
UserSettings.SETTING_OPENAI_KEY -> "test-api-key"
UserSettings.SETTING_OPENAI_MODEL_ID -> "gpt-4o-mini"
UserSettings.SETTING_OPENAI_URL -> "https://api.openai.com"
Expand Down