Skip to content

Commit

Permalink
[feature] Support #71, #73
Browse files Browse the repository at this point in the history
  • Loading branch information
SkyD666 committed Dec 28, 2024
1 parent 3e4e75b commit d4a5659
Show file tree
Hide file tree
Showing 16 changed files with 358 additions and 57 deletions.
2 changes: 1 addition & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ android {
minSdk = 24
targetSdk = 35
versionCode = 24
versionName = "2.1-rc01"
versionName = "2.1-rc02"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

Expand Down
4 changes: 4 additions & 0 deletions app/src/main/java/com/skyd/anivu/ext/PreferenceExt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import com.skyd.anivu.model.preference.appearance.feed.FeedDefaultGroupExpandPre
import com.skyd.anivu.model.preference.appearance.feed.FeedListTonalElevationPreference
import com.skyd.anivu.model.preference.appearance.feed.FeedNumberBadgePreference
import com.skyd.anivu.model.preference.appearance.feed.FeedTopBarTonalElevationPreference
import com.skyd.anivu.model.preference.appearance.media.MediaFileFilterPreference
import com.skyd.anivu.model.preference.appearance.media.MediaShowGroupTabPreference
import com.skyd.anivu.model.preference.appearance.media.MediaShowThumbnailPreference
import com.skyd.anivu.model.preference.appearance.read.ReadContentTonalElevationPreference
import com.skyd.anivu.model.preference.appearance.read.ReadTextSizePreference
Expand Down Expand Up @@ -85,6 +87,7 @@ fun Preferences.toSettings(): Settings {
articleItemMinWidth = ArticleItemMinWidthPreference.fromPreferences(this),
searchItemMinWidth = SearchItemMinWidthPreference.fromPreferences(this),
mediaShowThumbnail = MediaShowThumbnailPreference.fromPreferences(this),
mediaShowGroupTab = MediaShowGroupTabPreference.fromPreferences(this),
readTextSize = ReadTextSizePreference.fromPreferences(this),
readContentTonalElevation = ReadContentTonalElevationPreference.fromPreferences(this),
readTopBarTonalElevation = ReadTopBarTonalElevationPreference.fromPreferences(this),
Expand All @@ -100,6 +103,7 @@ fun Preferences.toSettings(): Settings {
articleSwipeRightAction = ArticleSwipeRightActionPreference.fromPreferences(this),
hideEmptyDefault = HideEmptyDefaultPreference.fromPreferences(this),
pickImageMethod = PickImageMethodPreference.fromPreferences(this),
mediaFileFilter = MediaFileFilterPreference.fromPreferences(this),

// RSS
rssSyncFrequency = RssSyncFrequencyPreference.fromPreferences(this),
Expand Down
8 changes: 8 additions & 0 deletions app/src/main/java/com/skyd/anivu/model/preference/Settings.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import com.skyd.anivu.model.preference.appearance.feed.FeedDefaultGroupExpandPre
import com.skyd.anivu.model.preference.appearance.feed.FeedListTonalElevationPreference
import com.skyd.anivu.model.preference.appearance.feed.FeedNumberBadgePreference
import com.skyd.anivu.model.preference.appearance.feed.FeedTopBarTonalElevationPreference
import com.skyd.anivu.model.preference.appearance.media.MediaFileFilterPreference
import com.skyd.anivu.model.preference.appearance.media.MediaShowGroupTabPreference
import com.skyd.anivu.model.preference.appearance.media.MediaShowThumbnailPreference
import com.skyd.anivu.model.preference.appearance.read.ReadContentTonalElevationPreference
import com.skyd.anivu.model.preference.appearance.read.ReadTextSizePreference
Expand Down Expand Up @@ -90,7 +92,9 @@ import com.skyd.anivu.ui.local.LocalFeedTopBarTonalElevation
import com.skyd.anivu.ui.local.LocalHardwareDecode
import com.skyd.anivu.ui.local.LocalHideEmptyDefault
import com.skyd.anivu.ui.local.LocalIgnoreUpdateVersion
import com.skyd.anivu.ui.local.LocalMediaFileFilter
import com.skyd.anivu.ui.local.LocalMediaLibLocation
import com.skyd.anivu.ui.local.LocalMediaShowGroupTab
import com.skyd.anivu.ui.local.LocalMediaShowThumbnail
import com.skyd.anivu.ui.local.LocalNavigationBarLabel
import com.skyd.anivu.ui.local.LocalOpmlExportDir
Expand Down Expand Up @@ -151,6 +155,7 @@ data class Settings(
val articleItemMinWidth: Float = ArticleItemMinWidthPreference.default,
val searchItemMinWidth: Float = SearchItemMinWidthPreference.default,
val mediaShowThumbnail: Boolean = MediaShowThumbnailPreference.default,
val mediaShowGroupTab: Boolean = MediaShowGroupTabPreference.default,
val readTextSize: Float = ReadTextSizePreference.default,
val readContentTonalElevation: Float = ReadContentTonalElevationPreference.default,
val readTopBarTonalElevation: Float = ReadTopBarTonalElevationPreference.default,
Expand All @@ -164,6 +169,7 @@ data class Settings(
val articleSwipeRightAction: String = ArticleSwipeRightActionPreference.default,
val hideEmptyDefault: Boolean = HideEmptyDefaultPreference.default,
val pickImageMethod: String = PickImageMethodPreference.default,
val mediaFileFilter: String = MediaFileFilterPreference.default,
// RSS
val rssSyncFrequency: Long = RssSyncFrequencyPreference.default,
val rssSyncWifiConstraint: Boolean = RssSyncWifiConstraintPreference.default,
Expand Down Expand Up @@ -229,6 +235,7 @@ fun SettingsProvider(
LocalArticleItemMinWidth provides settings.articleItemMinWidth,
LocalSearchItemMinWidth provides settings.searchItemMinWidth,
LocalMediaShowThumbnail provides settings.mediaShowThumbnail,
LocalMediaShowGroupTab provides settings.mediaShowGroupTab,
LocalReadTextSize provides settings.readTextSize,
LocalReadContentTonalElevation provides settings.readContentTonalElevation,
LocalReadTopBarTonalElevation provides settings.readTopBarTonalElevation,
Expand All @@ -242,6 +249,7 @@ fun SettingsProvider(
LocalArticleSwipeRightAction provides settings.articleSwipeRightAction,
LocalHideEmptyDefault provides settings.hideEmptyDefault,
LocalPickImageMethod provides settings.pickImageMethod,
LocalMediaFileFilter provides settings.mediaFileFilter,
// rss
LocalRssSyncFrequency provides settings.rssSyncFrequency,
LocalRssSyncWifiConstraint provides settings.rssSyncWifiConstraint,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.skyd.anivu.model.preference.appearance.media

import android.content.Context
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.stringPreferencesKey
import com.skyd.anivu.R
import com.skyd.anivu.base.BasePreference
import com.skyd.anivu.ext.dataStore
import com.skyd.anivu.ext.getOrDefault
import com.skyd.anivu.ext.put
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

object MediaFileFilterPreference : BasePreference<String> {
private const val MEDIA_FILE_FILTER = "mediaFileFilter"

const val VIDEO_REGEX = ".*\\.(mp4|avi|mkv|mov|flv|wmv|webm|mpg|mpeg|3gp|rmvb|ts|mov|m3u8)\$"
const val AUDIO_REGEX = ".*\\.(mp3|wav|flac|aac|ogg|m4a|wma|opus|alac|aiff|aif)\$"
const val MEDIA_REGEX = "($VIDEO_REGEX)|($AUDIO_REGEX)"
const val ALL_REGEX = ".*"

val values = arrayOf(ALL_REGEX, MEDIA_REGEX, VIDEO_REGEX, AUDIO_REGEX)

override val default = ALL_REGEX

val key = stringPreferencesKey(MEDIA_FILE_FILTER)

fun put(context: Context, scope: CoroutineScope, value: String) {
scope.launch(Dispatchers.IO) {
context.dataStore.put(key, value)
}
}

override fun fromPreferences(preferences: Preferences): String = preferences[key] ?: default

fun toDisplayName(
context: Context,
value: String = context.dataStore.getOrDefault(this),
): String = when (value) {
VIDEO_REGEX -> context.getString(R.string.media_display_filter_video)
AUDIO_REGEX -> context.getString(R.string.media_display_filter_audio)
MEDIA_REGEX -> context.getString(R.string.media_display_filter_media)
ALL_REGEX -> context.getString(R.string.media_display_filter_all)
else -> value
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.skyd.anivu.model.preference.appearance.media

import android.content.Context
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import com.skyd.anivu.base.BasePreference
import com.skyd.anivu.ext.dataStore
import com.skyd.anivu.ext.put
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch

object MediaShowGroupTabPreference : BasePreference<Boolean> {
private const val MEDIA_SHOW_GROUP_TAB = "mediaShowGroupTab"
override val default = true

val key = booleanPreferencesKey(MEDIA_SHOW_GROUP_TAB)

fun put(context: Context, scope: CoroutineScope, value: Boolean) {
scope.launch(Dispatchers.IO) {
context.dataStore.put(key, value)
}
}

override fun fromPreferences(preferences: Preferences): Boolean = preferences[key] ?: default
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,23 @@ package com.skyd.anivu.model.repository

import androidx.collection.LruCache
import androidx.compose.ui.util.fastFirstOrNull
import com.skyd.anivu.appContext
import com.skyd.anivu.base.BaseRepository
import com.skyd.anivu.ext.dataStore
import com.skyd.anivu.ext.validateFileName
import com.skyd.anivu.model.bean.MediaBean
import com.skyd.anivu.model.bean.MediaGroupBean
import com.skyd.anivu.model.bean.MediaGroupBean.Companion.isDefaultGroup
import com.skyd.anivu.model.preference.appearance.media.MediaFileFilterPreference
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.serialization.EncodeDefault
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
Expand Down Expand Up @@ -111,32 +118,45 @@ class MediaRepository @Inject constructor(
}
}

fun requestFiles(path: String, group: MediaGroupBean?): Flow<List<MediaBean>> {
return flow {
val fileJsons = getOrReadMediaLibJson(path).files.appendFiles(
File(path).listFiles().orEmpty().toMutableList().filter { it.exists() }
)
val videoList = (if (group == null) fileJsons else {
val groupName = if (group.isDefaultGroup()) null else group.name
fileJsons.filter { it.groupName == groupName }
}).mapNotNull {
val file = File(path, it.fileName)
if (file.exists()) {
MediaBean(
displayName = it.displayName,
file = file,
)
} else null
}
private val refreshFiles = MutableStateFlow(0)

fun refreshFile(): Flow<Unit> = flow {
refreshFiles.emit((refreshFiles.value + 1) % 100)
emit(Unit)
}

emit(
fun requestFiles(path: String, group: MediaGroupBean?): Flow<List<MediaBean>> {
return combine(
refreshFiles.map {
val fileJsons = getOrReadMediaLibJson(path).files.appendFiles(
File(path).listFiles().orEmpty().toMutableList().filter { it.exists() }
)
val videoList = (if (group == null) fileJsons else {
val groupName = if (group.isDefaultGroup()) null else group.name
fileJsons.filter { it.groupName == groupName }
}).mapNotNull {
val file = File(path, it.fileName)
if (file.exists()) {
MediaBean(
displayName = it.displayName,
file = file,
)
} else null
}
videoList.toMutableList().apply {
fastFirstOrNull { it.name.equals(FOLDER_INFO_JSON_NAME, true) }
?.let { remove(it) }
fastFirstOrNull { it.name.equals(MEDIA_LIB_JSON_NAME, true) }
?.let { remove(it) }
}
)
},
appContext.dataStore.data.map {
it[MediaFileFilterPreference.key] ?: MediaFileFilterPreference.default
}.distinctUntilChanged()
) { videoList, displayFilter ->
videoList.filter {
runCatching { it.file.name.matches(Regex(displayFilter)) }.getOrNull() == true
}
}
}

Expand All @@ -158,7 +178,8 @@ class MediaRepository @Inject constructor(
val validateFileName = newName.validateFileName()
val newFile = File(file.parentFile, validateFileName)
if (file.renameTo(newFile)) {
mediaLibJson.files.firstOrNull { it.fileName == file.name }?.fileName = validateFileName
mediaLibJson.files.firstOrNull { it.fileName == file.name }?.fileName =
validateFileName
writeMediaLibJson(path = path, mediaLibJson)
emit(newFile)
} else {
Expand Down
4 changes: 4 additions & 0 deletions app/src/main/java/com/skyd/anivu/ui/local/LocalValue.kt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import com.skyd.anivu.model.preference.appearance.feed.FeedDefaultGroupExpandPre
import com.skyd.anivu.model.preference.appearance.feed.FeedListTonalElevationPreference
import com.skyd.anivu.model.preference.appearance.feed.FeedNumberBadgePreference
import com.skyd.anivu.model.preference.appearance.feed.FeedTopBarTonalElevationPreference
import com.skyd.anivu.model.preference.appearance.media.MediaFileFilterPreference
import com.skyd.anivu.model.preference.appearance.media.MediaShowGroupTabPreference
import com.skyd.anivu.model.preference.appearance.media.MediaShowThumbnailPreference
import com.skyd.anivu.model.preference.appearance.read.ReadContentTonalElevationPreference
import com.skyd.anivu.model.preference.appearance.read.ReadTextSizePreference
Expand Down Expand Up @@ -99,6 +101,7 @@ val LocalShowArticlePullRefresh = compositionLocalOf { ShowArticlePullRefreshPre
val LocalArticleItemMinWidth = compositionLocalOf { ArticleItemMinWidthPreference.default }
val LocalSearchItemMinWidth = compositionLocalOf { SearchItemMinWidthPreference.default }
val LocalMediaShowThumbnail = compositionLocalOf { MediaShowThumbnailPreference.default }
val LocalMediaShowGroupTab = compositionLocalOf { MediaShowGroupTabPreference.default }
val LocalReadTextSize = compositionLocalOf { ReadTextSizePreference.default }
val LocalReadContentTonalElevation =
compositionLocalOf { ReadContentTonalElevationPreference.default }
Expand All @@ -116,6 +119,7 @@ val LocalArticleSwipeLeftAction = compositionLocalOf { ArticleSwipeLeftActionPre
val LocalArticleSwipeRightAction = compositionLocalOf { ArticleSwipeRightActionPreference.default }
val LocalHideEmptyDefault = compositionLocalOf { HideEmptyDefaultPreference.default }
val LocalPickImageMethod = compositionLocalOf { PickImageMethodPreference.default }
val LocalMediaFileFilter = compositionLocalOf { MediaFileFilterPreference.default }

// RSS
val LocalRssSyncFrequency = compositionLocalOf { RssSyncFrequencyPreference.default }
Expand Down
Loading

0 comments on commit d4a5659

Please sign in to comment.