diff --git a/app/src/main/kotlin/androidx/compose/material/icons/outlined/Remove.kt b/app/src/main/kotlin/androidx/compose/material/icons/outlined/Remove.kt new file mode 100644 index 0000000..bc25324 --- /dev/null +++ b/app/src/main/kotlin/androidx/compose/material/icons/outlined/Remove.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package androidx.compose.material.icons.outlined + +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.materialIcon +import androidx.compose.material.icons.materialPath +import androidx.compose.ui.graphics.vector.ImageVector + +public val Icons.Outlined.Remove: ImageVector + get() { + if (_remove != null) { + return _remove!! + } + _remove = materialIcon(name = "Outlined.Remove") { + materialPath { + moveTo(19.0F, 13.0F) + horizontalLineTo(5.0F) + verticalLineToRelative(-2.0F) + horizontalLineToRelative(14.0F) + verticalLineToRelative(2.0F) + close() + } + } + return _remove!! + } + +private var _remove: ImageVector? = null diff --git a/app/src/main/kotlin/com/muedsa/agetv/AppModule.kt b/app/src/main/kotlin/com/muedsa/agetv/AppModule.kt index 7bd8d0d..7984338 100644 --- a/app/src/main/kotlin/com/muedsa/agetv/AppModule.kt +++ b/app/src/main/kotlin/com/muedsa/agetv/AppModule.kt @@ -1,8 +1,10 @@ package com.muedsa.agetv +import android.content.Context import com.google.common.net.HttpHeaders import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactory import com.muedsa.agetv.repository.AppRepository +import com.muedsa.agetv.repository.DataStoreRepo import com.muedsa.agetv.service.AgeApiService import com.muedsa.agetv.service.AgePlayerService import com.muedsa.agetv.service.DanDanPlayApiService @@ -11,6 +13,7 @@ import com.muedsa.uitl.LenientJson import dagger.Module import dagger.Provides import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.components.SingletonComponent import okhttp3.MediaType.Companion.toMediaType import okhttp3.OkHttpClient @@ -88,4 +91,8 @@ internal object AppModule { playerService = playerService, danDanPlayApiService = danDanPlayApiService ) + + @Singleton + @Provides + fun provideDataStoreRepository(@ApplicationContext app: Context) = DataStoreRepo(app) } \ No newline at end of file diff --git a/app/src/main/kotlin/com/muedsa/agetv/Perfs.kt b/app/src/main/kotlin/com/muedsa/agetv/Perfs.kt new file mode 100644 index 0000000..d253281 --- /dev/null +++ b/app/src/main/kotlin/com/muedsa/agetv/Perfs.kt @@ -0,0 +1,12 @@ +package com.muedsa.agetv + +import androidx.datastore.preferences.core.booleanPreferencesKey +import androidx.datastore.preferences.core.intPreferencesKey + +val KEY_DANMAKU_ENABLE = booleanPreferencesKey("danmaku_enable") + +val KEY_DANMAKU_SIZE_SCALE = intPreferencesKey("danmaku_size_scale") + +val KEY_DANMAKU_ALPHA = intPreferencesKey("danmaku_alpha") + +val KEY_DANMAKU_SCREEN_PART = intPreferencesKey("danmaku_size_part") \ No newline at end of file diff --git a/app/src/main/kotlin/com/muedsa/agetv/model/AppSettingModel.kt b/app/src/main/kotlin/com/muedsa/agetv/model/AppSettingModel.kt new file mode 100644 index 0000000..83b5172 --- /dev/null +++ b/app/src/main/kotlin/com/muedsa/agetv/model/AppSettingModel.kt @@ -0,0 +1,8 @@ +package com.muedsa.agetv.model + +data class AppSettingModel( + val danmakuEnable: Boolean, + val danmakuSizeScale: Int, + val danmakuAlpha: Int, + val danmakuScreenPart: Int +) \ No newline at end of file diff --git a/app/src/main/kotlin/com/muedsa/agetv/repository/DataStoreRepo.kt b/app/src/main/kotlin/com/muedsa/agetv/repository/DataStoreRepo.kt new file mode 100644 index 0000000..c44d9ad --- /dev/null +++ b/app/src/main/kotlin/com/muedsa/agetv/repository/DataStoreRepo.kt @@ -0,0 +1,30 @@ +package com.muedsa.agetv.repository + +import android.content.Context +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.preferencesDataStore +import javax.inject.Inject + +private const val PREFS_NAME = "setting" + +private val Context.dataStore: DataStore by preferencesDataStore(name = PREFS_NAME) + +class DataStoreRepo @Inject constructor(private val context: Context) { + + val dataStore: DataStore = context.dataStore + +// suspend fun get(key: Preferences.Key): T? { +// return dataStore.data.first()[key] +// } +// +// suspend fun collectPrefs(collector: FlowCollector) { +// dataStore.data.collect(collector) +// } +// +// suspend fun putString(key: Preferences.Key, value: String) { +// dataStore.edit { +// it[key] = value +// } +// } +} \ No newline at end of file diff --git a/app/src/main/kotlin/com/muedsa/agetv/ui/features/detail/AnimeDetailScreen.kt b/app/src/main/kotlin/com/muedsa/agetv/ui/features/detail/AnimeDetailScreen.kt index 4402d78..ac32c5f 100644 --- a/app/src/main/kotlin/com/muedsa/agetv/ui/features/detail/AnimeDetailScreen.kt +++ b/app/src/main/kotlin/com/muedsa/agetv/ui/features/detail/AnimeDetailScreen.kt @@ -37,12 +37,14 @@ import androidx.tv.material3.AssistChip import androidx.tv.material3.ExperimentalTvMaterial3Api import androidx.tv.material3.Icon import androidx.tv.material3.MaterialTheme +import androidx.tv.material3.OutlinedButton import androidx.tv.material3.Text import com.muedsa.agetv.PlaybackActivity import com.muedsa.agetv.model.LazyType import com.muedsa.agetv.ui.AgePosterSize import com.muedsa.agetv.ui.RankFontColor import com.muedsa.agetv.ui.RankIconColor +import com.muedsa.agetv.ui.navigation.NavigationItems import com.muedsa.agetv.viewmodel.AnimeDetailViewModel import com.muedsa.compose.tv.model.ContentModel import com.muedsa.compose.tv.theme.ScreenPaddingLeft @@ -68,7 +70,8 @@ import kotlinx.coroutines.flow.update @Composable fun AnimeDetailScreen( viewModel: AnimeDetailViewModel = hiltViewModel(), - errorMsgBoxState: ErrorMessageBoxState + errorMsgBoxState: ErrorMessageBoxState, + onNavigate: (NavigationItems, List?) -> Unit = { _, _ -> } ) { val context = LocalContext.current val configuration = LocalConfiguration.current @@ -219,11 +222,11 @@ fun AnimeDetailScreen( Spacer(modifier = Modifier.height(25.dp)) } - // 播放源 + // 按钮列表 item { - // 切换播放源 Row(verticalAlignment = Alignment.CenterVertically) { + // 切换播放源 Text( text = "播放源", color = MaterialTheme.colorScheme.onBackground, @@ -278,9 +281,21 @@ fun AnimeDetailScreen( } ) } + + Spacer(modifier = Modifier.width(25.dp)) + OutlinedButton( + onClick = { + onNavigate(NavigationItems.Setting, null) + } + ) { + Text(text = "设置") + } } Spacer(modifier = Modifier.height(20.dp)) + } + // 切换播放源 + item { FlowRow( modifier = Modifier.fillMaxWidth(0.9f), verticalArrangement = Arrangement.Center, diff --git a/app/src/main/kotlin/com/muedsa/agetv/ui/features/playback/PlaybackScreen.kt b/app/src/main/kotlin/com/muedsa/agetv/ui/features/playback/PlaybackScreen.kt index e153bac..47e8ebe 100644 --- a/app/src/main/kotlin/com/muedsa/agetv/ui/features/playback/PlaybackScreen.kt +++ b/app/src/main/kotlin/com/muedsa/agetv/ui/features/playback/PlaybackScreen.kt @@ -30,17 +30,20 @@ fun PlaybackScreen( episodeTitle: String, mediaUrl: String, danEpisodeId: Long = 0, - viewModel: PlaybackViewModel = hiltViewModel() + playbackViewModel: PlaybackViewModel = hiltViewModel(), ) { val activity = (LocalContext.current as? Activity) val errorMsgBoxState = remember { ErrorMessageBoxState() } ErrorMessageBox(state = errorMsgBoxState) { - val danmakuListLD by viewModel.danmakuListLDSF.collectAsState() + val danmakuSettingLD by playbackViewModel.danmakuSettingLDSF.collectAsState() + val danmakuListLD by playbackViewModel.danmakuListLDSF.collectAsState() - LaunchedEffect(key1 = danEpisodeId) { - viewModel.loadDanmakuList(danEpisodeId) + LaunchedEffect(key1 = danmakuSettingLD) { + if (danmakuListLD.type == LazyType.FAILURE) { + errorMsgBoxState.error(danmakuListLD.error) + } } LaunchedEffect(key1 = danmakuListLD) { @@ -49,9 +52,16 @@ fun PlaybackScreen( } } - if (danmakuListLD.type == LazyType.SUCCESS) { + if (danmakuListLD.type == LazyType.SUCCESS && danmakuSettingLD.type == LazyType.SUCCESS) { + var danmakuSetting = danmakuSettingLD.data!! + DanmakuVideoPlayer( debug = BuildConfig.DEBUG, + danmakuConfigSetting = { + textSizeScale = danmakuSetting.danmakuSizeScale / 100f + alpha = danmakuSetting.danmakuAlpha / 100f + screenPart = danmakuSetting.danmakuScreenPart / 100f + }, danmakuPlayerInit = { if (!danmakuListLD.data.isNullOrEmpty()) { updateData(danmakuListLD.data!!) @@ -70,7 +80,7 @@ fun PlaybackScreen( override fun onRenderedFirstFrame() { stopState.value = false - viewModel.registerPlayerPositionSaver( + playbackViewModel.registerPlayerPositionSaver( aid, episodeTitle, this@DanmakuVideoPlayer, @@ -105,5 +115,16 @@ fun PlaybackScreen( prepare() } } + + if (danmakuSettingLD.type == LazyType.SUCCESS) { + val danmakuSetting = danmakuSettingLD.data!! + LaunchedEffect(key1 = danEpisodeId) { + playbackViewModel.loadDanmakuList( + if (danmakuSetting.danmakuEnable) + danEpisodeId + else 0 + ) + } + } } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/muedsa/agetv/ui/features/setting/AppSettingScreen.kt b/app/src/main/kotlin/com/muedsa/agetv/ui/features/setting/AppSettingScreen.kt new file mode 100644 index 0000000..dff8237 --- /dev/null +++ b/app/src/main/kotlin/com/muedsa/agetv/ui/features/setting/AppSettingScreen.kt @@ -0,0 +1,182 @@ +package com.muedsa.agetv.ui.features.setting + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Add +import androidx.compose.material.icons.outlined.Remove +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.tv.material3.ExperimentalTvMaterial3Api +import androidx.tv.material3.Icon +import androidx.tv.material3.MaterialTheme +import androidx.tv.material3.OutlinedIconButton +import androidx.tv.material3.Text +import com.muedsa.agetv.model.LazyType +import com.muedsa.agetv.viewmodel.AppSettingViewModel +import com.muedsa.compose.tv.theme.ScreenPaddingLeft +import com.muedsa.compose.tv.widget.ErrorMessageBoxState +import com.muedsa.compose.tv.widget.FocusScaleSwitch + +@OptIn(ExperimentalTvMaterial3Api::class) +@Composable +fun AppSettingScreen( + viewModel: AppSettingViewModel = hiltViewModel(), + errorMsgBoxState: ErrorMessageBoxState, +) { + + val settingLD by viewModel.settingLDSF.collectAsState() + + LaunchedEffect(key1 = settingLD) { + if (settingLD.type == LazyType.FAILURE) { + errorMsgBoxState.error(settingLD.error) + } + } + + if (settingLD.type == LazyType.SUCCESS && settingLD.data != null) { + val settingModel = settingLD.data!! + Column( + modifier = Modifier.padding( + start = ScreenPaddingLeft, + top = ScreenPaddingLeft + ) + ) { + Text( + modifier = Modifier.width(150.dp), + text = "设置", + color = MaterialTheme.colorScheme.onBackground, + style = MaterialTheme.typography.headlineMedium + ) + Spacer(modifier = Modifier.height(30.dp)) + + Row( + modifier = Modifier.padding(bottom = 20.dp), + horizontalArrangement = Arrangement.Center + ) { + Text( + modifier = Modifier.width(100.dp), + text = "弹幕开关", + color = MaterialTheme.colorScheme.onBackground, + style = MaterialTheme.typography.titleMedium + ) + FocusScaleSwitch( + checked = settingModel.danmakuEnable, + onCheckedChange = { + viewModel.changeDanmakuEnable(it) + } + ) + } + + Row( + modifier = Modifier.padding(bottom = 20.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + modifier = Modifier.width(100.dp), + text = "弹幕缩放", + color = MaterialTheme.colorScheme.onBackground, + style = MaterialTheme.typography.titleMedium + ) + + OutlinedIconButton(onClick = { + viewModel.changeDanmakuSizeScale(settingModel.danmakuSizeScale - 5) + }) { + Icon(imageVector = Icons.Outlined.Remove, contentDescription = "-") + } + + Text( + modifier = Modifier.width(60.dp), + text = "${settingModel.danmakuSizeScale}%", + color = MaterialTheme.colorScheme.onBackground, + style = MaterialTheme.typography.titleMedium, + textAlign = TextAlign.Center + ) + + OutlinedIconButton(onClick = { + viewModel.changeDanmakuSizeScale(settingModel.danmakuSizeScale + 5) + }) { + Icon(imageVector = Icons.Outlined.Add, contentDescription = "+") + } + } + + + Row( + modifier = Modifier.padding(bottom = 20.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + modifier = Modifier.width(100.dp), + text = "弹幕透明度", + color = MaterialTheme.colorScheme.onBackground, + style = MaterialTheme.typography.titleMedium + ) + + OutlinedIconButton(onClick = { + viewModel.changeDanmakuAlpha(settingModel.danmakuAlpha - 5) + }) { + Icon(imageVector = Icons.Outlined.Remove, contentDescription = "-") + } + + Text( + modifier = Modifier.width(60.dp), + text = "${settingModel.danmakuAlpha}%", + color = MaterialTheme.colorScheme.onBackground, + style = MaterialTheme.typography.titleMedium, + textAlign = TextAlign.Center + ) + + OutlinedIconButton(onClick = { + viewModel.changeDanmakuAlpha(settingModel.danmakuAlpha + 5) + }) { + Icon(imageVector = Icons.Outlined.Add, contentDescription = "+") + } + } + + Row( + modifier = Modifier.padding(bottom = 20.dp), + verticalAlignment = Alignment.CenterVertically + ) { + Text( + modifier = Modifier.width(100.dp), + text = "弹幕屏占比", + color = MaterialTheme.colorScheme.onBackground, + style = MaterialTheme.typography.titleMedium + ) + + OutlinedIconButton(onClick = { + viewModel.changeDanmakuScreenPart(settingModel.danmakuScreenPart - 5) + }) { + Icon(imageVector = Icons.Outlined.Remove, contentDescription = "-") + } + + Text( + modifier = Modifier.width(60.dp), + text = "${settingModel.danmakuScreenPart}%", + color = MaterialTheme.colorScheme.onBackground, + style = MaterialTheme.typography.titleMedium, + textAlign = TextAlign.Center + ) + + OutlinedIconButton(onClick = { + viewModel.changeDanmakuScreenPart(settingModel.danmakuScreenPart + 5) + }) { + Icon(imageVector = Icons.Outlined.Add, contentDescription = "+") + } + } + } + } + + +} \ No newline at end of file diff --git a/app/src/main/kotlin/com/muedsa/agetv/ui/navigation/AppNavigation.kt b/app/src/main/kotlin/com/muedsa/agetv/ui/navigation/AppNavigation.kt index 53c52d3..51f5e3c 100644 --- a/app/src/main/kotlin/com/muedsa/agetv/ui/navigation/AppNavigation.kt +++ b/app/src/main/kotlin/com/muedsa/agetv/ui/navigation/AppNavigation.kt @@ -10,6 +10,7 @@ import androidx.navigation.compose.composable import androidx.navigation.navArgument import com.muedsa.agetv.ui.features.detail.AnimeDetailScreen import com.muedsa.agetv.ui.features.home.HomeNavScreen +import com.muedsa.agetv.ui.features.setting.AppSettingScreen import com.muedsa.compose.tv.widget.ErrorMessageBoxState import com.muedsa.compose.tv.widget.NotFoundScreen @@ -48,6 +49,17 @@ fun AppNavigation(navController: NavHostController, errorMsgBoxState: ErrorMessa }) ) { AnimeDetailScreen( + errorMsgBoxState = errorMsgBoxState, + onNavigate = { navItem, pathParams -> + onNavigate(navController, navItem, pathParams) + } + ) + } + + composable( + route = NavigationItems.Setting.path + ) { + AppSettingScreen( errorMsgBoxState = errorMsgBoxState ) } diff --git a/app/src/main/kotlin/com/muedsa/agetv/ui/navigation/NavigationItems.kt b/app/src/main/kotlin/com/muedsa/agetv/ui/navigation/NavigationItems.kt index e6db949..a8c5c1b 100644 --- a/app/src/main/kotlin/com/muedsa/agetv/ui/navigation/NavigationItems.kt +++ b/app/src/main/kotlin/com/muedsa/agetv/ui/navigation/NavigationItems.kt @@ -8,5 +8,7 @@ sealed class NavigationItems( data object Detail : NavigationItems("detail/{animeId}", listOf("{animeId}")) + data object Setting : NavigationItems("setting") + data object NotFound : NavigationItems("not_found") } diff --git a/app/src/main/kotlin/com/muedsa/agetv/viewmodel/AppSettingViewModel.kt b/app/src/main/kotlin/com/muedsa/agetv/viewmodel/AppSettingViewModel.kt new file mode 100644 index 0000000..997e9d7 --- /dev/null +++ b/app/src/main/kotlin/com/muedsa/agetv/viewmodel/AppSettingViewModel.kt @@ -0,0 +1,87 @@ +package com.muedsa.agetv.viewmodel + +import androidx.datastore.preferences.core.edit +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.muedsa.agetv.KEY_DANMAKU_ALPHA +import com.muedsa.agetv.KEY_DANMAKU_ENABLE +import com.muedsa.agetv.KEY_DANMAKU_SCREEN_PART +import com.muedsa.agetv.KEY_DANMAKU_SIZE_SCALE +import com.muedsa.agetv.model.AppSettingModel +import com.muedsa.agetv.model.LazyData +import com.muedsa.agetv.repository.DataStoreRepo +import com.muedsa.uitl.LogUtil +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class AppSettingViewModel @Inject constructor( + private val repo: DataStoreRepo +) : ViewModel() { + + val settingLDSF: StateFlow> = repo.dataStore.data + .map { prefs -> + AppSettingModel( + danmakuEnable = prefs[KEY_DANMAKU_ENABLE] ?: true, + danmakuSizeScale = prefs[KEY_DANMAKU_SIZE_SCALE] ?: 140, + danmakuAlpha = prefs[KEY_DANMAKU_ALPHA] ?: 100, + danmakuScreenPart = prefs[KEY_DANMAKU_SCREEN_PART] ?: 100, + ).let { model -> + LazyData.success(model) + } + } + .catch { + LogUtil.d(it) + emit(LazyData.fail(it)) + } + .stateIn( + scope = viewModelScope, + started = SharingStarted.WhileSubscribed(5000), + initialValue = LazyData.init() + ) + + fun changeDanmakuEnable(enable: Boolean) { + viewModelScope.launch(Dispatchers.IO) { + repo.dataStore.edit { + it[KEY_DANMAKU_ENABLE] = enable + } + } + } + + fun changeDanmakuSizeScale(value: Int) { + if (value in 10..300) { + viewModelScope.launch(Dispatchers.IO) { + repo.dataStore.edit { + it[KEY_DANMAKU_SIZE_SCALE] = value + } + } + } + } + + fun changeDanmakuAlpha(value: Int) { + if (value in 0..100) { + viewModelScope.launch(Dispatchers.IO) { + repo.dataStore.edit { + it[KEY_DANMAKU_ALPHA] = value + } + } + } + } + + fun changeDanmakuScreenPart(value: Int) { + if (value in 10..100) { + viewModelScope.launch(Dispatchers.IO) { + repo.dataStore.edit { + it[KEY_DANMAKU_SCREEN_PART] = value + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/com/muedsa/agetv/viewmodel/PlaybackViewModel.kt b/app/src/main/kotlin/com/muedsa/agetv/viewmodel/PlaybackViewModel.kt index 8a28ed3..1a3a05b 100644 --- a/app/src/main/kotlin/com/muedsa/agetv/viewmodel/PlaybackViewModel.kt +++ b/app/src/main/kotlin/com/muedsa/agetv/viewmodel/PlaybackViewModel.kt @@ -5,23 +5,55 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import androidx.media3.exoplayer.ExoPlayer import com.kuaishou.akdanmaku.data.DanmakuItemData +import com.muedsa.agetv.KEY_DANMAKU_ALPHA +import com.muedsa.agetv.KEY_DANMAKU_ENABLE +import com.muedsa.agetv.KEY_DANMAKU_SCREEN_PART +import com.muedsa.agetv.KEY_DANMAKU_SIZE_SCALE +import com.muedsa.agetv.model.AppSettingModel import com.muedsa.agetv.model.LazyData +import com.muedsa.agetv.repository.DataStoreRepo import com.muedsa.agetv.service.DanDanPlayApiService import com.muedsa.uitl.LogUtil import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import javax.inject.Inject @HiltViewModel class PlaybackViewModel @Inject constructor( - private val danDanPlayApiService: DanDanPlayApiService + private val danDanPlayApiService: DanDanPlayApiService, + private val dateStoreRepo: DataStoreRepo ) : ViewModel() { + val danmakuSettingLDSF: StateFlow> = dateStoreRepo.dataStore.data + .map { prefs -> + AppSettingModel( + danmakuEnable = prefs[KEY_DANMAKU_ENABLE] ?: true, + danmakuSizeScale = prefs[KEY_DANMAKU_SIZE_SCALE] ?: 140, + danmakuAlpha = prefs[KEY_DANMAKU_ALPHA] ?: 100, + danmakuScreenPart = prefs[KEY_DANMAKU_SCREEN_PART] ?: 100, + ).let { model -> + LazyData.success(model) + } + } + .catch { + LogUtil.d(it) + emit(LazyData.fail(it)) + } + .stateIn( + scope = viewModelScope, + started = SharingStarted.WhileSubscribed(5000), + initialValue = LazyData.init() + ) + private val _danmakuListLDSF = MutableStateFlow(LazyData.init>()) val danmakuListLDSF: StateFlow>> = _danmakuListLDSF diff --git a/app/src/main/kotlin/com/muedsa/compose/tv/widget/player/DanmakuVideoPlayer.kt b/app/src/main/kotlin/com/muedsa/compose/tv/widget/player/DanmakuVideoPlayer.kt index 0784465..6c009ce 100644 --- a/app/src/main/kotlin/com/muedsa/compose/tv/widget/player/DanmakuVideoPlayer.kt +++ b/app/src/main/kotlin/com/muedsa/compose/tv/widget/player/DanmakuVideoPlayer.kt @@ -69,6 +69,7 @@ import kotlin.time.toDuration @Composable fun DanmakuVideoPlayer( debug: Boolean = false, + danmakuConfigSetting: DanmakuConfig.() -> Unit = {}, danmakuPlayerInit: DanmakuPlayer.() -> Unit = {}, videoPlayerBuilderSetting: ExoPlayer.Builder.() -> Unit = {}, videoPlayerInit: ExoPlayer.() -> Unit, @@ -79,9 +80,7 @@ fun DanmakuVideoPlayer( val playerControlTicker = remember { mutableIntStateOf(0) } val danmakuConfig = remember { - DanmakuConfig().apply { - textSizeScale = 1.4f - } + DanmakuConfig().apply(danmakuConfigSetting) } val danmakuPlayer = remember {