[feat] Video position remember& New Icon and Theme
BIN
aether.png
Normal file → Executable file
|
Before Width: | Height: | Size: 1.0 MiB After Width: | Height: | Size: 616 KiB |
BIN
aether_clip.png
|
Before Width: | Height: | Size: 508 KiB After Width: | Height: | Size: 348 KiB |
|
Before Width: | Height: | Size: 237 KiB After Width: | Height: | Size: 163 KiB |
12
app/src/main/java/com/acitelight/aether/model/VideoRecord.kt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
package com.acitelight.aether.model
|
||||||
|
|
||||||
|
import androidx.room.ColumnInfo
|
||||||
|
import androidx.room.Entity
|
||||||
|
import androidx.room.PrimaryKey
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
data class VideoRecord (
|
||||||
|
@PrimaryKey(autoGenerate = false) val id: String = "",
|
||||||
|
@ColumnInfo(name = "name") val klass: String = "",
|
||||||
|
@ColumnInfo(name = "position") val position: Long
|
||||||
|
)
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.acitelight.aether.model
|
||||||
|
|
||||||
|
import androidx.room.Dao
|
||||||
|
import androidx.room.Delete
|
||||||
|
import androidx.room.Insert
|
||||||
|
import androidx.room.OnConflictStrategy
|
||||||
|
import androidx.room.Query
|
||||||
|
import androidx.room.Update
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
interface VideoRecordDao {
|
||||||
|
@Query("SELECT * FROM videorecord")
|
||||||
|
fun getAll(): Flow<List<VideoRecord>>
|
||||||
|
|
||||||
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
|
suspend fun insert(rec: VideoRecord)
|
||||||
|
|
||||||
|
@Update
|
||||||
|
suspend fun update(rec: VideoRecord)
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
suspend fun delete(rec: VideoRecord)
|
||||||
|
|
||||||
|
@Query("SELECT * FROM videorecord WHERE id = :id")
|
||||||
|
suspend fun getById(id: String): VideoRecord?
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.acitelight.aether.model
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.room.Database
|
||||||
|
import androidx.room.Room
|
||||||
|
import androidx.room.RoomDatabase
|
||||||
|
|
||||||
|
@Database(entities = [VideoRecord::class], version = 1)
|
||||||
|
abstract class VideoRecordDatabase : RoomDatabase() {
|
||||||
|
abstract fun userDao(): VideoRecordDao
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@Volatile
|
||||||
|
private var INSTANCE: VideoRecordDatabase? = null
|
||||||
|
|
||||||
|
fun getDatabase(context: Context): VideoRecordDatabase {
|
||||||
|
return INSTANCE ?: synchronized(this) {
|
||||||
|
val instance = Room.databaseBuilder(
|
||||||
|
context.applicationContext,
|
||||||
|
VideoRecordDatabase::class.java,
|
||||||
|
"videorecord_database"
|
||||||
|
).build()
|
||||||
|
INSTANCE = instance
|
||||||
|
instance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -130,8 +130,8 @@ fun generateColorScheme(primaryColor: Color, isDarkMode: Boolean): ColorScheme {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val DarkColorScheme = generateColorScheme(Color(0xFF2F4F8F), isDarkMode = true)
|
private val DarkColorScheme = generateColorScheme(Color(0xFF4A6F9F), isDarkMode = true)
|
||||||
private val LightColorScheme = generateColorScheme(Color(0xFF2F4F8F), isDarkMode = false)
|
private val LightColorScheme = generateColorScheme(Color(0xFF4A6F9F), isDarkMode = false)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun AetherTheme(
|
fun AetherTheme(
|
||||||
|
|||||||
@@ -8,58 +8,44 @@ import androidx.compose.foundation.layout.Arrangement
|
|||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.Spacer
|
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.heightIn
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.width
|
|
||||||
import androidx.compose.foundation.layout.widthIn
|
import androidx.compose.foundation.layout.widthIn
|
||||||
import androidx.compose.foundation.layout.wrapContentHeight
|
import androidx.compose.foundation.layout.wrapContentHeight
|
||||||
import androidx.compose.foundation.lazy.LazyRow
|
import androidx.compose.foundation.lazy.LazyRow
|
||||||
import androidx.compose.foundation.lazy.items
|
|
||||||
import androidx.compose.foundation.lazy.itemsIndexed
|
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
|
||||||
import androidx.compose.foundation.pager.HorizontalPager
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
import androidx.compose.foundation.pager.rememberPagerState
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Bookmarks
|
import androidx.compose.material.icons.filled.Bookmarks
|
||||||
import androidx.compose.material.icons.filled.Key
|
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
import androidx.compose.material3.CardDefaults
|
import androidx.compose.material3.CardDefaults
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.graphics.Brush
|
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.max
|
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewModelScope
|
||||||
import androidx.navigation.NavHostController
|
import androidx.navigation.NavHostController
|
||||||
import coil3.compose.AsyncImage
|
import coil3.compose.AsyncImage
|
||||||
import coil3.request.ImageRequest
|
import coil3.request.ImageRequest
|
||||||
import com.acitelight.aether.ToggleFullScreen
|
|
||||||
import com.acitelight.aether.model.BookMark
|
import com.acitelight.aether.model.BookMark
|
||||||
import com.acitelight.aether.model.ComicRecord
|
|
||||||
import com.acitelight.aether.service.MediaManager
|
|
||||||
import com.acitelight.aether.viewModel.ComicPageViewModel
|
import com.acitelight.aether.viewModel.ComicPageViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@@ -71,7 +57,6 @@ fun ComicPageView(
|
|||||||
comicPageViewModel: ComicPageViewModel = hiltViewModel<ComicPageViewModel>()
|
comicPageViewModel: ComicPageViewModel = hiltViewModel<ComicPageViewModel>()
|
||||||
) {
|
) {
|
||||||
val colorScheme = MaterialTheme.colorScheme
|
val colorScheme = MaterialTheme.colorScheme
|
||||||
comicPageViewModel.SetupClient()
|
|
||||||
comicPageViewModel.Resolve(comicId.hexToString(), page.toInt())
|
comicPageViewModel.Resolve(comicId.hexToString(), page.toInt())
|
||||||
|
|
||||||
val title by comicPageViewModel.title
|
val title by comicPageViewModel.title
|
||||||
@@ -81,7 +66,7 @@ fun ComicPageView(
|
|||||||
var showPlane by comicPageViewModel.showPlane
|
var showPlane by comicPageViewModel.showPlane
|
||||||
var showBookMarkPop by remember { mutableStateOf(false) }
|
var showBookMarkPop by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
comicPageViewModel.UpdateProcess(pagerState.currentPage)
|
comicPageViewModel.updateProcess(pagerState.currentPage)
|
||||||
|
|
||||||
val comic by comicPageViewModel.comic
|
val comic by comicPageViewModel.comic
|
||||||
comic?.let {
|
comic?.let {
|
||||||
@@ -96,7 +81,7 @@ fun ComicPageView(
|
|||||||
.clickable {
|
.clickable {
|
||||||
showPlane = !showPlane
|
showPlane = !showPlane
|
||||||
if (showPlane) {
|
if (showPlane) {
|
||||||
comicPageViewModel.coroutineScope?.launch {
|
comicPageViewModel.viewModelScope.launch {
|
||||||
comicPageViewModel.listState?.scrollToItem(index = pagerState.currentPage)
|
comicPageViewModel.listState?.scrollToItem(index = pagerState.currentPage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -329,7 +314,7 @@ fun ComicPageView(
|
|||||||
showBookMarkPop = false
|
showBookMarkPop = false
|
||||||
}, { s ->
|
}, { s ->
|
||||||
showBookMarkPop = false
|
showBookMarkPop = false
|
||||||
comicPageViewModel.coroutineScope?.launch {
|
comicPageViewModel.viewModelScope.launch {
|
||||||
comicPageViewModel.mediaManager.postBookmark(
|
comicPageViewModel.mediaManager.postBookmark(
|
||||||
comicId.hexToString(),
|
comicId.hexToString(),
|
||||||
BookMark(name = s, page = comicPageViewModel.pageList[pagerState.currentPage])
|
BookMark(name = s, page = comicPageViewModel.pageList[pagerState.currentPage])
|
||||||
|
|||||||
@@ -213,7 +213,7 @@ fun VideoPlayer(
|
|||||||
videoId: String,
|
videoId: String,
|
||||||
navController: NavHostController
|
navController: NavHostController
|
||||||
) {
|
) {
|
||||||
videoPlayerViewModel.Init(videoId)
|
videoPlayerViewModel.init(videoId)
|
||||||
|
|
||||||
if(videoPlayerViewModel.startPlaying)
|
if(videoPlayerViewModel.startPlaying)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
package com.acitelight.aether.viewModel
|
package com.acitelight.aether.viewModel
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.foundation.pager.PagerState
|
|
||||||
import androidx.compose.foundation.pager.rememberPagerState
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.mutableStateListOf
|
import androidx.compose.runtime.mutableStateListOf
|
||||||
@@ -22,8 +19,6 @@ import com.acitelight.aether.model.ComicRecord
|
|||||||
import com.acitelight.aether.model.ComicRecordDatabase
|
import com.acitelight.aether.model.ComicRecordDatabase
|
||||||
import com.acitelight.aether.service.ApiClient.createOkHttp
|
import com.acitelight.aether.service.ApiClient.createOkHttp
|
||||||
import com.acitelight.aether.service.MediaManager
|
import com.acitelight.aether.service.MediaManager
|
||||||
import com.acitelight.aether.service.SettingsDataStoreManager
|
|
||||||
import com.acitelight.aether.view.hexToString
|
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
@@ -32,7 +27,8 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class ComicPageViewModel @Inject constructor(
|
class ComicPageViewModel @Inject constructor(
|
||||||
val mediaManager: MediaManager
|
val mediaManager: MediaManager,
|
||||||
|
@ApplicationContext private val context: Context
|
||||||
) : ViewModel()
|
) : ViewModel()
|
||||||
{
|
{
|
||||||
var imageLoader: ImageLoader? = null
|
var imageLoader: ImageLoader? = null
|
||||||
@@ -40,29 +36,18 @@ class ComicPageViewModel @Inject constructor(
|
|||||||
var pageList = mutableStateListOf<String>()
|
var pageList = mutableStateListOf<String>()
|
||||||
var title = mutableStateOf<String>("")
|
var title = mutableStateOf<String>("")
|
||||||
var listState: LazyListState? = null
|
var listState: LazyListState? = null
|
||||||
var coroutineScope: CoroutineScope? = null
|
|
||||||
var showPlane = mutableStateOf(true)
|
var showPlane = mutableStateOf(true)
|
||||||
var db: ComicRecordDatabase? = null
|
var db: ComicRecordDatabase
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun SetupClient()
|
init{
|
||||||
{
|
|
||||||
val context = LocalContext.current
|
|
||||||
imageLoader = ImageLoader.Builder(context)
|
imageLoader = ImageLoader.Builder(context)
|
||||||
.components {
|
.components {
|
||||||
add(OkHttpNetworkFetcherFactory(createOkHttp()))
|
add(OkHttpNetworkFetcherFactory(createOkHttp()))
|
||||||
}
|
}
|
||||||
.build()
|
.build()
|
||||||
listState = rememberLazyListState()
|
listState = LazyListState(0, 0)
|
||||||
coroutineScope = rememberCoroutineScope()
|
db = ComicRecordDatabase.getDatabase(context)
|
||||||
|
|
||||||
db = remember {
|
|
||||||
try{
|
|
||||||
ComicRecordDatabase.getDatabase(context)
|
|
||||||
}catch (e: Exception) {
|
|
||||||
print(e.message)
|
|
||||||
} as ComicRecordDatabase?
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@@ -70,23 +55,23 @@ class ComicPageViewModel @Inject constructor(
|
|||||||
{
|
{
|
||||||
if(comic.value != null) return
|
if(comic.value != null) return
|
||||||
LaunchedEffect(id, page) {
|
LaunchedEffect(id, page) {
|
||||||
coroutineScope?.launch {
|
viewModelScope.launch {
|
||||||
comic.value = mediaManager.queryComicInfoSingle(id)
|
comic.value = mediaManager.queryComicInfoSingle(id)
|
||||||
comic.value?.let {
|
comic.value?.let {
|
||||||
pageList.addAll(it.comic.list)
|
pageList.addAll(it.comic.list)
|
||||||
title.value = it.comic.comic_name
|
title.value = it.comic.comic_name
|
||||||
listState?.scrollToItem(index = page)
|
listState?.scrollToItem(index = page)
|
||||||
UpdateProcess(page)
|
updateProcess(page)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun UpdateProcess(page: Int)
|
fun updateProcess(page: Int)
|
||||||
{
|
{
|
||||||
if(comic.value == null) return
|
if(comic.value == null) return
|
||||||
coroutineScope?.launch {
|
viewModelScope.launch {
|
||||||
db?.userDao()?.insert(ComicRecord(id = comic.value!!.id.toInt(), name = comic.value!!.comic.comic_name, position = page))
|
db.userDao().insert(ComicRecord(id = comic.value!!.id.toInt(), name = comic.value!!.comic.comic_name, position = page))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
package com.acitelight.aether.viewModel
|
package com.acitelight.aether.viewModel
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.annotation.OptIn
|
import androidx.annotation.OptIn
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
@@ -25,11 +27,15 @@ import coil3.ImageLoader
|
|||||||
import coil3.network.okhttp.OkHttpNetworkFetcherFactory
|
import coil3.network.okhttp.OkHttpNetworkFetcherFactory
|
||||||
import com.acitelight.aether.model.Video
|
import com.acitelight.aether.model.Video
|
||||||
import com.acitelight.aether.model.VideoQueryIndex
|
import com.acitelight.aether.model.VideoQueryIndex
|
||||||
|
import com.acitelight.aether.model.VideoRecord
|
||||||
|
import com.acitelight.aether.model.VideoRecordDatabase
|
||||||
import com.acitelight.aether.service.ApiClient.createOkHttp
|
import com.acitelight.aether.service.ApiClient.createOkHttp
|
||||||
import com.acitelight.aether.service.MediaManager
|
import com.acitelight.aether.service.MediaManager
|
||||||
import com.acitelight.aether.service.RecentManager
|
import com.acitelight.aether.service.RecentManager
|
||||||
|
import com.acitelight.aether.view.formatTime
|
||||||
import com.acitelight.aether.view.hexToString
|
import com.acitelight.aether.view.hexToString
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
@@ -39,6 +45,7 @@ import javax.inject.Inject
|
|||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class VideoPlayerViewModel @Inject constructor(
|
class VideoPlayerViewModel @Inject constructor(
|
||||||
|
@ApplicationContext private val context: Context,
|
||||||
val mediaManager: MediaManager,
|
val mediaManager: MediaManager,
|
||||||
val recentManager: RecentManager
|
val recentManager: RecentManager
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
@@ -66,25 +73,24 @@ class VideoPlayerViewModel @Inject constructor(
|
|||||||
val dataSourceFactory = OkHttpDataSource.Factory(createOkHttp())
|
val dataSourceFactory = OkHttpDataSource.Factory(createOkHttp())
|
||||||
var imageLoader: ImageLoader? = null;
|
var imageLoader: ImageLoader? = null;
|
||||||
var brit by mutableFloatStateOf(0.5f)
|
var brit by mutableFloatStateOf(0.5f)
|
||||||
|
val database: VideoRecordDatabase = VideoRecordDatabase.getDatabase(context)
|
||||||
|
|
||||||
@OptIn(UnstableApi::class)
|
@OptIn(UnstableApi::class)
|
||||||
@Composable
|
fun init(videoId: String) {
|
||||||
fun Init(videoId: String) {
|
|
||||||
if (_init) return;
|
if (_init) return;
|
||||||
val context = LocalContext.current
|
|
||||||
val v = videoId.hexToString()
|
val v = videoId.hexToString()
|
||||||
|
|
||||||
imageLoader = ImageLoader.Builder(context)
|
imageLoader = ImageLoader.Builder(context)
|
||||||
.components {
|
.components {
|
||||||
add(OkHttpNetworkFetcherFactory(createOkHttp()))
|
add(OkHttpNetworkFetcherFactory(createOkHttp()))
|
||||||
}
|
}
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
remember {
|
viewModelScope.launch {
|
||||||
viewModelScope.launch {
|
video = mediaManager.queryVideo(v.split("/")[0], v.split("/")[1])!!
|
||||||
video = mediaManager.queryVideo(v.split("/")[0], v.split("/")[1])!!
|
recentManager.pushVideo(context, VideoQueryIndex(v.split("/")[0], v.split("/")[1]))
|
||||||
recentManager.pushVideo(context, VideoQueryIndex(v.split("/")[0], v.split("/")[1]))
|
_player =
|
||||||
_player = (if(video!!.isLocal) ExoPlayer.Builder(context) else ExoPlayer.Builder(context).setMediaSourceFactory(DefaultMediaSourceFactory(dataSourceFactory)))
|
(if (video!!.isLocal) ExoPlayer.Builder(context) else ExoPlayer.Builder(context)
|
||||||
|
.setMediaSourceFactory(DefaultMediaSourceFactory(dataSourceFactory)))
|
||||||
.build().apply {
|
.build().apply {
|
||||||
val url = video?.getVideo() ?: ""
|
val url = video?.getVideo() ?: ""
|
||||||
val mediaItem = if (video!!.isLocal)
|
val mediaItem = if (video!!.isLocal)
|
||||||
@@ -105,18 +111,27 @@ class VideoPlayerViewModel @Inject constructor(
|
|||||||
|
|
||||||
override fun onRenderedFirstFrame() {
|
override fun onRenderedFirstFrame() {
|
||||||
super.onRenderedFirstFrame()
|
super.onRenderedFirstFrame()
|
||||||
|
if(!renderedFirst)
|
||||||
|
{
|
||||||
|
viewModelScope.launch {
|
||||||
|
val ii = database.userDao().getById(video!!.id)
|
||||||
|
if(ii != null)
|
||||||
|
{
|
||||||
|
_player!!.seekTo(ii.position)
|
||||||
|
Toast.makeText(context, "Recover from ${formatTime(ii.position)} ", Toast.LENGTH_SHORT).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
renderedFirst = true
|
renderedFirst = true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPlayerError(error: PlaybackException) {
|
override fun onPlayerError(error: PlaybackException) {
|
||||||
Log.e("ExoPlayer", "Playback error: ", error)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
startListen()
|
startListen()
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_init = true;
|
_init = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,6 +150,10 @@ class VideoPlayerViewModel @Inject constructor(
|
|||||||
|
|
||||||
override fun onCleared() {
|
override fun onCleared() {
|
||||||
super.onCleared()
|
super.onCleared()
|
||||||
|
val p = _player!!.currentPosition
|
||||||
_player?.release()
|
_player?.release()
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
database.userDao().insert(VideoRecord(video!!.id, video!!.klass, p))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 9.9 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 6.7 KiB After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 9.9 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 17 KiB |