diff --git a/app/src/main/java/com/maxrave/simpmusic/data/dataStore/DataStoreManager.kt b/app/src/main/java/com/maxrave/simpmusic/data/dataStore/DataStoreManager.kt index 0156f7c1..dd3fc87c 100644 --- a/app/src/main/java/com/maxrave/simpmusic/data/dataStore/DataStoreManager.kt +++ b/app/src/main/java/com/maxrave/simpmusic/data/dataStore/DataStoreManager.kt @@ -669,6 +669,44 @@ class DataStoreManager( } } + val shouldShowLogInRequiredAlert = + settingsDataStore.data.map { preferences -> + preferences[SHOULD_SHOW_LOG_IN_REQUIRED_ALERT] ?: TRUE + } + + suspend fun setShouldShowLogInRequiredAlert(shouldShow: Boolean) { + withContext(Dispatchers.IO) { + if (shouldShow) { + settingsDataStore.edit { settings -> + settings[SHOULD_SHOW_LOG_IN_REQUIRED_ALERT] = TRUE + } + } else { + settingsDataStore.edit { settings -> + settings[SHOULD_SHOW_LOG_IN_REQUIRED_ALERT] = FALSE + } + } + } + } + + val autoCheckForUpdates = + settingsDataStore.data.map { preferences -> + preferences[AUTO_CHECK_FOR_UPDATES] ?: TRUE + } + + suspend fun setAutoCheckForUpdates(autoCheck: Boolean) { + withContext(Dispatchers.IO) { + if (autoCheck) { + settingsDataStore.edit { settings -> + settings[AUTO_CHECK_FOR_UPDATES] = TRUE + } + } else { + settingsDataStore.edit { settings -> + settings[AUTO_CHECK_FOR_UPDATES] = FALSE + } + } + } + } + companion object Settings { val COOKIE = stringPreferencesKey("cookie") val LOGGED_IN = stringPreferencesKey("logged_in") @@ -711,6 +749,8 @@ class DataStoreManager( val PROXY_HOST = stringPreferencesKey("proxy_host") val PROXY_PORT = intPreferencesKey("proxy_port") val ENDLESS_QUEUE = stringPreferencesKey("endless_queue") + val SHOULD_SHOW_LOG_IN_REQUIRED_ALERT = stringPreferencesKey("should_show_log_in_required_alert") + val AUTO_CHECK_FOR_UPDATES = stringPreferencesKey("auto_check_for_updates") const val REPEAT_MODE_OFF = "REPEAT_MODE_OFF" const val REPEAT_ONE = "REPEAT_ONE" const val REPEAT_ALL = "REPEAT_ALL" diff --git a/app/src/main/java/com/maxrave/simpmusic/ui/MainActivity.kt b/app/src/main/java/com/maxrave/simpmusic/ui/MainActivity.kt index 0ceef248..610ab29e 100644 --- a/app/src/main/java/com/maxrave/simpmusic/ui/MainActivity.kt +++ b/app/src/main/java/com/maxrave/simpmusic/ui/MainActivity.kt @@ -691,90 +691,92 @@ class MainActivity : AppCompatActivity() { // } private fun checkForUpdate() { - viewModel.checkForUpdate() - viewModel.githubResponse.observe(this) { response -> - if (response != null && !this.isInPictureInPictureMode && !viewModel.showedUpdateDialog) { - Log.w("MainActivity", "Check for update") - Log.w("MainActivity", "Current version: ${getString(R.string.version_format, VersionManager.getVersionName())}") - if (response.tagName != getString(R.string.version_format, VersionManager.getVersionName())) { - viewModel.showedUpdateDialog = true - val inputFormat = - SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.getDefault()) - val outputFormat = SimpleDateFormat("dd MMM yyyy HH:mm:ss", Locale.getDefault()) - val formatted = - response.publishedAt?.let { input -> - inputFormat - .parse(input) - ?.let { outputFormat.format(it) } - } - val scrollView = - ScrollView(this) - .apply { + if (viewModel.shouldCheckForUpdate()) { + viewModel.checkForUpdate() + viewModel.githubResponse.observe(this) { response -> + if (response != null && !this.isInPictureInPictureMode && !viewModel.showedUpdateDialog) { + Log.w("MainActivity", "Check for update") + Log.w("MainActivity", "Current version: ${getString(R.string.version_format, VersionManager.getVersionName())}") + if (response.tagName != getString(R.string.version_format, VersionManager.getVersionName())) { + viewModel.showedUpdateDialog = true + val inputFormat = + SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.getDefault()) + val outputFormat = SimpleDateFormat("dd MMM yyyy HH:mm:ss", Locale.getDefault()) + val formatted = + response.publishedAt?.let { input -> + inputFormat + .parse(input) + ?.let { outputFormat.format(it) } + } + val scrollView = + ScrollView(this) + .apply { + layoutParams = + LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT, + ) + } + val layout = + LinearLayout(this).apply { + orientation = LinearLayout.VERTICAL layoutParams = LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT, ) + setPadding(24, 24, 24, 12) } - val layout = - LinearLayout(this).apply { - orientation = LinearLayout.VERTICAL - layoutParams = - LinearLayout.LayoutParams( - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.WRAP_CONTENT, - ) - setPadding(24, 24, 24, 12) - } - layout.addView( - TextView(this).apply { - text = - getString( - R.string.update_message, - response.tagName, - formatted, - "", - ) - textSize = 13f - layoutParams = - MarginLayoutParams( - MarginLayoutParams.MATCH_PARENT, - MarginLayoutParams.WRAP_CONTENT, - ).apply { - setMargins(42, 8, 42, 0) - } - }, - ) - layout.addView( - TextView(this).apply { - text = markdownToHtml(response.body ?: "") - textSize = 13f - autoLinkMask = Linkify.ALL - setLineSpacing(0f, 1.2f) - layoutParams = - MarginLayoutParams( - MarginLayoutParams.MATCH_PARENT, - MarginLayoutParams.WRAP_CONTENT, - ).apply { - setMargins(42, 0, 42, 24) - } - }, - ) - scrollView.addView(layout) - - MaterialAlertDialogBuilder(this) - .setTitle(getString(R.string.update_available)) - .setView(scrollView) - .setPositiveButton(getString(R.string.download)) { _, _ -> - val browserIntent = - Intent( - Intent.ACTION_VIEW, - Uri.parse(response.assets?.firstOrNull()?.browserDownloadUrl), - ) - startActivity(browserIntent) - }.setNegativeButton(getString(R.string.cancel)) { dialog, _ -> - dialog.dismiss() - }.show() + layout.addView( + TextView(this).apply { + text = + getString( + R.string.update_message, + response.tagName, + formatted, + "", + ) + textSize = 13f + layoutParams = + MarginLayoutParams( + MarginLayoutParams.MATCH_PARENT, + MarginLayoutParams.WRAP_CONTENT, + ).apply { + setMargins(42, 8, 42, 0) + } + }, + ) + layout.addView( + TextView(this).apply { + text = markdownToHtml(response.body ?: "") + textSize = 13f + autoLinkMask = Linkify.ALL + setLineSpacing(0f, 1.2f) + layoutParams = + MarginLayoutParams( + MarginLayoutParams.MATCH_PARENT, + MarginLayoutParams.WRAP_CONTENT, + ).apply { + setMargins(42, 0, 42, 24) + } + }, + ) + scrollView.addView(layout) + + MaterialAlertDialogBuilder(this) + .setTitle(getString(R.string.update_available)) + .setView(scrollView) + .setPositiveButton(getString(R.string.download)) { _, _ -> + val browserIntent = + Intent( + Intent.ACTION_VIEW, + Uri.parse(response.assets?.firstOrNull()?.browserDownloadUrl), + ) + startActivity(browserIntent) + }.setNegativeButton(getString(R.string.cancel)) { dialog, _ -> + dialog.dismiss() + }.show() + } } } } diff --git a/app/src/main/java/com/maxrave/simpmusic/ui/screen/home/HomeScreen.kt b/app/src/main/java/com/maxrave/simpmusic/ui/screen/home/HomeScreen.kt index f13fc631..ae471860 100644 --- a/app/src/main/java/com/maxrave/simpmusic/ui/screen/home/HomeScreen.kt +++ b/app/src/main/java/com/maxrave/simpmusic/ui/screen/home/HomeScreen.kt @@ -11,6 +11,7 @@ import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.shrinkVertically import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.clickable import androidx.compose.foundation.gestures.snapping.SnapLayoutInfoProvider import androidx.compose.foundation.gestures.snapping.SnapPosition import androidx.compose.foundation.gestures.snapping.rememberSnapFlingBehavior @@ -38,6 +39,7 @@ import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Checkbox import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Text import androidx.compose.material3.TextButton @@ -171,16 +173,39 @@ fun HomeScreen( } if (shouldShowLogInAlert) { + var doNotShowAgain by rememberSaveable { + mutableStateOf(false) + } AlertDialog( title = { Text(stringResource(R.string.warning)) }, text = { - Text(text = stringResource(R.string.log_in_warning)) + Column { + Text(text = stringResource(R.string.log_in_warning)) + Spacer(modifier = Modifier.height(4.dp)) + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = + Modifier + .clickable { + doNotShowAgain = !doNotShowAgain + }.fillMaxWidth(), + ) { + Checkbox( + checked = doNotShowAgain, + onCheckedChange = { + doNotShowAgain = it + }, + ) + Spacer(modifier = Modifier.width(5.dp)) + Text(stringResource(R.string.do_not_show_again)) + } + } }, confirmButton = { TextButton(onClick = { - viewModel.doneShowLogInAlert() + viewModel.doneShowLogInAlert(doNotShowAgain) navController.navigateSafe(R.id.action_global_logInFragment) }) { Text(stringResource(R.string.go_to_log_in_page)) @@ -188,7 +213,7 @@ fun HomeScreen( }, dismissButton = { TextButton(onClick = { - viewModel.doneShowLogInAlert() + viewModel.doneShowLogInAlert(doNotShowAgain) }) { Text(stringResource(R.string.cancel)) } diff --git a/app/src/main/java/com/maxrave/simpmusic/ui/screen/home/SettingScreen.kt b/app/src/main/java/com/maxrave/simpmusic/ui/screen/home/SettingScreen.kt index f2e1b06f..bafbebcc 100644 --- a/app/src/main/java/com/maxrave/simpmusic/ui/screen/home/SettingScreen.kt +++ b/app/src/main/java/com/maxrave/simpmusic/ui/screen/home/SettingScreen.kt @@ -188,6 +188,7 @@ fun SettingScreen( val proxyType by viewModel.proxyType.collectAsStateWithLifecycle() val proxyHost by viewModel.proxyHost.collectAsStateWithLifecycle() val proxyPort by viewModel.proxyPort.collectAsStateWithLifecycle() + val autoCheckUpdate by viewModel.autoCheckUpdate.collectAsStateWithLifecycle() var checkForUpdateSubtitle by rememberSaveable { mutableStateOf("") } @@ -1117,6 +1118,11 @@ fun SettingScreen( navController.navigateSafe(R.id.action_global_creditFragment) }, ) + SettingItem( + title = stringResource(R.string.auto_check_for_update), + subtitle = stringResource(R.string.auto_check_for_update_description), + switch = (autoCheckUpdate to { viewModel.setAutoCheckUpdate(it) }), + ) SettingItem( title = stringResource(R.string.check_for_update), subtitle = checkForUpdateSubtitle, diff --git a/app/src/main/java/com/maxrave/simpmusic/viewModel/HomeViewModel.kt b/app/src/main/java/com/maxrave/simpmusic/viewModel/HomeViewModel.kt index b534fb09..9990dd3b 100644 --- a/app/src/main/java/com/maxrave/simpmusic/viewModel/HomeViewModel.kt +++ b/app/src/main/java/com/maxrave/simpmusic/viewModel/HomeViewModel.kt @@ -3,7 +3,6 @@ package com.maxrave.simpmusic.viewModel import android.app.Application import android.util.Log import android.widget.Toast -import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import androidx.media3.common.util.UnstableApi import androidx.media3.exoplayer.offline.Download @@ -11,6 +10,7 @@ import com.maxrave.simpmusic.R import com.maxrave.simpmusic.common.DownloadState import com.maxrave.simpmusic.common.SELECTED_LANGUAGE import com.maxrave.simpmusic.common.SUPPORTED_LANGUAGE +import com.maxrave.simpmusic.data.dataStore.DataStoreManager.Settings.TRUE import com.maxrave.simpmusic.data.db.entities.LocalPlaylistEntity import com.maxrave.simpmusic.data.db.entities.PairSongLocalPlaylist import com.maxrave.simpmusic.data.db.entities.SongEntity @@ -34,11 +34,9 @@ import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking - import java.time.LocalDateTime @UnstableApi - class HomeViewModel( private val application: Application, ) : BaseViewModel(application) { @@ -79,7 +77,11 @@ class HomeViewModel( val showLogInAlert: StateFlow = _showLogInAlert init { - if (runBlocking { dataStoreManager.cookie.first() }.isEmpty()) { + if (runBlocking { dataStoreManager.cookie.first() }.isEmpty() && + runBlocking { + dataStoreManager.shouldShowLogInRequiredAlert.first() == TRUE + } + ) { _showLogInAlert.update { true } } homeJob = Job() @@ -128,8 +130,13 @@ class HomeViewModel( } } - fun doneShowLogInAlert() { - _showLogInAlert.update { false } + fun doneShowLogInAlert(neverShowAgain: Boolean = false) { + viewModelScope.launch { + _showLogInAlert.update { false } + if (neverShowAgain) { + dataStoreManager.setShouldShowLogInRequiredAlert(false) + } + } } fun getHomeItemList(params: String? = null) { diff --git a/app/src/main/java/com/maxrave/simpmusic/viewModel/SettingsViewModel.kt b/app/src/main/java/com/maxrave/simpmusic/viewModel/SettingsViewModel.kt index fb3a7b3a..cb0af046 100644 --- a/app/src/main/java/com/maxrave/simpmusic/viewModel/SettingsViewModel.kt +++ b/app/src/main/java/com/maxrave/simpmusic/viewModel/SettingsViewModel.kt @@ -121,6 +121,8 @@ class SettingsViewModel( val proxyHost: StateFlow = _proxyHost private var _proxyPort = MutableStateFlow(8000) val proxyPort: StateFlow = _proxyPort + private var _autoCheckUpdate = MutableStateFlow(false) + val autoCheckUpdate: StateFlow = _autoCheckUpdate private var _alertData: MutableStateFlow = MutableStateFlow(null) val alertData: StateFlow = _alertData @@ -167,11 +169,27 @@ class SettingsViewModel( getUsingProxy() getCanvasCache() getTranslucentBottomBar() + getAutoCheckUpdate() viewModelScope.launch { calculateDataFraction() } } + private fun getAutoCheckUpdate() { + viewModelScope.launch { + dataStoreManager.autoCheckForUpdates.collect { autoCheckUpdate -> + _autoCheckUpdate.value = autoCheckUpdate == DataStoreManager.TRUE + } + } + } + + fun setAutoCheckUpdate(autoCheckUpdate: Boolean) { + viewModelScope.launch { + dataStoreManager.setAutoCheckForUpdates(autoCheckUpdate) + getAutoCheckUpdate() + } + } + private fun getCanvasCache() { _canvasCacheSize.value = canvasCache.cacheSpace } @@ -266,20 +284,20 @@ class SettingsViewModel( it.copy( otherApp = otherApp.toFloat().div(totalByte.toFloat()), downloadCache = - downloadCache.cacheSpace - .bytesToMB() - .toFloat() - .div(totalByte.toFloat()), + downloadCache.cacheSpace + .bytesToMB() + .toFloat() + .div(totalByte.toFloat()), playerCache = - playerCache.cacheSpace - .bytesToMB() - .toFloat() - .div(totalByte.toFloat()), + playerCache.cacheSpace + .bytesToMB() + .toFloat() + .div(totalByte.toFloat()), canvasCache = - canvasCache.cacheSpace - .bytesToMB() - .toFloat() - .div(totalByte.toFloat()), + canvasCache.cacheSpace + .bytesToMB() + .toFloat() + .div(totalByte.toFloat()), thumbCache = thumbSize.toFloat().div(totalByte.toFloat()), freeSpace = freeSpace.toFloat().div(totalByte.toFloat()), appDatabase = databaseSize.toFloat().div(totalByte.toFloat()), diff --git a/app/src/main/java/com/maxrave/simpmusic/viewModel/SharedViewModel.kt b/app/src/main/java/com/maxrave/simpmusic/viewModel/SharedViewModel.kt index 808e1307..e9736093 100644 --- a/app/src/main/java/com/maxrave/simpmusic/viewModel/SharedViewModel.kt +++ b/app/src/main/java/com/maxrave/simpmusic/viewModel/SharedViewModel.kt @@ -1587,6 +1587,8 @@ class SharedViewModel( _homeRefresh.value = false } + fun shouldCheckForUpdate(): Boolean = runBlocking { dataStoreManager.autoCheckForUpdates.first() == TRUE } + fun runWorker() { Log.w("Check Worker", "Worker") val request = diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index ae8458de..57d6999f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -379,4 +379,7 @@ Lyrics provided by LRCLIB Sync this playlist to YouTube Music first Endless queue + Do not show again + Automatic check for update + Checking for update when you open app \ No newline at end of file