Merge pull request #6952 from Bnyro/master

fix: backup file names contain (for some file systems) invalid char ':'
This commit is contained in:
Bnyro 2025-01-13 17:17:39 +01:00 committed by GitHub
commit 83d257d513
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 18 additions and 11 deletions

View File

@ -201,7 +201,7 @@ object ImportHelper {
val playlistName = lines[1].split(",").reversed().getOrNull(2) val playlistName = lines[1].split(",").reversed().getOrNull(2)
// the playlist name can be undefined in some cases, e.g. watch later lists // the playlist name can be undefined in some cases, e.g. watch later lists
playlist.name = playlistName ?: TextUtils.defaultPlaylistName playlist.name = playlistName ?: TextUtils.getFileSafeTimeStampNow()
// start directly at the beginning if header playlist info such as name is missing // start directly at the beginning if header playlist info such as name is missing
val startIndex = if (playlistName == null) { val startIndex = if (playlistName == null) {
@ -235,7 +235,7 @@ object ImportHelper {
ImportFormat.URLSORIDS -> { ImportFormat.URLSORIDS -> {
activity.contentResolver.openInputStream(uri)?.use { inputStream -> activity.contentResolver.openInputStream(uri)?.use { inputStream ->
val playlist = PipedImportPlaylist(name = TextUtils.defaultPlaylistName) val playlist = PipedImportPlaylist(name = TextUtils.getFileSafeTimeStampNow())
playlist.videos = inputStream.bufferedReader().readLines() playlist.videos = inputStream.bufferedReader().readLines()
.flatMap { it.split(",") } .flatMap { it.split(",") }

View File

@ -26,7 +26,7 @@ class DownloadPlaylistDialog : DialogFragment() {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
playlistId = requireArguments().getString(IntentData.playlistId)!! playlistId = requireArguments().getString(IntentData.playlistId)!!
playlistName = requireArguments().getString(IntentData.playlistName) ?: TextUtils.defaultPlaylistName playlistName = requireArguments().getString(IntentData.playlistName) ?: TextUtils.getFileSafeTimeStampNow()
playlistType = requireArguments().serializable(IntentData.playlistType)!! playlistType = requireArguments().serializable(IntentData.playlistType)!!
} }

View File

@ -20,7 +20,7 @@ class ImportTempPlaylistDialog : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val title = arguments?.getString(IntentData.playlistName) val title = arguments?.getString(IntentData.playlistName)
?.takeIf { it.isNotEmpty() } ?.takeIf { it.isNotEmpty() }
?: TextUtils.defaultPlaylistName ?: TextUtils.getFileSafeTimeStampNow()
val videoIds = arguments?.getStringArray(IntentData.videoIds).orEmpty() val videoIds = arguments?.getStringArray(IntentData.videoIds).orEmpty()
return MaterialAlertDialogBuilder(requireContext()) return MaterialAlertDialogBuilder(requireContext())

View File

@ -17,17 +17,15 @@ import com.github.libretube.ui.base.BasePreferenceFragment
import com.github.libretube.ui.dialogs.BackupDialog import com.github.libretube.ui.dialogs.BackupDialog
import com.github.libretube.ui.dialogs.BackupDialog.Companion.BACKUP_DIALOG_REQUEST_KEY import com.github.libretube.ui.dialogs.BackupDialog.Companion.BACKUP_DIALOG_REQUEST_KEY
import com.github.libretube.ui.dialogs.RequireRestartDialog import com.github.libretube.ui.dialogs.RequireRestartDialog
import com.github.libretube.util.TextUtils
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
class BackupRestoreSettings : BasePreferenceFragment() { class BackupRestoreSettings : BasePreferenceFragment() {
private val backupDateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd-HH:mm:ss")
private var backupFile = BackupFile() private var backupFile = BackupFile()
private var importFormat: ImportFormat = ImportFormat.NEWPIPE private var importFormat: ImportFormat = ImportFormat.NEWPIPE
@ -159,8 +157,8 @@ class BackupRestoreSettings : BasePreferenceFragment() {
) { _, resultBundle -> ) { _, resultBundle ->
val encodedBackupFile = resultBundle.getString(IntentData.backupFile)!! val encodedBackupFile = resultBundle.getString(IntentData.backupFile)!!
backupFile = Json.decodeFromString(encodedBackupFile) backupFile = Json.decodeFromString(encodedBackupFile)
val timestamp = backupDateTimeFormatter.format(LocalDateTime.now()) val timestamp = TextUtils.getFileSafeTimeStampNow()
createBackupFile.launch("libretube-backup-$timestamp.json") createBackupFile.launch("libretube-backup-${timestamp}.json")
} }
val advancedBackup = findPreference<Preference>("backup") val advancedBackup = findPreference<Preference>("backup")
advancedBackup?.setOnPreferenceClickListener { advancedBackup?.setOnPreferenceClickListener {

View File

@ -18,7 +18,6 @@ import java.time.ZoneId
import java.time.format.DateTimeFormatter import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle import java.time.format.FormatStyle
import java.time.temporal.ChronoUnit import java.time.temporal.ChronoUnit
import java.util.Date
import kotlin.time.Duration import kotlin.time.Duration
import kotlinx.datetime.LocalDate as KotlinLocalDate import kotlinx.datetime.LocalDate as KotlinLocalDate
@ -38,7 +37,10 @@ object TextUtils {
*/ */
private val MEDIUM_DATE_FORMATTER = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM) private val MEDIUM_DATE_FORMATTER = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)
val defaultPlaylistName get() = Date().toString() /**
* Date time formatter which doesn't use any forbidden characters for file names like ':'
*/
private val SAFE_FILENAME_DATETIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd-HH_mm_ss")
/** /**
* Localize the date from a date string, using the medium format. * Localize the date from a date string, using the medium format.
@ -163,4 +165,11 @@ object TextUtils {
} }
return listOfNotNull(uploader, viewsString, uploadDate).joinToString(SEPARATOR) return listOfNotNull(uploader, viewsString, uploadDate).joinToString(SEPARATOR)
} }
/**
* Timestamp of the current time which doesn't use any forbidden characters for file names like ':'
*/
fun getFileSafeTimeStampNow(): String {
return SAFE_FILENAME_DATETIME_FORMATTER.format(LocalDateTime.now())
}
} }