diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/UiSettings.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/UiSettings.kt index 002b2935f..b1e9c9466 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/UiSettings.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/UiSettings.kt @@ -31,6 +31,7 @@ data class UiSettings( val preferredLanguage: String? = null, val automaticallyShowImages: ConnectivityType = ConnectivityType.ALWAYS, val automaticallyStartPlayback: ConnectivityType = ConnectivityType.ALWAYS, + val automaticallyPlayVideos: BooleanType = BooleanType.ALWAYS, val automaticallyShowUrlPreview: ConnectivityType = ConnectivityType.ALWAYS, val automaticallyHideNavigationBars: BooleanType = BooleanType.ALWAYS, val automaticallyShowProfilePictures: ConnectivityType = ConnectivityType.ALWAYS, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/UiSettingsFlow.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/UiSettingsFlow.kt index 37cb82cc3..7a4bbeb1b 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/UiSettingsFlow.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/UiSettingsFlow.kt @@ -31,6 +31,7 @@ class UiSettingsFlow( val preferredLanguage: MutableStateFlow = MutableStateFlow(null), val automaticallyShowImages: MutableStateFlow = MutableStateFlow(ConnectivityType.ALWAYS), val automaticallyStartPlayback: MutableStateFlow = MutableStateFlow(ConnectivityType.ALWAYS), + val automaticallyPlayVideos: MutableStateFlow = MutableStateFlow(BooleanType.ALWAYS), val automaticallyShowUrlPreview: MutableStateFlow = MutableStateFlow(ConnectivityType.ALWAYS), val automaticallyHideNavigationBars: MutableStateFlow = MutableStateFlow(BooleanType.ALWAYS), val automaticallyShowProfilePictures: MutableStateFlow = MutableStateFlow(ConnectivityType.ALWAYS), @@ -46,6 +47,7 @@ class UiSettingsFlow( preferredLanguage, automaticallyShowImages, automaticallyStartPlayback, + automaticallyPlayVideos, automaticallyShowUrlPreview, automaticallyHideNavigationBars, automaticallyShowProfilePictures, @@ -64,14 +66,15 @@ class UiSettingsFlow( flows[1] as String?, flows[2] as ConnectivityType, flows[3] as ConnectivityType, - flows[4] as ConnectivityType, - flows[5] as BooleanType, - flows[6] as ConnectivityType, - flows[7] as Boolean, + flows[4] as BooleanType, + flows[5] as ConnectivityType, + flows[6] as BooleanType, + flows[7] as ConnectivityType, flows[8] as Boolean, - flows[9] as FeatureSetType, - flows[10] as ProfileGalleryType, - flows[11] as BooleanType, + flows[9] as Boolean, + flows[10] as FeatureSetType, + flows[11] as ProfileGalleryType, + flows[12] as BooleanType, ) } @@ -81,6 +84,7 @@ class UiSettingsFlow( preferredLanguage.value, automaticallyShowImages.value, automaticallyStartPlayback.value, + automaticallyPlayVideos.value, automaticallyShowUrlPreview.value, automaticallyHideNavigationBars.value, automaticallyShowProfilePictures.value, @@ -110,6 +114,10 @@ class UiSettingsFlow( automaticallyStartPlayback.tryEmit(torSettings.automaticallyStartPlayback) any = true } + if (automaticallyPlayVideos.value != torSettings.automaticallyPlayVideos) { + automaticallyPlayVideos.tryEmit(torSettings.automaticallyPlayVideos) + any = true + } if (automaticallyShowUrlPreview.value != torSettings.automaticallyShowUrlPreview) { automaticallyShowUrlPreview.tryEmit(torSettings.automaticallyShowUrlPreview) any = true @@ -165,6 +173,7 @@ class UiSettingsFlow( MutableStateFlow(uiSettings.preferredLanguage), MutableStateFlow(uiSettings.automaticallyShowImages), MutableStateFlow(uiSettings.automaticallyStartPlayback), + MutableStateFlow(uiSettings.automaticallyPlayVideos), MutableStateFlow(uiSettings.automaticallyShowUrlPreview), MutableStateFlow(uiSettings.automaticallyHideNavigationBars), MutableStateFlow(uiSettings.automaticallyShowProfilePictures), diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/preferences/UISharedPreferences.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/preferences/UISharedPreferences.kt index c2f573f41..c899fcbdc 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/preferences/UISharedPreferences.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/preferences/UISharedPreferences.kt @@ -95,6 +95,7 @@ class UiSharedPreferences( val UI_LANGUAGE = stringPreferencesKey("ui.language") val UI_SHOW_IMAGES = stringPreferencesKey("ui.show_images") val UI_START_PLAYBACK = stringPreferencesKey("ui.start_playback") + val UI_PLAY_VIDEOS = stringPreferencesKey("ui.play_videos") val UI_SHOW_URL_PREVIEW = stringPreferencesKey("ui.show_url_preview") val UI_HIDE_NAVIGATION_BARS = stringPreferencesKey("ui.hide_navigation_bars") val UI_SHOW_PROFILE_PICTURES = stringPreferencesKey("ui.show_profile_pictures") @@ -114,6 +115,7 @@ class UiSharedPreferences( preferredLanguage = preferences[UI_LANGUAGE]?.ifBlank { null }, automaticallyShowImages = preferences[UI_SHOW_IMAGES]?.let { ConnectivityType.valueOf(it) } ?: ConnectivityType.ALWAYS, automaticallyStartPlayback = preferences[UI_START_PLAYBACK]?.let { ConnectivityType.valueOf(it) } ?: ConnectivityType.ALWAYS, + automaticallyPlayVideos = preferences[UI_PLAY_VIDEOS]?.let { BooleanType.valueOf(it) } ?: BooleanType.ALWAYS, automaticallyShowUrlPreview = preferences[UI_SHOW_URL_PREVIEW]?.let { ConnectivityType.valueOf(it) } ?: ConnectivityType.ALWAYS, automaticallyHideNavigationBars = preferences[UI_HIDE_NAVIGATION_BARS]?.let { BooleanType.valueOf(it) } ?: BooleanType.ALWAYS, automaticallyShowProfilePictures = preferences[UI_SHOW_PROFILE_PICTURES]?.let { ConnectivityType.valueOf(it) } ?: ConnectivityType.ALWAYS, @@ -150,6 +152,7 @@ class UiSharedPreferences( preferences[UI_LANGUAGE] = sharedSettings.preferredLanguage ?: "" preferences[UI_SHOW_IMAGES] = sharedSettings.automaticallyShowImages.name preferences[UI_START_PLAYBACK] = sharedSettings.automaticallyStartPlayback.name + preferences[UI_PLAY_VIDEOS] = sharedSettings.automaticallyPlayVideos.name preferences[UI_SHOW_URL_PREVIEW] = sharedSettings.automaticallyShowUrlPreview.name preferences[UI_HIDE_NAVIGATION_BARS] = sharedSettings.automaticallyHideNavigationBars.name preferences[UI_SHOW_PROFILE_PICTURES] = sharedSettings.automaticallyShowProfilePictures.name diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/playback/composable/VideoView.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/playback/composable/VideoView.kt index 6d8cf5382..0a219cd6d 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/playback/composable/VideoView.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/playback/composable/VideoView.kt @@ -102,12 +102,12 @@ fun VideoView( accountViewModel: AccountViewModel, thumbhash: String? = null, ) { - val automaticallyStartPlayback = - remember { - mutableStateOf( - if (alwaysShowVideo) true else accountViewModel.settings.startVideoPlayback(), - ) - } + val initialAutoStart = if (alwaysShowVideo) true else accountViewModel.settings.startVideoPlayback() + val automaticallyStartPlayback = remember { mutableStateOf(initialAutoStart) } + + // Once the video is being shown, only honor the user's autoplay preference when it was auto-loaded. + // If the user manually tapped the download button, they want it to play. + val autoplay = alwaysShowVideo || (initialAutoStart && accountViewModel.settings.autoPlayVideos()) || (!initialAutoStart && automaticallyStartPlayback.value) if (blurhash == null && thumbhash == null) { val ratio = dimensions?.aspectRatio() ?: MediaAspectRatioCache.get(videoUri) @@ -137,7 +137,7 @@ fun VideoView( artworkUri = artworkUri, authorName = authorName, nostrUriCallback = nostrUriCallback, - automaticallyStartPlayback = automaticallyStartPlayback.value, + automaticallyStartPlayback = autoplay, onZoom = onDialog, hasBlurhash = false, accountViewModel = accountViewModel, @@ -185,7 +185,7 @@ fun VideoView( artworkUri = artworkUri, authorName = authorName, nostrUriCallback = nostrUriCallback, - automaticallyStartPlayback = automaticallyStartPlayback.value, + automaticallyStartPlayback = autoplay, onZoom = onDialog, hasBlurhash = true, accountViewModel = accountViewModel, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/UiSettingsState.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/UiSettingsState.kt index 70b9bb0d8..d6177d0c6 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/UiSettingsState.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/UiSettingsState.kt @@ -138,5 +138,7 @@ class UiSettingsState( fun startVideoPlayback() = startVideoPlayback.value + fun autoPlayVideos() = uiSettingsFlow.automaticallyPlayVideos.value == BooleanType.ALWAYS + fun showImages() = showImages.value } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/settings/AppSettingsScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/settings/AppSettingsScreen.kt index ace4f154d..5e7c8caca 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/settings/AppSettingsScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/settings/AppSettingsScreen.kt @@ -116,6 +116,7 @@ fun SettingsScreen(sharedPrefs: UiSettingsFlow) { ShowThemeChoice(sharedPrefs) ShowImagePreviewChoice(sharedPrefs) ShowVideoPlaybackChoice(sharedPrefs) + AutoplayVideosChoice(sharedPrefs) ShowUrlPreviewChoice(sharedPrefs) ShowProfilePictureChoice(sharedPrefs) ImmersiveScrollingChoice(sharedPrefs) @@ -264,6 +265,26 @@ fun ShowVideoPlaybackChoice(sharedPrefs: UiSettingsFlow) { } } +@Composable +fun AutoplayVideosChoice(sharedPrefs: UiSettingsFlow) { + val autoplayIndex by sharedPrefs.automaticallyPlayVideos.collectAsState() + + val booleanItems = + persistentListOf( + TitleExplainer(stringRes(ConnectivityType.ALWAYS.resourceId)), + TitleExplainer(stringRes(ConnectivityType.NEVER.resourceId)), + ) + + SettingsRow( + R.string.autoplay_videos, + R.string.autoplay_videos_description, + booleanItems, + autoplayIndex.screenCode, + ) { + sharedPrefs.automaticallyPlayVideos.tryEmit(parseBooleanType(it)) + } +} + @Composable fun ShowUrlPreviewChoice(sharedPrefs: UiSettingsFlow) { val connectivityBasedOptions = diff --git a/amethyst/src/main/res/values/strings.xml b/amethyst/src/main/res/values/strings.xml index b537cbcf6..7362efe51 100644 --- a/amethyst/src/main/res/values/strings.xml +++ b/amethyst/src/main/res/values/strings.xml @@ -1093,6 +1093,7 @@ Theme Image Preview Video Playback + Autoplay Videos URL Preview Immersive Scrolling Hide Nav Bars when Scrolling @@ -1184,7 +1185,8 @@ For the App\'s Interface Dark, Light or System theme Automatically load images and GIFs - Automatically plays videos and GIFs + Automatically load videos and GIFs + Automatically play videos when visible on screen Show URL previews When to load images