6.0.12 commit
This commit is contained in:
parent
87e84882fb
commit
b4b850baba
|
@ -126,8 +126,8 @@ android {
|
||||||
buildConfig true
|
buildConfig true
|
||||||
}
|
}
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
versionCode 3020211
|
versionCode 3020212
|
||||||
versionName "6.0.11"
|
versionName "6.0.12"
|
||||||
|
|
||||||
applicationId "ac.mdiq.podcini.R"
|
applicationId "ac.mdiq.podcini.R"
|
||||||
def commit = ""
|
def commit = ""
|
||||||
|
|
|
@ -82,7 +82,7 @@ object DownloadRequestCreator {
|
||||||
|
|
||||||
private fun getMediafilePath(media: EpisodeMedia): String {
|
private fun getMediafilePath(media: EpisodeMedia): String {
|
||||||
val item = media.episode ?: return ""
|
val item = media.episode ?: return ""
|
||||||
Logd(TAG, "item managed: ${item?.isManaged()}")
|
Logd(TAG, "item managed: ${item.isManaged()}")
|
||||||
val title = item.feed?.title?:return ""
|
val title = item.feed?.title?:return ""
|
||||||
val mediaPath = (MEDIA_DOWNLOADPATH + FileNameGenerator.generateFileName(title))
|
val mediaPath = (MEDIA_DOWNLOADPATH + FileNameGenerator.generateFileName(title))
|
||||||
return UserPreferences.getDataFolder(mediaPath).toString() + "/"
|
return UserPreferences.getDataFolder(mediaPath).toString() + "/"
|
||||||
|
|
|
@ -8,6 +8,7 @@ import ac.mdiq.podcini.net.sync.model.EpisodeAction
|
||||||
import ac.mdiq.podcini.net.sync.model.EpisodeAction.Companion.readFromJsonObject
|
import ac.mdiq.podcini.net.sync.model.EpisodeAction.Companion.readFromJsonObject
|
||||||
import ac.mdiq.podcini.net.sync.model.SyncServiceException
|
import ac.mdiq.podcini.net.sync.model.SyncServiceException
|
||||||
import ac.mdiq.podcini.preferences.ExportWriter
|
import ac.mdiq.podcini.preferences.ExportWriter
|
||||||
|
import ac.mdiq.podcini.preferences.OpmlTransporter.*
|
||||||
import ac.mdiq.podcini.preferences.UserPreferences.getDataFolder
|
import ac.mdiq.podcini.preferences.UserPreferences.getDataFolder
|
||||||
import ac.mdiq.podcini.storage.database.Episodes.getEpisodeByGuidOrUrl
|
import ac.mdiq.podcini.storage.database.Episodes.getEpisodeByGuidOrUrl
|
||||||
import ac.mdiq.podcini.storage.database.Episodes.getEpisodes
|
import ac.mdiq.podcini.storage.database.Episodes.getEpisodes
|
||||||
|
@ -15,12 +16,11 @@ import ac.mdiq.podcini.storage.database.Feeds.getFeedList
|
||||||
import ac.mdiq.podcini.storage.database.RealmDB.realm
|
import ac.mdiq.podcini.storage.database.RealmDB.realm
|
||||||
import ac.mdiq.podcini.storage.database.RealmDB.upsertBlk
|
import ac.mdiq.podcini.storage.database.RealmDB.upsertBlk
|
||||||
import ac.mdiq.podcini.storage.model.Episode
|
import ac.mdiq.podcini.storage.model.Episode
|
||||||
import ac.mdiq.podcini.storage.model.Feed
|
|
||||||
import ac.mdiq.podcini.preferences.OpmlTransporter.*
|
|
||||||
import ac.mdiq.podcini.storage.database.Episodes.getEpisodeByTitle
|
|
||||||
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
import ac.mdiq.podcini.storage.model.EpisodeFilter
|
||||||
import ac.mdiq.podcini.storage.utils.EpisodeUtil.hasAlmostEnded
|
|
||||||
import ac.mdiq.podcini.storage.model.EpisodeSortOrder
|
import ac.mdiq.podcini.storage.model.EpisodeSortOrder
|
||||||
|
import ac.mdiq.podcini.storage.model.Feed
|
||||||
|
import ac.mdiq.podcini.storage.utils.EpisodeUtil.hasAlmostEnded
|
||||||
|
import ac.mdiq.podcini.storage.utils.FileNameGenerator.generateFileName
|
||||||
import ac.mdiq.podcini.ui.activity.OpmlImportActivity
|
import ac.mdiq.podcini.ui.activity.OpmlImportActivity
|
||||||
import ac.mdiq.podcini.ui.activity.PreferenceActivity
|
import ac.mdiq.podcini.ui.activity.PreferenceActivity
|
||||||
import ac.mdiq.podcini.util.Logd
|
import ac.mdiq.podcini.util.Logd
|
||||||
|
@ -709,6 +709,9 @@ class ImportExportPreferencesFragment : PreferenceFragmentCompat() {
|
||||||
|
|
||||||
object MediaFilesTransporter {
|
object MediaFilesTransporter {
|
||||||
private val TAG: String = MediaFilesTransporter::class.simpleName ?: "Anonymous"
|
private val TAG: String = MediaFilesTransporter::class.simpleName ?: "Anonymous"
|
||||||
|
var feed: Feed? = null
|
||||||
|
val nameFeedMap: MutableMap<String, Feed> = mutableMapOf()
|
||||||
|
val nameEpisodeMap: MutableMap<String, Episode> = mutableMapOf()
|
||||||
@Throws(IOException::class)
|
@Throws(IOException::class)
|
||||||
fun exportToDocument(uri: Uri, context: Context) {
|
fun exportToDocument(uri: Uri, context: Context) {
|
||||||
try {
|
try {
|
||||||
|
@ -753,6 +756,13 @@ class ImportExportPreferencesFragment : PreferenceFragmentCompat() {
|
||||||
private fun copyRecursive(context: Context, srcFile: DocumentFile, srcRootDir: DocumentFile, destRootDir: File) {
|
private fun copyRecursive(context: Context, srcFile: DocumentFile, srcRootDir: DocumentFile, destRootDir: File) {
|
||||||
val relativePath = srcFile.uri.path?.substring(srcRootDir.uri.path!!.length+1) ?: return
|
val relativePath = srcFile.uri.path?.substring(srcRootDir.uri.path!!.length+1) ?: return
|
||||||
if (srcFile.isDirectory) {
|
if (srcFile.isDirectory) {
|
||||||
|
Logd(TAG, "copyRecursive folder title: $relativePath")
|
||||||
|
feed = nameFeedMap[relativePath] ?: return
|
||||||
|
Logd(TAG, "copyRecursive found feed: ${feed?.title}")
|
||||||
|
nameEpisodeMap.clear()
|
||||||
|
feed!!.episodes.forEach { e ->
|
||||||
|
if (!e.title.isNullOrEmpty()) nameEpisodeMap[generateFileName(e.title!!)] = e
|
||||||
|
}
|
||||||
val destFile = File(destRootDir, relativePath)
|
val destFile = File(destRootDir, relativePath)
|
||||||
if (!destFile.exists()) destFile.mkdirs()
|
if (!destFile.exists()) destFile.mkdirs()
|
||||||
srcFile.listFiles().forEach { file ->
|
srcFile.listFiles().forEach { file ->
|
||||||
|
@ -763,13 +773,18 @@ class ImportExportPreferencesFragment : PreferenceFragmentCompat() {
|
||||||
if (nameParts.size < 3) return
|
if (nameParts.size < 3) return
|
||||||
val ext = nameParts[nameParts.size-1]
|
val ext = nameParts[nameParts.size-1]
|
||||||
val title = nameParts.dropLast(2).joinToString(".")
|
val title = nameParts.dropLast(2).joinToString(".")
|
||||||
Logd(TAG, "copyRecursive title: $title")
|
Logd(TAG, "copyRecursive file title: $title")
|
||||||
val episode = getEpisodeByTitle(title) ?: return
|
val episode = nameEpisodeMap[title] ?: return
|
||||||
|
Logd(TAG, "copyRecursive found episode: ${episode.title}")
|
||||||
val destName = "$title.${episode.id}.$ext"
|
val destName = "$title.${episode.id}.$ext"
|
||||||
val destFile = File(destRootDir, destName)
|
val destFile = File(destRootDir, destName)
|
||||||
if (!destFile.exists()) {
|
if (!destFile.exists()) {
|
||||||
|
Logd(TAG, "copyRecursive copying file to: ${destFile.absolutePath}")
|
||||||
copyFile(srcFile, destFile, context)
|
copyFile(srcFile, destFile, context)
|
||||||
upsertBlk(episode) { it.media?.setfileUrlOrNull(destFile.name)}
|
upsertBlk(episode) {
|
||||||
|
it.media?.fileUrl = destFile.absolutePath
|
||||||
|
it.media?.setIsDownloaded()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -798,13 +813,24 @@ class ImportExportPreferencesFragment : PreferenceFragmentCompat() {
|
||||||
val exportedDir = DocumentFile.fromTreeUri(context, uri) ?: throw IOException("Backup directory is not valid")
|
val exportedDir = DocumentFile.fromTreeUri(context, uri) ?: throw IOException("Backup directory is not valid")
|
||||||
if (exportedDir.name?.contains("Podcini-MediaFiles") != true) return
|
if (exportedDir.name?.contains("Podcini-MediaFiles") != true) return
|
||||||
val mediaDir = context.getExternalFilesDir("media") ?: return
|
val mediaDir = context.getExternalFilesDir("media") ?: return
|
||||||
exportedDir.listFiles().forEach { file ->
|
val fileList = exportedDir.listFiles()
|
||||||
|
if (fileList.isNotEmpty()) {
|
||||||
|
val feeds = getFeedList()
|
||||||
|
feeds.forEach { f ->
|
||||||
|
if (!f.title.isNullOrEmpty()) nameFeedMap[generateFileName(f.title!!)] = f
|
||||||
|
}
|
||||||
|
fileList.forEach { file ->
|
||||||
copyRecursive(context, file, exportedDir, mediaDir)
|
copyRecursive(context, file, exportedDir, mediaDir)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
Log.e(TAG, Log.getStackTraceString(e))
|
Log.e(TAG, Log.getStackTraceString(e))
|
||||||
throw e
|
throw e
|
||||||
} finally { }
|
} finally {
|
||||||
|
nameFeedMap.clear()
|
||||||
|
nameEpisodeMap.clear()
|
||||||
|
feed = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ object FileNameGenerator {
|
||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
fun generateFileName(string: String): String {
|
fun generateFileName(string: String): String {
|
||||||
var string = StringUtils.stripAccents(string)
|
val string = StringUtils.stripAccents(string)
|
||||||
val buf = StringBuilder()
|
val buf = StringBuilder()
|
||||||
for (c in string) {
|
for (c in string) {
|
||||||
if (Character.isSpaceChar(c) && (buf.isEmpty() || Character.isSpaceChar(buf[buf.length - 1]))) continue
|
if (Character.isSpaceChar(c) && (buf.isEmpty() || Character.isSpaceChar(buf[buf.length - 1]))) continue
|
||||||
|
|
|
@ -618,6 +618,9 @@ import java.util.concurrent.Semaphore
|
||||||
} else episodes.addAll(feed_.episodes)
|
} else episodes.addAll(feed_.episodes)
|
||||||
val sortOrder = fromCode(feed_.preferences?.sortOrderCode?:0)
|
val sortOrder = fromCode(feed_.preferences?.sortOrderCode?:0)
|
||||||
if (sortOrder != null) getPermutor(sortOrder).reorder(episodes)
|
if (sortOrder != null) getPermutor(sortOrder).reorder(episodes)
|
||||||
|
// episodes.forEach {
|
||||||
|
// Logd(TAG, "Episode: ${it.title} ${it.media?.downloaded} ${it.media?.fileUrl}")
|
||||||
|
// }
|
||||||
if (onInit) {
|
if (onInit) {
|
||||||
var hasNonMediaItems = false
|
var hasNonMediaItems = false
|
||||||
for (item in episodes) {
|
for (item in episodes) {
|
||||||
|
|
|
@ -22,11 +22,11 @@
|
||||||
search:keywords="@string/import_export_search_keywords"
|
search:keywords="@string/import_export_search_keywords"
|
||||||
android:title="@string/media_files_export_label"
|
android:title="@string/media_files_export_label"
|
||||||
android:summary="@string/media_files_export_summary"/>
|
android:summary="@string/media_files_export_summary"/>
|
||||||
<!-- <Preference-->
|
<Preference
|
||||||
<!-- android:key="prefMediaFilesImport"-->
|
android:key="prefMediaFilesImport"
|
||||||
<!-- search:keywords="@string/import_export_search_keywords"-->
|
search:keywords="@string/import_export_search_keywords"
|
||||||
<!-- android:title="@string/media_files_import_label"-->
|
android:title="@string/media_files_import_label"
|
||||||
<!-- android:summary="@string/media_files_import_summary"/>-->
|
android:summary="@string/media_files_import_summary"/>
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory android:title="@string/preferences">
|
<PreferenceCategory android:title="@string/preferences">
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
# 6.0.12
|
||||||
|
|
||||||
|
* re-enabled import of downloaded media files, which can be used to migrate from 5.5.4. Media files imported are restricted to existing feeds and episodes.
|
||||||
|
* importing media files is only allowed from a directory with name containing "Podcini-MediaFiles"
|
||||||
|
* if you have imported some media files exported from 5.5.4 using version 6.0.10, these files are junk. You can opt for clearing storage or re-installing version 6, or you can ignore them for now as I plan to provide media file management functionality in the near future.
|
||||||
|
|
||||||
# 6.0.11
|
# 6.0.11
|
||||||
|
|
||||||
* This is a minor release of subtraction: import of downloaded media files is temporarily disabled as it's more complicated than I thought. Imported file names from earlier versions aren't easily recognizable.
|
* This is a minor release of subtraction: import of downloaded media files is temporarily disabled as it's more complicated than I thought. Imported file names from earlier versions aren't easily recognizable.
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
Version 6.0.12 brings several changes:
|
||||||
|
|
||||||
|
* re-enabled import of downloaded media files, which can be used to migrate from 5.5.4. Media files imported are restricted to existing feeds and episodes.
|
||||||
|
* importing media files is only allowed from a directory with name containing "Podcini-MediaFiles"
|
||||||
|
* if you have imported some media files exported from 5.5.4 using version 6.0.10, these files are junk. You can opt for clearing storage or re-installing version 6, or you can ignore them for now as I plan to provide media file management functionality in the near future.
|
|
@ -13,15 +13,13 @@ the following can be imported to it from Settings -> Import/Export:
|
||||||
* preferences files
|
* preferences files
|
||||||
* OPML file
|
* OPML file
|
||||||
* json file of episodes progress
|
* json file of episodes progress
|
||||||
* downloaded media files (5.5.4 only, but currently not enabled for import)
|
* downloaded media files (5.5.4 only)
|
||||||
|
|
||||||
An OPML file should be imported before importing episodes progress, but you can always re-do any of the above
|
An OPML file should be imported before importing episodes progress, but you can always re-do any of the above
|
||||||
|
|
||||||
These files can be best exported in version 5.5.4 (or 5.5.3, or 5.5.2) in Settings -> Import/Export
|
These files can be best exported in version 5.5.4 (or 5.5.3, or 5.5.2) in Settings -> Import/Export
|
||||||
|
|
||||||
Then your subscriptions, listening progress, favorites, and app preferences will be updated.
|
Then your subscriptions, listening progress, favorites, downloaded media files, and app preferences will be updated.
|
||||||
|
|
||||||
Unfortunately, media files will need to be separately downloaded.
|
|
||||||
|
|
||||||
* Note you can also export the progress from version 5.5.2 if you don't have 5.5.3, the difference is only that 5.5.3 includes the info about how far out an episode has been played, which can be useful when looking at statistics. Without that info, you can get similar (albeit not exactly the same) results by "Include marked played" in the filter of the statistics view.
|
* Note you can also export the progress from version 5.5.2 if you don't have 5.5.3, the difference is only that 5.5.3 includes the info about how far out an episode has been played, which can be useful when looking at statistics. Without that info, you can get similar (albeit not exactly the same) results by "Include marked played" in the filter of the statistics view.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue