Skip to content

Commit

Permalink
[feature|optimize|fix] Support sharing and copying images from readin…
Browse files Browse the repository at this point in the history
…g page; support recording playback progress; optimize player code; fix some issues
  • Loading branch information
SkyD666 committed Aug 24, 2024
1 parent 44909d1 commit cbc418c
Show file tree
Hide file tree
Showing 50 changed files with 767 additions and 117 deletions.
3 changes: 2 additions & 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 = 22
versionName = "2.1-alpha21"
versionName = "2.1-alpha22"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"

Expand Down Expand Up @@ -203,6 +203,7 @@ dependencies {
implementation("io.coil-kt:coil-compose:2.7.0")
implementation("io.coil-kt:coil-gif:2.7.0")
implementation("io.coil-kt:coil-svg:2.7.0")
implementation("io.coil-kt:coil-video:2.7.0")
implementation("com.airbnb.android:lottie-compose:6.5.0")
implementation("com.rometools:rome:2.1.0")
implementation("be.ceau:opml-parser:3.1.0") {
Expand Down
8 changes: 4 additions & 4 deletions app/src/main/java/com/skyd/anivu/base/mvi/MviIntent.kt
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,25 @@ interface MviIntent

@Composable
fun <I : MviIntent, S : MviViewState, E : MviSingleEvent>
AbstractMviViewModel<I, S, E>.getDispatcher(startWith: I): (I) -> Unit {
AbstractMviViewModel<I, S, E>.getDispatcher(startWith: I?): (I) -> Unit {
return getDispatcher(Unit, startWith = startWith)
}

@Composable
fun <I : MviIntent, S : MviViewState, E : MviSingleEvent>
AbstractMviViewModel<I, S, E>.getDispatcher(key1: Any?, startWith: I): (I) -> Unit {
AbstractMviViewModel<I, S, E>.getDispatcher(key1: Any?, startWith: I?): (I) -> Unit {
return getDispatcher(*arrayOf(key1), startWith = startWith)
}

@Composable
fun <I : MviIntent, S : MviViewState, E : MviSingleEvent>
AbstractMviViewModel<I, S, E>.getDispatcher(vararg keys: Any?, startWith: I): (I) -> Unit {
AbstractMviViewModel<I, S, E>.getDispatcher(vararg keys: Any?, startWith: I?): (I) -> Unit {
val intentChannel = remember(*keys) { Channel<I>(Channel.UNLIMITED) }
LaunchedEffect(*keys, intentChannel) {
withContext(Dispatchers.Main.immediate) {
intentChannel
.consumeAsFlow()
.startWith(startWith)
.run { if (startWith == null) this else startWith(startWith) }
.onEach(this@getDispatcher::processIntent)
.collect()
}
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/java/com/skyd/anivu/config/Const.kt
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ object Const {
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
"AniVu"
).apply { if (!exists()) mkdirs() }
val TEMP_PICTURES_DIR = File(appContext.cacheDir.path, "Pictures").apply {
if (!exists()) mkdirs()
}

val INTERNAL_STORAGE: String = Environment.getExternalStorageDirectory().absolutePath
}
7 changes: 6 additions & 1 deletion app/src/main/java/com/skyd/anivu/di/DatabaseModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.skyd.anivu.model.db.dao.DownloadInfoDao
import com.skyd.anivu.model.db.dao.EnclosureDao
import com.skyd.anivu.model.db.dao.FeedDao
import com.skyd.anivu.model.db.dao.GroupDao
import com.skyd.anivu.model.db.dao.MediaPlayHistoryDao
import com.skyd.anivu.model.db.dao.SearchDomainDao
import com.skyd.anivu.model.db.dao.SessionParamsDao
import com.skyd.anivu.model.db.dao.TorrentFileDao
Expand Down Expand Up @@ -56,6 +57,11 @@ object DatabaseModule {
fun provideSessionParamsDao(database: AppDatabase): SessionParamsDao =
database.sessionParamsDao()

@Provides
@Singleton
fun provideMediaPlayHistoryDao(database: AppDatabase): MediaPlayHistoryDao =
database.mediaPlayHistoryDao()


@Provides
@Singleton
Expand All @@ -66,5 +72,4 @@ object DatabaseModule {
@Singleton
fun provideSearchDomain(database: SearchDomainDatabase): SearchDomainDao =
database.searchDomainDao()

}
2 changes: 2 additions & 0 deletions app/src/main/java/com/skyd/anivu/ext/ContextExt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import coil.ImageLoader
import coil.decode.GifDecoder
import coil.decode.ImageDecoderDecoder
import coil.decode.SvgDecoder
import coil.decode.VideoFrameDecoder

val Context.activity: Activity
get() {
Expand Down Expand Up @@ -121,5 +122,6 @@ fun Context.imageLoaderBuilder(): ImageLoader.Builder {
add(GifDecoder.Factory())
}
add(SvgDecoder.Factory())
add(VideoFrameDecoder.Factory())
}
}
9 changes: 9 additions & 0 deletions app/src/main/java/com/skyd/anivu/ext/FileExt.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ fun File.deleteRecursivelyExclude(hook: (File) -> Boolean = { true }): Boolean =
(it != this && hook(it) && (it.delete() || !it.exists())) && res
}

fun File.deleteDirs(
maxSize: Int = 5_242_880,
exclude: (file: File) -> Boolean,
) {
if (walkTopDown().filter { it.isFile }.map { it.length() }.sum() > maxSize) {
walkBottomUp().forEach { if (!exclude(it)) it.deleteRecursively() }
}
}

fun File.getMimeType(): String? {
if (isDirectory) return DocumentsContract.Document.MIME_TYPE_DIR
var type: String? = null
Expand Down
30 changes: 25 additions & 5 deletions app/src/main/java/com/skyd/anivu/ext/IOExt.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.skyd.anivu.ext

import android.content.ActivityNotFoundException
import android.content.ClipData
import android.content.ClipboardManager
import android.content.ContentResolver
import android.content.Context
import android.content.Intent
Expand Down Expand Up @@ -70,24 +72,33 @@ fun Uri.openWith(context: Context) = openChooser(
chooserTitle = context.getString(R.string.open_with),
)

fun Uri.share(context: Context) = openChooser(
fun Uri.share(context: Context, mimeType: String? = null) = openChooser(
context = context,
action = Intent.ACTION_SEND,
chooserTitle = context.getString(R.string.share),
mimeType = mimeType,
)

private fun Uri.openChooser(context: Context, action: String, chooserTitle: CharSequence) {
private fun Uri.openChooser(
context: Context,
action: String,
chooserTitle: CharSequence,
mimeType: String? = null,
) {
try {
val mimeType = context.contentResolver.getType(this)
val currentMimeType = mimeType ?: context.contentResolver.getType(this)
val intent = Intent.createChooser(
Intent().apply {
this.action = action
putExtra(Intent.EXTRA_STREAM, this@openChooser)
setDataAndType(this@openChooser, mimeType)
setDataAndType(this@openChooser, currentMimeType)
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
},
chooserTitle
)
if (context.tryActivity == null) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
ContextCompat.startActivity(context, intent, null)
} catch (e: Exception) {
e.printStackTrace()
Expand Down Expand Up @@ -228,4 +239,13 @@ fun File.md5(): String? {
}

inline val String.extName: String
get() = substringAfterLast(".", missingDelimiterValue = "")
get() = substringAfterLast(".", missingDelimiterValue = "")

fun Uri.copyToClipboard(context: Context, mimeType: String? = null) {
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
clipboard.setPrimaryClip(
ClipData("AniVu", arrayOf(mimeType), ClipData.Item(this)).apply {
addItem(ClipData.Item(this@copyToClipboard))
}
)
}
5 changes: 4 additions & 1 deletion app/src/main/java/com/skyd/anivu/model/bean/GroupBean.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ open class GroupBean(
open val previousGroupId: String? = null,
@ColumnInfo(name = NEXT_GROUP_ID_COLUMN)
open val nextGroupId: String? = null,
@ColumnInfo(name = IS_EXPANDED_COLUMN)
open val isExpanded: Boolean = true,
) : BaseBean, Parcelable {
override fun equals(other: Any?): Boolean {
if (this === other) return true
Expand All @@ -41,13 +43,14 @@ open class GroupBean(
}

fun toVo(): GroupVo {
return GroupVo(groupId, name)
return GroupVo(groupId, name, isExpanded)
}

companion object {
const val NAME_COLUMN = "name"
const val GROUP_ID_COLUMN = "groupId"
const val PREVIOUS_GROUP_ID_COLUMN = "previousGroupId"
const val NEXT_GROUP_ID_COLUMN = "nextGroupId"
const val IS_EXPANDED_COLUMN = "isExpanded"
}
}
12 changes: 10 additions & 2 deletions app/src/main/java/com/skyd/anivu/model/bean/GroupVo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import android.os.Parcelable
import com.skyd.anivu.R
import com.skyd.anivu.appContext
import com.skyd.anivu.base.BaseBean
import com.skyd.anivu.ext.dataStore
import com.skyd.anivu.ext.getOrDefault
import com.skyd.anivu.model.preference.appearance.feed.FeedGroupExpandPreference
import kotlinx.parcelize.Parcelize
import kotlinx.serialization.Serializable

Expand All @@ -12,13 +15,18 @@ import kotlinx.serialization.Serializable
open class GroupVo(
val groupId: String,
open val name: String,
open val isExpanded: Boolean,
) : BaseBean, Parcelable {
fun toPo(): GroupBean {
return GroupBean(groupId, name, null, null)
return GroupBean(groupId, name, null, null, isExpanded = isExpanded)
}

object DefaultGroup :
GroupVo(DEFAULT_GROUP_ID, appContext.getString(R.string.default_feed_group)) {
GroupVo(
DEFAULT_GROUP_ID,
appContext.getString(R.string.default_feed_group),
appContext.dataStore.getOrDefault(FeedGroupExpandPreference),
) {
private fun readResolve(): Any = DefaultGroup
override val name: String
get() = appContext.getString(R.string.default_feed_group)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.skyd.anivu.model.bean

import android.os.Parcelable
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import com.skyd.anivu.base.BaseBean
import kotlinx.parcelize.Parcelize
import kotlinx.serialization.Serializable

const val MEDIA_PLAY_HISTORY_TABLE_NAME = "MediaPlayHistory"

@Parcelize
@Serializable
@Entity(tableName = MEDIA_PLAY_HISTORY_TABLE_NAME)
data class MediaPlayHistoryBean(
@PrimaryKey
@ColumnInfo(name = PATH_COLUMN)
val path: String,
@ColumnInfo(name = LAST_PLAY_POSITION_COLUMN)
val lastPlayPosition: Long,
) : BaseBean, Parcelable {
companion object {
const val PATH_COLUMN = "path"
const val LAST_PLAY_POSITION_COLUMN = "lastPlayPosition"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,16 @@ data class DownloadInfoBean(
var downloadPayloadRate: Int = 0

enum class DownloadState {
Init, Downloading, Paused, Completed, ErrorPaused, StorageMovedFailed, Seeding, SeedingPaused
Init, Downloading, Paused, Completed, ErrorPaused, StorageMovedFailed, Seeding, SeedingPaused;

fun downloadComplete(): Boolean {
return this == Completed || this == Seeding || this == SeedingPaused
}
}

companion object {
const val LINK_COLUMN = "link"
const val NAME_COLUMN = "name"
const val DOWNLOADING_DIR_NAME_COLUMN = "downloadingDirName"
const val DOWNLOAD_DATE_COLUMN = "downloadDate"
const val SIZE_COLUMN = "size"
const val PROGRESS_COLUMN = "progress"
Expand Down
9 changes: 7 additions & 2 deletions app/src/main/java/com/skyd/anivu/model/db/AppDatabase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import com.skyd.anivu.model.bean.EnclosureBean
import com.skyd.anivu.model.bean.FeedBean
import com.skyd.anivu.model.bean.FeedViewBean
import com.skyd.anivu.model.bean.GroupBean
import com.skyd.anivu.model.bean.MediaPlayHistoryBean
import com.skyd.anivu.model.bean.download.DownloadInfoBean
import com.skyd.anivu.model.bean.download.DownloadLinkUuidMapBean
import com.skyd.anivu.model.bean.download.SessionParamsBean
Expand All @@ -19,8 +20,10 @@ import com.skyd.anivu.model.db.dao.DownloadInfoDao
import com.skyd.anivu.model.db.dao.EnclosureDao
import com.skyd.anivu.model.db.dao.FeedDao
import com.skyd.anivu.model.db.dao.GroupDao
import com.skyd.anivu.model.db.dao.MediaPlayHistoryDao
import com.skyd.anivu.model.db.dao.SessionParamsDao
import com.skyd.anivu.model.db.dao.TorrentFileDao
import com.skyd.anivu.model.db.migration.Migration10To11
import com.skyd.anivu.model.db.migration.Migration1To2
import com.skyd.anivu.model.db.migration.Migration2To3
import com.skyd.anivu.model.db.migration.Migration3To4
Expand All @@ -43,9 +46,10 @@ const val APP_DATA_BASE_FILE_NAME = "app.db"
SessionParamsBean::class,
TorrentFileBean::class,
GroupBean::class,
MediaPlayHistoryBean::class,
],
views = [FeedViewBean::class],
version = 10,
version = 11,
)
@TypeConverters(
value = []
Expand All @@ -58,6 +62,7 @@ abstract class AppDatabase : RoomDatabase() {
abstract fun downloadInfoDao(): DownloadInfoDao
abstract fun torrentFileDao(): TorrentFileDao
abstract fun sessionParamsDao(): SessionParamsDao
abstract fun mediaPlayHistoryDao(): MediaPlayHistoryDao

companion object {
@Volatile
Expand All @@ -66,7 +71,7 @@ abstract class AppDatabase : RoomDatabase() {
private val migrations = arrayOf(
Migration1To2(), Migration2To3(), Migration3To4(), Migration4To5(),
Migration5To6(), Migration6To7(), Migration7To8(), Migration8To9(),
Migration9To10(),
Migration9To10(), Migration10To11(),
)

fun getInstance(context: Context): AppDatabase {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.skyd.anivu.model.db.dao

import androidx.paging.PagingSource
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Transaction
import com.skyd.anivu.model.bean.MEDIA_PLAY_HISTORY_TABLE_NAME
import com.skyd.anivu.model.bean.MediaPlayHistoryBean

@Dao
interface MediaPlayHistoryDao {
@Transaction
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun updateMediaPlayHistory(mediaPlayHistoryBean: MediaPlayHistoryBean)

@Transaction
@Query(
"""
DELETE FROM $MEDIA_PLAY_HISTORY_TABLE_NAME
WHERE ${MediaPlayHistoryBean.PATH_COLUMN} = :path
"""
)
suspend fun deleteMediaPlayHistory(path: String): Int

@Transaction
@Query("DELETE FROM $MEDIA_PLAY_HISTORY_TABLE_NAME")
suspend fun deleteAllMediaPlayHistory(): Int

@Transaction
@Query(
"""
SELECT * FROM $MEDIA_PLAY_HISTORY_TABLE_NAME
WHERE ${MediaPlayHistoryBean.PATH_COLUMN} = :path
"""
)
fun getMediaPlayHistory(path: String): MediaPlayHistoryBean

@Transaction
@Query("SELECT * FROM $MEDIA_PLAY_HISTORY_TABLE_NAME")
fun getMediaPlayHistoryList(): PagingSource<Int, MediaPlayHistoryBean>

@Transaction
@Query(
"""
UPDATE $MEDIA_PLAY_HISTORY_TABLE_NAME
SET ${MediaPlayHistoryBean.LAST_PLAY_POSITION_COLUMN} = :lastPlayPosition
WHERE ${MediaPlayHistoryBean.PATH_COLUMN} = :path
"""
)
fun updateLastPlayPosition(path: String, lastPlayPosition: Long): Int
}
Loading

0 comments on commit cbc418c

Please sign in to comment.