mirror of
https://github.com/libre-tube/LibreTube.git
synced 2025-04-27 23:40:33 +05:30
add frontend support
This commit is contained in:
parent
ea1d2765c9
commit
0d65071c79
330
app/schemas/com.github.libretube.db.AppDatabase/9.json
Normal file
330
app/schemas/com.github.libretube.db.AppDatabase/9.json
Normal file
@ -0,0 +1,330 @@
|
|||||||
|
{
|
||||||
|
"formatVersion": 1,
|
||||||
|
"database": {
|
||||||
|
"version": 9,
|
||||||
|
"identityHash": "8c1e428cb526415347639e49f7757f76",
|
||||||
|
"entities": [
|
||||||
|
{
|
||||||
|
"tableName": "watchHistoryItem",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`videoId` TEXT NOT NULL, `title` TEXT, `uploadDate` TEXT, `uploader` TEXT, `uploaderUrl` TEXT, `uploaderAvatar` TEXT, `thumbnailUrl` TEXT, `duration` INTEGER, PRIMARY KEY(`videoId`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "videoId",
|
||||||
|
"columnName": "videoId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "title",
|
||||||
|
"columnName": "title",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "uploadDate",
|
||||||
|
"columnName": "uploadDate",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "uploader",
|
||||||
|
"columnName": "uploader",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "uploaderUrl",
|
||||||
|
"columnName": "uploaderUrl",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "uploaderAvatar",
|
||||||
|
"columnName": "uploaderAvatar",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "thumbnailUrl",
|
||||||
|
"columnName": "thumbnailUrl",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "duration",
|
||||||
|
"columnName": "duration",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"videoId"
|
||||||
|
],
|
||||||
|
"autoGenerate": false
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "watchPosition",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`videoId` TEXT NOT NULL, `position` INTEGER NOT NULL, PRIMARY KEY(`videoId`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "videoId",
|
||||||
|
"columnName": "videoId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "position",
|
||||||
|
"columnName": "position",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"videoId"
|
||||||
|
],
|
||||||
|
"autoGenerate": false
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "searchHistoryItem",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`query` TEXT NOT NULL, PRIMARY KEY(`query`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "query",
|
||||||
|
"columnName": "query",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"query"
|
||||||
|
],
|
||||||
|
"autoGenerate": false
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "customInstance",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`name` TEXT NOT NULL, `apiUrl` TEXT NOT NULL, `frontendUrl` TEXT NOT NULL, PRIMARY KEY(`name`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "apiUrl",
|
||||||
|
"columnName": "apiUrl",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "frontendUrl",
|
||||||
|
"columnName": "frontendUrl",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"name"
|
||||||
|
],
|
||||||
|
"autoGenerate": false
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "localSubscription",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`channelId` TEXT NOT NULL, PRIMARY KEY(`channelId`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "channelId",
|
||||||
|
"columnName": "channelId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"channelId"
|
||||||
|
],
|
||||||
|
"autoGenerate": false
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "playlistBookmark",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`playlistId` TEXT NOT NULL, `playlistName` TEXT, `thumbnailUrl` TEXT, `uploader` TEXT, `uploaderUrl` TEXT, `uploaderAvatar` TEXT, PRIMARY KEY(`playlistId`))",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "playlistId",
|
||||||
|
"columnName": "playlistId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "playlistName",
|
||||||
|
"columnName": "playlistName",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "thumbnailUrl",
|
||||||
|
"columnName": "thumbnailUrl",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "uploader",
|
||||||
|
"columnName": "uploader",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "uploaderUrl",
|
||||||
|
"columnName": "uploaderUrl",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "uploaderAvatar",
|
||||||
|
"columnName": "uploaderAvatar",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"playlistId"
|
||||||
|
],
|
||||||
|
"autoGenerate": false
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "LocalPlaylist",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `name` TEXT NOT NULL, `thumbnailUrl` TEXT NOT NULL)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "name",
|
||||||
|
"columnName": "name",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "thumbnailUrl",
|
||||||
|
"columnName": "thumbnailUrl",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"autoGenerate": true
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "LocalPlaylistItem",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `playlistId` INTEGER NOT NULL, `videoId` TEXT NOT NULL, `title` TEXT, `uploadDate` TEXT, `uploader` TEXT, `uploaderUrl` TEXT, `uploaderAvatar` TEXT, `thumbnailUrl` TEXT, `duration` INTEGER)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "playlistId",
|
||||||
|
"columnName": "playlistId",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "videoId",
|
||||||
|
"columnName": "videoId",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "title",
|
||||||
|
"columnName": "title",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "uploadDate",
|
||||||
|
"columnName": "uploadDate",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "uploader",
|
||||||
|
"columnName": "uploader",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "uploaderUrl",
|
||||||
|
"columnName": "uploaderUrl",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "uploaderAvatar",
|
||||||
|
"columnName": "uploaderAvatar",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "thumbnailUrl",
|
||||||
|
"columnName": "thumbnailUrl",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "duration",
|
||||||
|
"columnName": "duration",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"id"
|
||||||
|
],
|
||||||
|
"autoGenerate": true
|
||||||
|
},
|
||||||
|
"indices": [],
|
||||||
|
"foreignKeys": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"views": [],
|
||||||
|
"setupQueries": [
|
||||||
|
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||||
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '8c1e428cb526415347639e49f7757f76')"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -3,7 +3,6 @@ package com.github.libretube
|
|||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.os.StrictMode
|
import android.os.StrictMode
|
||||||
import android.os.StrictMode.VmPolicy
|
import android.os.StrictMode.VmPolicy
|
||||||
import android.util.Log
|
|
||||||
import androidx.core.app.NotificationChannelCompat
|
import androidx.core.app.NotificationChannelCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import androidx.work.ExistingPeriodicWorkPolicy
|
import androidx.work.ExistingPeriodicWorkPolicy
|
||||||
@ -13,10 +12,6 @@ import com.github.libretube.constants.BACKGROUND_CHANNEL_ID
|
|||||||
import com.github.libretube.constants.DOWNLOAD_CHANNEL_ID
|
import com.github.libretube.constants.DOWNLOAD_CHANNEL_ID
|
||||||
import com.github.libretube.constants.PUSH_CHANNEL_ID
|
import com.github.libretube.constants.PUSH_CHANNEL_ID
|
||||||
import com.github.libretube.db.DatabaseHolder
|
import com.github.libretube.db.DatabaseHolder
|
||||||
import com.github.libretube.db.obj.LocalPlaylist
|
|
||||||
import com.github.libretube.db.obj.LocalPlaylistItem
|
|
||||||
import com.github.libretube.extensions.awaitQuery
|
|
||||||
import com.github.libretube.extensions.query
|
|
||||||
import com.github.libretube.util.ExceptionHandler
|
import com.github.libretube.util.ExceptionHandler
|
||||||
import com.github.libretube.util.ImageHelper
|
import com.github.libretube.util.ImageHelper
|
||||||
import com.github.libretube.util.NotificationHelper
|
import com.github.libretube.util.NotificationHelper
|
||||||
@ -41,8 +36,6 @@ class LibreTubeApp : Application() {
|
|||||||
*/
|
*/
|
||||||
DatabaseHolder().initializeDatabase(this)
|
DatabaseHolder().initializeDatabase(this)
|
||||||
|
|
||||||
runDatabaseTests()
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bypassing fileUriExposedException, see https://stackoverflow.com/questions/38200282/android-os-fileuriexposedexception-file-storage-emulated-0-test-txt-exposed
|
* Bypassing fileUriExposedException, see https://stackoverflow.com/questions/38200282/android-os-fileuriexposedexception-file-storage-emulated-0-test-txt-exposed
|
||||||
*/
|
*/
|
||||||
@ -107,23 +100,4 @@ class LibreTubeApp : Application() {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun runDatabaseTests() {
|
|
||||||
awaitQuery {
|
|
||||||
val playlist = LocalPlaylist(
|
|
||||||
name = "TEstlist",
|
|
||||||
thumbnailUrl = "thumb"
|
|
||||||
)
|
|
||||||
DatabaseHolder.Database.localPlaylistsDao().createPlaylist(playlist)
|
|
||||||
val playlistId = DatabaseHolder.Database.localPlaylistsDao().getAll().first().playlist.id
|
|
||||||
val video = LocalPlaylistItem(
|
|
||||||
videoId = "video",
|
|
||||||
playlistId = playlistId,
|
|
||||||
title = "awesomePlaylistTitle"
|
|
||||||
)
|
|
||||||
DatabaseHolder.Database.localPlaylistsDao().addPlaylistVideo(video)
|
|
||||||
val lists = DatabaseHolder.Database.localPlaylistsDao().getAll()
|
|
||||||
Log.e("lists", lists.toString())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
127
app/src/main/java/com/github/libretube/api/PlaylistsHelper.kt
Normal file
127
app/src/main/java/com/github/libretube/api/PlaylistsHelper.kt
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
package com.github.libretube.api
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.Log
|
||||||
|
import com.github.libretube.R
|
||||||
|
import com.github.libretube.api.obj.Playlist
|
||||||
|
import com.github.libretube.api.obj.PlaylistId
|
||||||
|
import com.github.libretube.api.obj.Playlists
|
||||||
|
import com.github.libretube.db.DatabaseHolder
|
||||||
|
import com.github.libretube.db.obj.LocalPlaylist
|
||||||
|
import com.github.libretube.enums.PlaylistType
|
||||||
|
import com.github.libretube.extensions.TAG
|
||||||
|
import com.github.libretube.extensions.awaitQuery
|
||||||
|
import com.github.libretube.extensions.toLocalPlaylistItem
|
||||||
|
import com.github.libretube.extensions.toStreamItem
|
||||||
|
import com.github.libretube.extensions.toastFromMainThread
|
||||||
|
import com.github.libretube.util.PreferenceHelper
|
||||||
|
import retrofit2.HttpException
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
object PlaylistsHelper {
|
||||||
|
val token get() = PreferenceHelper.getToken()
|
||||||
|
|
||||||
|
suspend fun getPlaylists(): List<Playlists> {
|
||||||
|
if (token != "") return RetrofitInstance.authApi.getUserPlaylists(token)
|
||||||
|
|
||||||
|
val localPlaylists = awaitQuery {
|
||||||
|
DatabaseHolder.Database.localPlaylistsDao().getAll()
|
||||||
|
}
|
||||||
|
val playlists = mutableListOf<Playlists>()
|
||||||
|
localPlaylists.forEach {
|
||||||
|
playlists.add(
|
||||||
|
Playlists(
|
||||||
|
id = it.playlist.id.toString(),
|
||||||
|
name = it.playlist.name,
|
||||||
|
thumbnail = it.playlist.thumbnailUrl,
|
||||||
|
videos = it.videos.size.toLong()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return playlists
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun getPlaylist(playlistType: PlaylistType, playlistId: String): Playlist {
|
||||||
|
// load locally stored playlists with the auth api
|
||||||
|
return when (playlistType) {
|
||||||
|
PlaylistType.OWNED -> RetrofitInstance.authApi.getPlaylist(playlistId)
|
||||||
|
PlaylistType.PUBLIC -> RetrofitInstance.api.getPlaylist(playlistId)
|
||||||
|
PlaylistType.LOCAL -> {
|
||||||
|
val relation = awaitQuery {
|
||||||
|
DatabaseHolder.Database.localPlaylistsDao().getAll()
|
||||||
|
}.first { it.playlist.id.toString() == playlistId }
|
||||||
|
return Playlist(
|
||||||
|
name = relation.playlist.name,
|
||||||
|
thumbnailUrl = relation.playlist.thumbnailUrl,
|
||||||
|
videos = relation.videos.size,
|
||||||
|
relatedStreams = relation.videos.map { it.toStreamItem() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun createPlaylist(playlistName: String, appContext: Context, onSuccess: () -> Unit) {
|
||||||
|
if (token == "") {
|
||||||
|
awaitQuery {
|
||||||
|
DatabaseHolder.Database.localPlaylistsDao().createPlaylist(
|
||||||
|
LocalPlaylist(
|
||||||
|
name = playlistName,
|
||||||
|
thumbnailUrl = ""
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onSuccess.invoke()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val response = try {
|
||||||
|
RetrofitInstance.authApi.createPlaylist(
|
||||||
|
token,
|
||||||
|
Playlists(name = playlistName)
|
||||||
|
)
|
||||||
|
} catch (e: IOException) {
|
||||||
|
appContext.toastFromMainThread(R.string.unknown_error)
|
||||||
|
return
|
||||||
|
} catch (e: HttpException) {
|
||||||
|
Log.e(TAG(), e.toString())
|
||||||
|
appContext.toastFromMainThread(R.string.server_error)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (response.playlistId != null) {
|
||||||
|
appContext.toastFromMainThread(R.string.playlistCreated)
|
||||||
|
onSuccess.invoke()
|
||||||
|
} else {
|
||||||
|
appContext.toastFromMainThread(R.string.unknown_error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun addToPlaylist(playlistId: String, videoId: String): Boolean {
|
||||||
|
if (token == "") {
|
||||||
|
val localPlaylistItem = RetrofitInstance.api.getStreams(videoId).toLocalPlaylistItem(playlistId, videoId)
|
||||||
|
awaitQuery {
|
||||||
|
DatabaseHolder.Database.localPlaylistsDao().addPlaylistVideo(localPlaylistItem)
|
||||||
|
val localPlaylist = DatabaseHolder.Database.localPlaylistsDao().getAll()
|
||||||
|
.first { it.playlist.id.toString() == playlistId }.playlist
|
||||||
|
if (localPlaylist.thumbnailUrl == "") {
|
||||||
|
localPlaylistItem.thumbnailUrl?.let {
|
||||||
|
localPlaylist.thumbnailUrl = it
|
||||||
|
DatabaseHolder.Database.localPlaylistsDao().updatePlaylist(localPlaylist)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return RetrofitInstance.authApi.addToPlaylist(
|
||||||
|
token,
|
||||||
|
PlaylistId(playlistId, videoId)
|
||||||
|
).message == "ok"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getType(): PlaylistType {
|
||||||
|
return if (PreferenceHelper.getToken() != "") {
|
||||||
|
PlaylistType.PUBLIC
|
||||||
|
} else {
|
||||||
|
PlaylistType.LOCAL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,4 +9,5 @@ object IntentData {
|
|||||||
const val position = "position"
|
const val position = "position"
|
||||||
const val fileName = "fileName"
|
const val fileName = "fileName"
|
||||||
const val openQueueOnce = "openQueue"
|
const val openQueueOnce = "openQueue"
|
||||||
|
const val playlistType = "playlistType"
|
||||||
}
|
}
|
||||||
|
@ -4,16 +4,16 @@ import androidx.room.AutoMigration
|
|||||||
import androidx.room.Database
|
import androidx.room.Database
|
||||||
import androidx.room.RoomDatabase
|
import androidx.room.RoomDatabase
|
||||||
import com.github.libretube.db.dao.CustomInstanceDao
|
import com.github.libretube.db.dao.CustomInstanceDao
|
||||||
import com.github.libretube.db.dao.LocalSubscriptionDao
|
|
||||||
import com.github.libretube.db.dao.LocalPlaylistsDao
|
import com.github.libretube.db.dao.LocalPlaylistsDao
|
||||||
|
import com.github.libretube.db.dao.LocalSubscriptionDao
|
||||||
import com.github.libretube.db.dao.PlaylistBookmarkDao
|
import com.github.libretube.db.dao.PlaylistBookmarkDao
|
||||||
import com.github.libretube.db.dao.SearchHistoryDao
|
import com.github.libretube.db.dao.SearchHistoryDao
|
||||||
import com.github.libretube.db.dao.WatchHistoryDao
|
import com.github.libretube.db.dao.WatchHistoryDao
|
||||||
import com.github.libretube.db.dao.WatchPositionDao
|
import com.github.libretube.db.dao.WatchPositionDao
|
||||||
import com.github.libretube.db.obj.CustomInstance
|
import com.github.libretube.db.obj.CustomInstance
|
||||||
import com.github.libretube.db.obj.LocalSubscription
|
|
||||||
import com.github.libretube.db.obj.LocalPlaylist
|
import com.github.libretube.db.obj.LocalPlaylist
|
||||||
import com.github.libretube.db.obj.LocalPlaylistItem
|
import com.github.libretube.db.obj.LocalPlaylistItem
|
||||||
|
import com.github.libretube.db.obj.LocalSubscription
|
||||||
import com.github.libretube.db.obj.PlaylistBookmark
|
import com.github.libretube.db.obj.PlaylistBookmark
|
||||||
import com.github.libretube.db.obj.SearchHistoryItem
|
import com.github.libretube.db.obj.SearchHistoryItem
|
||||||
import com.github.libretube.db.obj.WatchHistoryItem
|
import com.github.libretube.db.obj.WatchHistoryItem
|
||||||
|
@ -25,9 +25,15 @@ interface LocalPlaylistsDao {
|
|||||||
@Delete
|
@Delete
|
||||||
fun deletePlaylist(playlist: LocalPlaylist)
|
fun deletePlaylist(playlist: LocalPlaylist)
|
||||||
|
|
||||||
|
@Query("DELETE FROM localPlaylist WHERE id = :playlistId")
|
||||||
|
fun deletePlaylistById(playlistId: String)
|
||||||
|
|
||||||
@Insert
|
@Insert
|
||||||
fun addPlaylistVideo(playlistVideo: LocalPlaylistItem)
|
fun addPlaylistVideo(playlistVideo: LocalPlaylistItem)
|
||||||
|
|
||||||
@Delete
|
@Delete
|
||||||
fun removePlaylistVideo(playlistVideo: LocalPlaylistItem)
|
fun removePlaylistVideo(playlistVideo: LocalPlaylistItem)
|
||||||
|
|
||||||
|
@Query("DELETE FROM localPlaylistItem WHERE playlistId = :playlistId")
|
||||||
|
fun deletePlaylistItemsByPlaylistId(playlistId: String)
|
||||||
}
|
}
|
||||||
|
@ -8,5 +8,5 @@ data class LocalPlaylist(
|
|||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
val id: Int = 0,
|
val id: Int = 0,
|
||||||
val name: String,
|
val name: String,
|
||||||
val thumbnailUrl: String
|
var thumbnailUrl: String
|
||||||
)
|
)
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
package com.github.libretube.enums
|
||||||
|
|
||||||
|
enum class PlaylistType {
|
||||||
|
LOCAL,
|
||||||
|
OWNED,
|
||||||
|
PUBLIC
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
package com.github.libretube.ui.extensions
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
|
import android.os.Bundle
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
|
inline fun <reified T : Serializable> Bundle.serializable(key: String): T? = when {
|
||||||
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> getSerializable(key, T::class.java)
|
||||||
|
else -> @Suppress("DEPRECATION") getSerializable(key) as? T
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package com.github.libretube.extensions
|
||||||
|
|
||||||
|
import com.github.libretube.api.obj.Streams
|
||||||
|
import com.github.libretube.db.obj.LocalPlaylistItem
|
||||||
|
|
||||||
|
fun Streams.toLocalPlaylistItem(playlistId: String, videoId: String): LocalPlaylistItem {
|
||||||
|
return LocalPlaylistItem(
|
||||||
|
playlistId = playlistId.toInt(),
|
||||||
|
videoId = videoId,
|
||||||
|
title = title,
|
||||||
|
thumbnailUrl = thumbnailUrl,
|
||||||
|
uploader = uploader,
|
||||||
|
uploaderUrl = uploaderUrl,
|
||||||
|
uploaderAvatar = uploaderAvatar,
|
||||||
|
uploadDate = uploadDate,
|
||||||
|
duration = duration
|
||||||
|
)
|
||||||
|
}
|
@ -2,6 +2,7 @@ package com.github.libretube.extensions
|
|||||||
|
|
||||||
import com.github.libretube.api.obj.StreamItem
|
import com.github.libretube.api.obj.StreamItem
|
||||||
import com.github.libretube.api.obj.Streams
|
import com.github.libretube.api.obj.Streams
|
||||||
|
import com.github.libretube.db.obj.LocalPlaylistItem
|
||||||
|
|
||||||
fun Streams.toStreamItem(videoId: String): StreamItem {
|
fun Streams.toStreamItem(videoId: String): StreamItem {
|
||||||
return StreamItem(
|
return StreamItem(
|
||||||
@ -19,3 +20,17 @@ fun Streams.toStreamItem(videoId: String): StreamItem {
|
|||||||
shortDescription = description
|
shortDescription = description
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun LocalPlaylistItem.toStreamItem(): StreamItem {
|
||||||
|
return StreamItem(
|
||||||
|
url = videoId,
|
||||||
|
title = title,
|
||||||
|
thumbnail = thumbnailUrl,
|
||||||
|
uploaderName = uploader,
|
||||||
|
uploaderUrl = uploaderUrl,
|
||||||
|
uploaderAvatar = uploaderAvatar,
|
||||||
|
uploadedDate = uploadDate,
|
||||||
|
uploaded = null,
|
||||||
|
duration = duration
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -5,16 +5,6 @@ import android.os.Handler
|
|||||||
import android.os.Looper
|
import android.os.Looper
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
|
||||||
fun Context.toastFromMainThread(stringId: Int) {
|
|
||||||
Handler(Looper.getMainLooper()).post {
|
|
||||||
Toast.makeText(
|
|
||||||
this,
|
|
||||||
stringId,
|
|
||||||
Toast.LENGTH_SHORT
|
|
||||||
).show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Context.toastFromMainThread(text: String) {
|
fun Context.toastFromMainThread(text: String) {
|
||||||
Handler(Looper.getMainLooper()).post {
|
Handler(Looper.getMainLooper()).post {
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
@ -24,3 +14,7 @@ fun Context.toastFromMainThread(text: String) {
|
|||||||
).show()
|
).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Context.toastFromMainThread(stringId: Int) {
|
||||||
|
toastFromMainThread(getString(stringId))
|
||||||
|
}
|
||||||
|
@ -11,6 +11,7 @@ import com.github.libretube.api.RetrofitInstance
|
|||||||
import com.github.libretube.api.obj.PlaylistId
|
import com.github.libretube.api.obj.PlaylistId
|
||||||
import com.github.libretube.api.obj.StreamItem
|
import com.github.libretube.api.obj.StreamItem
|
||||||
import com.github.libretube.databinding.PlaylistRowBinding
|
import com.github.libretube.databinding.PlaylistRowBinding
|
||||||
|
import com.github.libretube.enums.PlaylistType
|
||||||
import com.github.libretube.extensions.TAG
|
import com.github.libretube.extensions.TAG
|
||||||
import com.github.libretube.extensions.toID
|
import com.github.libretube.extensions.toID
|
||||||
import com.github.libretube.ui.base.BaseActivity
|
import com.github.libretube.ui.base.BaseActivity
|
||||||
@ -30,7 +31,7 @@ import java.io.IOException
|
|||||||
class PlaylistAdapter(
|
class PlaylistAdapter(
|
||||||
private val videoFeed: MutableList<StreamItem>,
|
private val videoFeed: MutableList<StreamItem>,
|
||||||
private val playlistId: String,
|
private val playlistId: String,
|
||||||
private val isOwner: Boolean
|
private val playlistType: PlaylistType
|
||||||
) : RecyclerView.Adapter<PlaylistViewHolder>() {
|
) : RecyclerView.Adapter<PlaylistViewHolder>() {
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
override fun getItemCount(): Int {
|
||||||
@ -70,7 +71,7 @@ class PlaylistAdapter(
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isOwner) {
|
if (playlistType != PlaylistType.PUBLIC) {
|
||||||
deletePlaylist.visibility = View.VISIBLE
|
deletePlaylist.visibility = View.VISIBLE
|
||||||
deletePlaylist.setOnClickListener {
|
deletePlaylist.setOnClickListener {
|
||||||
removeFromPlaylist(root.context, position)
|
removeFromPlaylist(root.context, position)
|
||||||
|
@ -6,6 +6,7 @@ import androidx.appcompat.app.AppCompatActivity
|
|||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.github.libretube.databinding.PlaylistBookmarkRowBinding
|
import com.github.libretube.databinding.PlaylistBookmarkRowBinding
|
||||||
import com.github.libretube.db.obj.PlaylistBookmark
|
import com.github.libretube.db.obj.PlaylistBookmark
|
||||||
|
import com.github.libretube.enums.PlaylistType
|
||||||
import com.github.libretube.extensions.toDp
|
import com.github.libretube.extensions.toDp
|
||||||
import com.github.libretube.ui.sheets.PlaylistOptionsBottomSheet
|
import com.github.libretube.ui.sheets.PlaylistOptionsBottomSheet
|
||||||
import com.github.libretube.ui.viewholders.PlaylistBookmarkViewHolder
|
import com.github.libretube.ui.viewholders.PlaylistBookmarkViewHolder
|
||||||
@ -39,14 +40,14 @@ class PlaylistBookmarkAdapter(
|
|||||||
uploaderName.text = bookmark.uploader
|
uploaderName.text = bookmark.uploader
|
||||||
|
|
||||||
root.setOnClickListener {
|
root.setOnClickListener {
|
||||||
NavigationHelper.navigatePlaylist(root.context, bookmark.playlistId, false)
|
NavigationHelper.navigatePlaylist(root.context, bookmark.playlistId, PlaylistType.PUBLIC)
|
||||||
}
|
}
|
||||||
|
|
||||||
root.setOnLongClickListener {
|
root.setOnLongClickListener {
|
||||||
PlaylistOptionsBottomSheet(
|
PlaylistOptionsBottomSheet(
|
||||||
playlistId = bookmark.playlistId,
|
playlistId = bookmark.playlistId,
|
||||||
playlistName = bookmark.playlistName ?: "",
|
playlistName = bookmark.playlistName ?: "",
|
||||||
isOwner = false
|
playlistType = PlaylistType.PUBLIC
|
||||||
).show(
|
).show(
|
||||||
(root.context as AppCompatActivity).supportFragmentManager
|
(root.context as AppCompatActivity).supportFragmentManager
|
||||||
)
|
)
|
||||||
|
@ -6,6 +6,7 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import com.github.libretube.R
|
import com.github.libretube.R
|
||||||
import com.github.libretube.api.obj.Playlists
|
import com.github.libretube.api.obj.Playlists
|
||||||
import com.github.libretube.databinding.PlaylistsRowBinding
|
import com.github.libretube.databinding.PlaylistsRowBinding
|
||||||
|
import com.github.libretube.enums.PlaylistType
|
||||||
import com.github.libretube.ui.base.BaseActivity
|
import com.github.libretube.ui.base.BaseActivity
|
||||||
import com.github.libretube.ui.dialogs.DeletePlaylistDialog
|
import com.github.libretube.ui.dialogs.DeletePlaylistDialog
|
||||||
import com.github.libretube.ui.sheets.PlaylistOptionsBottomSheet
|
import com.github.libretube.ui.sheets.PlaylistOptionsBottomSheet
|
||||||
@ -14,7 +15,8 @@ import com.github.libretube.util.ImageHelper
|
|||||||
import com.github.libretube.util.NavigationHelper
|
import com.github.libretube.util.NavigationHelper
|
||||||
|
|
||||||
class PlaylistsAdapter(
|
class PlaylistsAdapter(
|
||||||
private val playlists: MutableList<Playlists>
|
private val playlists: MutableList<Playlists>,
|
||||||
|
private val playlistType: PlaylistType
|
||||||
) : RecyclerView.Adapter<PlaylistsViewHolder>() {
|
) : RecyclerView.Adapter<PlaylistsViewHolder>() {
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
override fun getItemCount(): Int {
|
||||||
@ -48,7 +50,7 @@ class PlaylistsAdapter(
|
|||||||
videoCount.text = playlist.videos.toString()
|
videoCount.text = playlist.videos.toString()
|
||||||
|
|
||||||
deletePlaylist.setOnClickListener {
|
deletePlaylist.setOnClickListener {
|
||||||
DeletePlaylistDialog(playlist.id!!) {
|
DeletePlaylistDialog(playlist.id!!, playlistType) {
|
||||||
playlists.removeAt(position)
|
playlists.removeAt(position)
|
||||||
(root.context as BaseActivity).runOnUiThread {
|
(root.context as BaseActivity).runOnUiThread {
|
||||||
notifyItemRemoved(position)
|
notifyItemRemoved(position)
|
||||||
@ -60,14 +62,14 @@ class PlaylistsAdapter(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
root.setOnClickListener {
|
root.setOnClickListener {
|
||||||
NavigationHelper.navigatePlaylist(root.context, playlist.id, true)
|
NavigationHelper.navigatePlaylist(root.context, playlist.id, playlistType)
|
||||||
}
|
}
|
||||||
|
|
||||||
root.setOnLongClickListener {
|
root.setOnLongClickListener {
|
||||||
val playlistOptionsDialog = PlaylistOptionsBottomSheet(
|
val playlistOptionsDialog = PlaylistOptionsBottomSheet(
|
||||||
playlistId = playlist.id!!,
|
playlistId = playlist.id!!,
|
||||||
playlistName = playlist.name!!,
|
playlistName = playlist.name!!,
|
||||||
isOwner = true
|
playlistType = playlistType
|
||||||
)
|
)
|
||||||
playlistOptionsDialog.show(
|
playlistOptionsDialog.show(
|
||||||
(root.context as BaseActivity).supportFragmentManager,
|
(root.context as BaseActivity).supportFragmentManager,
|
||||||
|
@ -10,6 +10,7 @@ import com.github.libretube.api.obj.ContentItem
|
|||||||
import com.github.libretube.databinding.ChannelRowBinding
|
import com.github.libretube.databinding.ChannelRowBinding
|
||||||
import com.github.libretube.databinding.PlaylistsRowBinding
|
import com.github.libretube.databinding.PlaylistsRowBinding
|
||||||
import com.github.libretube.databinding.VideoRowBinding
|
import com.github.libretube.databinding.VideoRowBinding
|
||||||
|
import com.github.libretube.enums.PlaylistType
|
||||||
import com.github.libretube.extensions.formatShort
|
import com.github.libretube.extensions.formatShort
|
||||||
import com.github.libretube.extensions.toID
|
import com.github.libretube.extensions.toID
|
||||||
import com.github.libretube.ui.base.BaseActivity
|
import com.github.libretube.ui.base.BaseActivity
|
||||||
@ -140,13 +141,13 @@ class SearchAdapter(
|
|||||||
playlistTitle.text = item.name
|
playlistTitle.text = item.name
|
||||||
playlistDescription.text = item.uploaderName
|
playlistDescription.text = item.uploaderName
|
||||||
root.setOnClickListener {
|
root.setOnClickListener {
|
||||||
NavigationHelper.navigatePlaylist(root.context, item.url, false)
|
NavigationHelper.navigatePlaylist(root.context, item.url, PlaylistType.PUBLIC)
|
||||||
}
|
}
|
||||||
deletePlaylist.visibility = View.GONE
|
deletePlaylist.visibility = View.GONE
|
||||||
root.setOnLongClickListener {
|
root.setOnLongClickListener {
|
||||||
val playlistId = item.url!!.toID()
|
val playlistId = item.url!!.toID()
|
||||||
val playlistName = item.name!!
|
val playlistName = item.name!!
|
||||||
PlaylistOptionsBottomSheet(playlistId, playlistName, false)
|
PlaylistOptionsBottomSheet(playlistId, playlistName, PlaylistType.PUBLIC)
|
||||||
.show((root.context as BaseActivity).supportFragmentManager, PlaylistOptionsBottomSheet::class.java.name)
|
.show((root.context as BaseActivity).supportFragmentManager, PlaylistOptionsBottomSheet::class.java.name)
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -10,28 +10,23 @@ import androidx.fragment.app.Fragment
|
|||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.github.libretube.R
|
import com.github.libretube.R
|
||||||
import com.github.libretube.api.RetrofitInstance
|
import com.github.libretube.api.PlaylistsHelper
|
||||||
import com.github.libretube.api.obj.PlaylistId
|
|
||||||
import com.github.libretube.constants.IntentData
|
import com.github.libretube.constants.IntentData
|
||||||
import com.github.libretube.databinding.DialogAddtoplaylistBinding
|
import com.github.libretube.databinding.DialogAddtoplaylistBinding
|
||||||
import com.github.libretube.extensions.TAG
|
import com.github.libretube.extensions.TAG
|
||||||
import com.github.libretube.extensions.toastFromMainThread
|
import com.github.libretube.extensions.toastFromMainThread
|
||||||
import com.github.libretube.ui.models.PlaylistViewModel
|
import com.github.libretube.ui.models.PlaylistViewModel
|
||||||
import com.github.libretube.util.PreferenceHelper
|
|
||||||
import com.github.libretube.util.ThemeHelper
|
import com.github.libretube.util.ThemeHelper
|
||||||
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 retrofit2.HttpException
|
|
||||||
import java.io.IOException
|
|
||||||
|
|
||||||
class AddToPlaylistDialog : DialogFragment() {
|
class AddToPlaylistDialog : DialogFragment() {
|
||||||
private lateinit var binding: DialogAddtoplaylistBinding
|
private lateinit var binding: DialogAddtoplaylistBinding
|
||||||
private val viewModel: PlaylistViewModel by activityViewModels()
|
private val viewModel: PlaylistViewModel by activityViewModels()
|
||||||
|
|
||||||
private lateinit var videoId: String
|
private lateinit var videoId: String
|
||||||
private lateinit var token: String
|
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
videoId = arguments?.getString(IntentData.videoId)!!
|
videoId = arguments?.getString(IntentData.videoId)!!
|
||||||
@ -46,9 +41,7 @@ class AddToPlaylistDialog : DialogFragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
token = PreferenceHelper.getToken()
|
fetchPlaylists()
|
||||||
|
|
||||||
if (token != "") fetchPlaylists()
|
|
||||||
|
|
||||||
return MaterialAlertDialogBuilder(requireContext())
|
return MaterialAlertDialogBuilder(requireContext())
|
||||||
.setView(binding.root)
|
.setView(binding.root)
|
||||||
@ -58,16 +51,11 @@ class AddToPlaylistDialog : DialogFragment() {
|
|||||||
private fun fetchPlaylists() {
|
private fun fetchPlaylists() {
|
||||||
lifecycleScope.launchWhenCreated {
|
lifecycleScope.launchWhenCreated {
|
||||||
val response = try {
|
val response = try {
|
||||||
RetrofitInstance.authApi.getUserPlaylists(token)
|
PlaylistsHelper.getPlaylists()
|
||||||
} catch (e: IOException) {
|
} catch (e: Exception) {
|
||||||
println(e)
|
Log.e(TAG(), e.toString())
|
||||||
Log.e(TAG(), "IOException, you might not have internet connection")
|
|
||||||
Toast.makeText(context, R.string.unknown_error, Toast.LENGTH_SHORT).show()
|
Toast.makeText(context, R.string.unknown_error, Toast.LENGTH_SHORT).show()
|
||||||
return@launchWhenCreated
|
return@launchWhenCreated
|
||||||
} catch (e: HttpException) {
|
|
||||||
Log.e(TAG(), "HttpException, unexpected response")
|
|
||||||
Toast.makeText(context, R.string.server_error, Toast.LENGTH_SHORT).show()
|
|
||||||
return@launchWhenCreated
|
|
||||||
}
|
}
|
||||||
if (response.isNotEmpty()) {
|
if (response.isNotEmpty()) {
|
||||||
val names = response.map { it.name }
|
val names = response.map { it.name }
|
||||||
@ -81,8 +69,7 @@ class AddToPlaylistDialog : DialogFragment() {
|
|||||||
var selectionIndex = 0
|
var selectionIndex = 0
|
||||||
response.forEachIndexed { index, playlist ->
|
response.forEachIndexed { index, playlist ->
|
||||||
if (playlist.id == viewModel.lastSelectedPlaylistId) {
|
if (playlist.id == viewModel.lastSelectedPlaylistId) {
|
||||||
selectionIndex =
|
selectionIndex = index
|
||||||
index
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
binding.playlistsSpinner.setSelection(selectionIndex)
|
binding.playlistsSpinner.setSelection(selectionIndex)
|
||||||
@ -102,23 +89,15 @@ class AddToPlaylistDialog : DialogFragment() {
|
|||||||
private fun addToPlaylist(playlistId: String) {
|
private fun addToPlaylist(playlistId: String) {
|
||||||
val appContext = context?.applicationContext ?: return
|
val appContext = context?.applicationContext ?: return
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
val response = try {
|
val success = try {
|
||||||
RetrofitInstance.authApi.addToPlaylist(
|
PlaylistsHelper.addToPlaylist(playlistId, videoId)
|
||||||
token,
|
} catch (e: Exception) {
|
||||||
PlaylistId(playlistId, videoId)
|
Log.e(TAG(), e.toString())
|
||||||
)
|
|
||||||
} catch (e: IOException) {
|
|
||||||
println(e)
|
|
||||||
Log.e(TAG(), "IOException, you might not have internet connection")
|
|
||||||
appContext.toastFromMainThread(R.string.unknown_error)
|
appContext.toastFromMainThread(R.string.unknown_error)
|
||||||
return@launch
|
return@launch
|
||||||
} catch (e: HttpException) {
|
|
||||||
Log.e(TAG(), "HttpException, unexpected response")
|
|
||||||
appContext.toastFromMainThread(R.string.server_error)
|
|
||||||
return@launch
|
|
||||||
}
|
}
|
||||||
appContext.toastFromMainThread(
|
appContext.toastFromMainThread(
|
||||||
if (response.message == "ok") R.string.added_to_playlist else R.string.fail
|
if (success) R.string.added_to_playlist else R.string.fail
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,25 +2,18 @@ package com.github.libretube.ui.dialogs
|
|||||||
|
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.github.libretube.R
|
import com.github.libretube.R
|
||||||
import com.github.libretube.api.RetrofitInstance
|
import com.github.libretube.api.PlaylistsHelper
|
||||||
import com.github.libretube.api.obj.Playlists
|
|
||||||
import com.github.libretube.databinding.DialogCreatePlaylistBinding
|
import com.github.libretube.databinding.DialogCreatePlaylistBinding
|
||||||
import com.github.libretube.extensions.TAG
|
|
||||||
import com.github.libretube.util.PreferenceHelper
|
|
||||||
import com.github.libretube.util.ThemeHelper
|
import com.github.libretube.util.ThemeHelper
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import retrofit2.HttpException
|
|
||||||
import java.io.IOException
|
|
||||||
|
|
||||||
class CreatePlaylistDialog(
|
class CreatePlaylistDialog(
|
||||||
private val onSuccess: () -> Unit = {}
|
private val onSuccess: () -> Unit = {}
|
||||||
) : DialogFragment() {
|
) : DialogFragment() {
|
||||||
private var token: String = ""
|
|
||||||
private lateinit var binding: DialogCreatePlaylistBinding
|
private lateinit var binding: DialogCreatePlaylistBinding
|
||||||
|
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
@ -32,14 +25,17 @@ class CreatePlaylistDialog(
|
|||||||
dismiss()
|
dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
token = PreferenceHelper.getToken()
|
|
||||||
|
|
||||||
binding.createNewPlaylist.setOnClickListener {
|
binding.createNewPlaylist.setOnClickListener {
|
||||||
// avoid creating the same playlist multiple times by spamming the button
|
// avoid creating the same playlist multiple times by spamming the button
|
||||||
binding.createNewPlaylist.setOnClickListener(null)
|
binding.createNewPlaylist.setOnClickListener(null)
|
||||||
val listName = binding.playlistName.text.toString()
|
val listName = binding.playlistName.text.toString()
|
||||||
if (listName != "") {
|
if (listName != "") {
|
||||||
createPlaylist(listName)
|
lifecycleScope.launchWhenCreated {
|
||||||
|
PlaylistsHelper.createPlaylist(listName, requireContext().applicationContext) {
|
||||||
|
onSuccess.invoke()
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(context, R.string.emptyPlaylistName, Toast.LENGTH_LONG).show()
|
Toast.makeText(context, R.string.emptyPlaylistName, Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
@ -49,37 +45,4 @@ class CreatePlaylistDialog(
|
|||||||
.setView(binding.root)
|
.setView(binding.root)
|
||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createPlaylist(name: String) {
|
|
||||||
lifecycleScope.launchWhenCreated {
|
|
||||||
val response = try {
|
|
||||||
RetrofitInstance.authApi.createPlaylist(
|
|
||||||
token,
|
|
||||||
Playlists(name = name)
|
|
||||||
)
|
|
||||||
} catch (e: IOException) {
|
|
||||||
println(e)
|
|
||||||
Log.e(TAG(), "IOException, you might not have internet connection")
|
|
||||||
Toast.makeText(context, R.string.unknown_error, Toast.LENGTH_SHORT).show()
|
|
||||||
return@launchWhenCreated
|
|
||||||
} catch (e: HttpException) {
|
|
||||||
Log.e(TAG(), "HttpException, unexpected response $e")
|
|
||||||
Toast.makeText(context, R.string.server_error, Toast.LENGTH_SHORT).show()
|
|
||||||
return@launchWhenCreated
|
|
||||||
}
|
|
||||||
if (response.playlistId != null) {
|
|
||||||
Toast.makeText(context, R.string.playlistCreated, Toast.LENGTH_SHORT).show()
|
|
||||||
} else {
|
|
||||||
Toast.makeText(context, getString(R.string.unknown_error), Toast.LENGTH_SHORT)
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
// refresh the playlists in the library
|
|
||||||
try {
|
|
||||||
onSuccess.invoke()
|
|
||||||
} catch (e: Exception) {
|
|
||||||
Log.e(TAG(), e.toString())
|
|
||||||
}
|
|
||||||
dismiss()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,10 @@ import androidx.fragment.app.DialogFragment
|
|||||||
import com.github.libretube.R
|
import com.github.libretube.R
|
||||||
import com.github.libretube.api.RetrofitInstance
|
import com.github.libretube.api.RetrofitInstance
|
||||||
import com.github.libretube.api.obj.PlaylistId
|
import com.github.libretube.api.obj.PlaylistId
|
||||||
|
import com.github.libretube.db.DatabaseHolder
|
||||||
|
import com.github.libretube.enums.PlaylistType
|
||||||
import com.github.libretube.extensions.TAG
|
import com.github.libretube.extensions.TAG
|
||||||
|
import com.github.libretube.extensions.awaitQuery
|
||||||
import com.github.libretube.util.PreferenceHelper
|
import com.github.libretube.util.PreferenceHelper
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
@ -16,6 +19,7 @@ import kotlinx.coroutines.launch
|
|||||||
|
|
||||||
class DeletePlaylistDialog(
|
class DeletePlaylistDialog(
|
||||||
private val playlistId: String,
|
private val playlistId: String,
|
||||||
|
private val playlistType: PlaylistType,
|
||||||
private val onSuccess: () -> Unit = {}
|
private val onSuccess: () -> Unit = {}
|
||||||
) : DialogFragment() {
|
) : DialogFragment() {
|
||||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
@ -31,6 +35,14 @@ class DeletePlaylistDialog(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun deletePlaylist() {
|
private fun deletePlaylist() {
|
||||||
|
if (playlistType == PlaylistType.LOCAL) {
|
||||||
|
awaitQuery {
|
||||||
|
DatabaseHolder.Database.localPlaylistsDao().deletePlaylistById(playlistId)
|
||||||
|
DatabaseHolder.Database.localPlaylistsDao().deletePlaylistItemsByPlaylistId(playlistId)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
val response = try {
|
val response = try {
|
||||||
RetrofitInstance.authApi.deletePlaylist(
|
RetrofitInstance.authApi.deletePlaylist(
|
||||||
|
@ -11,6 +11,7 @@ import androidx.recyclerview.widget.GridLayoutManager
|
|||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.github.libretube.R
|
import com.github.libretube.R
|
||||||
|
import com.github.libretube.api.PlaylistsHelper
|
||||||
import com.github.libretube.api.RetrofitInstance
|
import com.github.libretube.api.RetrofitInstance
|
||||||
import com.github.libretube.api.SubscriptionHelper
|
import com.github.libretube.api.SubscriptionHelper
|
||||||
import com.github.libretube.databinding.FragmentHomeBinding
|
import com.github.libretube.databinding.FragmentHomeBinding
|
||||||
@ -101,13 +102,12 @@ class HomeFragment : BaseFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
runOrError {
|
runOrError {
|
||||||
if (token == "") return@runOrError
|
val playlists = PlaylistsHelper.getPlaylists().withMaxSize(20)
|
||||||
val playlists = RetrofitInstance.authApi.getUserPlaylists(token).withMaxSize(20)
|
|
||||||
if (playlists.isEmpty()) return@runOrError
|
if (playlists.isEmpty()) return@runOrError
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
makeVisible(binding.playlistsRV, binding.playlistsTV)
|
makeVisible(binding.playlistsRV, binding.playlistsTV)
|
||||||
binding.playlistsRV.layoutManager = LinearLayoutManager(context)
|
binding.playlistsRV.layoutManager = LinearLayoutManager(context)
|
||||||
binding.playlistsRV.adapter = PlaylistsAdapter(playlists.toMutableList())
|
binding.playlistsRV.adapter = PlaylistsAdapter(playlists.toMutableList(), PlaylistsHelper.getType())
|
||||||
binding.playlistsRV.adapter?.registerAdapterDataObserver(object :
|
binding.playlistsRV.adapter?.registerAdapterDataObserver(object :
|
||||||
RecyclerView.AdapterDataObserver() {
|
RecyclerView.AdapterDataObserver() {
|
||||||
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
|
override fun onItemRangeRemoved(positionStart: Int, itemCount: Int) {
|
||||||
|
@ -12,7 +12,7 @@ import androidx.navigation.fragment.findNavController
|
|||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.github.libretube.R
|
import com.github.libretube.R
|
||||||
import com.github.libretube.api.RetrofitInstance
|
import com.github.libretube.api.PlaylistsHelper
|
||||||
import com.github.libretube.constants.PreferenceKeys
|
import com.github.libretube.constants.PreferenceKeys
|
||||||
import com.github.libretube.databinding.FragmentLibraryBinding
|
import com.github.libretube.databinding.FragmentLibraryBinding
|
||||||
import com.github.libretube.extensions.TAG
|
import com.github.libretube.extensions.TAG
|
||||||
@ -22,8 +22,6 @@ import com.github.libretube.ui.base.BaseFragment
|
|||||||
import com.github.libretube.ui.dialogs.CreatePlaylistDialog
|
import com.github.libretube.ui.dialogs.CreatePlaylistDialog
|
||||||
import com.github.libretube.ui.models.PlayerViewModel
|
import com.github.libretube.ui.models.PlayerViewModel
|
||||||
import com.github.libretube.util.PreferenceHelper
|
import com.github.libretube.util.PreferenceHelper
|
||||||
import retrofit2.HttpException
|
|
||||||
import java.io.IOException
|
|
||||||
|
|
||||||
class LibraryFragment : BaseFragment() {
|
class LibraryFragment : BaseFragment() {
|
||||||
|
|
||||||
@ -70,26 +68,16 @@ class LibraryFragment : BaseFragment() {
|
|||||||
findNavController().navigate(R.id.downloadsFragment)
|
findNavController().navigate(R.id.downloadsFragment)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (token != "") {
|
fetchPlaylists()
|
||||||
binding.boogh.setImageResource(R.drawable.ic_list)
|
|
||||||
binding.textLike.text = getString(R.string.emptyList)
|
|
||||||
|
|
||||||
binding.loginOrRegister.visibility = View.GONE
|
binding.playlistRefresh.isEnabled = true
|
||||||
|
binding.playlistRefresh.setOnRefreshListener {
|
||||||
fetchPlaylists()
|
fetchPlaylists()
|
||||||
|
}
|
||||||
binding.playlistRefresh.isEnabled = true
|
binding.createPlaylist.setOnClickListener {
|
||||||
binding.playlistRefresh.setOnRefreshListener {
|
CreatePlaylistDialog {
|
||||||
fetchPlaylists()
|
fetchPlaylists()
|
||||||
}
|
}.show(childFragmentManager, CreatePlaylistDialog::class.java.name)
|
||||||
binding.createPlaylist.setOnClickListener {
|
|
||||||
val newFragment = CreatePlaylistDialog {
|
|
||||||
fetchPlaylists()
|
|
||||||
}
|
|
||||||
newFragment.show(childFragmentManager, CreatePlaylistDialog::class.java.name)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
binding.playlistRefresh.isEnabled = false
|
|
||||||
binding.createPlaylist.visibility = View.GONE
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,26 +89,19 @@ class LibraryFragment : BaseFragment() {
|
|||||||
binding.createPlaylist.layoutParams = layoutParams
|
binding.createPlaylist.layoutParams = layoutParams
|
||||||
}
|
}
|
||||||
|
|
||||||
fun fetchPlaylists() {
|
private fun fetchPlaylists() {
|
||||||
binding.playlistRefresh.isRefreshing = true
|
binding.playlistRefresh.isRefreshing = true
|
||||||
lifecycleScope.launchWhenCreated {
|
lifecycleScope.launchWhenCreated {
|
||||||
var playlists = try {
|
var playlists = try {
|
||||||
RetrofitInstance.authApi.getUserPlaylists(token)
|
PlaylistsHelper.getPlaylists()
|
||||||
} catch (e: IOException) {
|
} catch (e: Exception) {
|
||||||
println(e)
|
Log.e(TAG(), e.toString())
|
||||||
Log.e(TAG(), "IOException, you might not have internet connection")
|
|
||||||
Toast.makeText(context, R.string.unknown_error, Toast.LENGTH_SHORT).show()
|
Toast.makeText(context, R.string.unknown_error, Toast.LENGTH_SHORT).show()
|
||||||
return@launchWhenCreated
|
return@launchWhenCreated
|
||||||
} catch (e: HttpException) {
|
|
||||||
Log.e(TAG(), "HttpException, unexpected response")
|
|
||||||
Toast.makeText(context, R.string.server_error, Toast.LENGTH_SHORT).show()
|
|
||||||
return@launchWhenCreated
|
|
||||||
} finally {
|
} finally {
|
||||||
binding.playlistRefresh.isRefreshing = false
|
binding.playlistRefresh.isRefreshing = false
|
||||||
}
|
}
|
||||||
if (playlists.isNotEmpty()) {
|
if (playlists.isNotEmpty()) {
|
||||||
binding.loginOrRegister.visibility = View.GONE
|
|
||||||
|
|
||||||
playlists = when (
|
playlists = when (
|
||||||
PreferenceHelper.getString(
|
PreferenceHelper.getString(
|
||||||
PreferenceKeys.PLAYLISTS_ORDER,
|
PreferenceKeys.PLAYLISTS_ORDER,
|
||||||
@ -135,16 +116,15 @@ class LibraryFragment : BaseFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val playlistsAdapter = PlaylistsAdapter(
|
val playlistsAdapter = PlaylistsAdapter(
|
||||||
playlists.toMutableList()
|
playlists.toMutableList(),
|
||||||
|
PlaylistsHelper.getType()
|
||||||
)
|
)
|
||||||
|
|
||||||
// listen for playlists to become deleted
|
// listen for playlists to become deleted
|
||||||
playlistsAdapter.registerAdapterDataObserver(object :
|
playlistsAdapter.registerAdapterDataObserver(object :
|
||||||
RecyclerView.AdapterDataObserver() {
|
RecyclerView.AdapterDataObserver() {
|
||||||
override fun onChanged() {
|
override fun onChanged() {
|
||||||
if (playlistsAdapter.itemCount == 0) {
|
binding.nothingHere.visibility = if (playlistsAdapter.itemCount == 0) View.VISIBLE else View.GONE
|
||||||
binding.loginOrRegister.visibility = View.VISIBLE
|
|
||||||
}
|
|
||||||
super.onChanged()
|
super.onChanged()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -152,7 +132,7 @@ class LibraryFragment : BaseFragment() {
|
|||||||
binding.playlistRecView.adapter = playlistsAdapter
|
binding.playlistRecView.adapter = playlistsAdapter
|
||||||
} else {
|
} else {
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
binding.loginOrRegister.visibility = View.VISIBLE
|
binding.nothingHere.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,17 +11,20 @@ import androidx.recyclerview.widget.ItemTouchHelper
|
|||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.github.libretube.R
|
import com.github.libretube.R
|
||||||
|
import com.github.libretube.api.PlaylistsHelper
|
||||||
import com.github.libretube.api.RetrofitInstance
|
import com.github.libretube.api.RetrofitInstance
|
||||||
import com.github.libretube.constants.IntentData
|
import com.github.libretube.constants.IntentData
|
||||||
import com.github.libretube.databinding.FragmentPlaylistBinding
|
import com.github.libretube.databinding.FragmentPlaylistBinding
|
||||||
import com.github.libretube.db.DatabaseHolder
|
import com.github.libretube.db.DatabaseHolder
|
||||||
import com.github.libretube.db.obj.PlaylistBookmark
|
import com.github.libretube.db.obj.PlaylistBookmark
|
||||||
|
import com.github.libretube.enums.PlaylistType
|
||||||
import com.github.libretube.extensions.TAG
|
import com.github.libretube.extensions.TAG
|
||||||
import com.github.libretube.extensions.awaitQuery
|
import com.github.libretube.extensions.awaitQuery
|
||||||
import com.github.libretube.extensions.query
|
import com.github.libretube.extensions.query
|
||||||
import com.github.libretube.extensions.toID
|
import com.github.libretube.extensions.toID
|
||||||
import com.github.libretube.ui.adapters.PlaylistAdapter
|
import com.github.libretube.ui.adapters.PlaylistAdapter
|
||||||
import com.github.libretube.ui.base.BaseFragment
|
import com.github.libretube.ui.base.BaseFragment
|
||||||
|
import com.github.libretube.ui.extensions.serializable
|
||||||
import com.github.libretube.ui.sheets.PlaylistOptionsBottomSheet
|
import com.github.libretube.ui.sheets.PlaylistOptionsBottomSheet
|
||||||
import com.github.libretube.util.ImageHelper
|
import com.github.libretube.util.ImageHelper
|
||||||
import com.github.libretube.util.NavigationHelper
|
import com.github.libretube.util.NavigationHelper
|
||||||
@ -34,7 +37,7 @@ class PlaylistFragment : BaseFragment() {
|
|||||||
|
|
||||||
private var playlistId: String? = null
|
private var playlistId: String? = null
|
||||||
private var playlistName: String? = null
|
private var playlistName: String? = null
|
||||||
private var isOwner: Boolean = false
|
private var playlistType: PlaylistType = PlaylistType.PUBLIC
|
||||||
private var nextPage: String? = null
|
private var nextPage: String? = null
|
||||||
private var playlistAdapter: PlaylistAdapter? = null
|
private var playlistAdapter: PlaylistAdapter? = null
|
||||||
private var isLoading = true
|
private var isLoading = true
|
||||||
@ -44,7 +47,7 @@ class PlaylistFragment : BaseFragment() {
|
|||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
arguments?.let {
|
arguments?.let {
|
||||||
playlistId = it.getString(IntentData.playlistId)
|
playlistId = it.getString(IntentData.playlistId)
|
||||||
isOwner = it.getBoolean("isOwner")
|
playlistType = it.serializable(IntentData.playlistType)!!
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,12 +87,7 @@ class PlaylistFragment : BaseFragment() {
|
|||||||
binding.playlistScrollview.visibility = View.GONE
|
binding.playlistScrollview.visibility = View.GONE
|
||||||
lifecycleScope.launchWhenCreated {
|
lifecycleScope.launchWhenCreated {
|
||||||
val response = try {
|
val response = try {
|
||||||
// load locally stored playlists with the auth api
|
PlaylistsHelper.getPlaylist(playlistType, playlistId!!)
|
||||||
if (isOwner) {
|
|
||||||
RetrofitInstance.authApi.getPlaylist(playlistId!!)
|
|
||||||
} else {
|
|
||||||
RetrofitInstance.api.getPlaylist(playlistId!!)
|
|
||||||
}
|
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
println(e)
|
println(e)
|
||||||
Log.e(TAG(), "IOException, you might not have internet connection")
|
Log.e(TAG(), "IOException, you might not have internet connection")
|
||||||
@ -116,7 +114,7 @@ class PlaylistFragment : BaseFragment() {
|
|||||||
|
|
||||||
// show playlist options
|
// show playlist options
|
||||||
binding.optionsMenu.setOnClickListener {
|
binding.optionsMenu.setOnClickListener {
|
||||||
PlaylistOptionsBottomSheet(playlistId!!, playlistName ?: "", isOwner).show(
|
PlaylistOptionsBottomSheet(playlistId!!, playlistName ?: "", playlistType).show(
|
||||||
childFragmentManager,
|
childFragmentManager,
|
||||||
PlaylistOptionsBottomSheet::class.java.name
|
PlaylistOptionsBottomSheet::class.java.name
|
||||||
)
|
)
|
||||||
@ -131,7 +129,7 @@ class PlaylistFragment : BaseFragment() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isOwner) binding.bookmark.visibility = View.GONE
|
if (playlistType != PlaylistType.PUBLIC) binding.bookmark.visibility = View.GONE
|
||||||
|
|
||||||
binding.bookmark.setOnClickListener {
|
binding.bookmark.setOnClickListener {
|
||||||
isBookmarked = !isBookmarked
|
isBookmarked = !isBookmarked
|
||||||
@ -157,7 +155,7 @@ class PlaylistFragment : BaseFragment() {
|
|||||||
playlistAdapter = PlaylistAdapter(
|
playlistAdapter = PlaylistAdapter(
|
||||||
response.relatedStreams.orEmpty().toMutableList(),
|
response.relatedStreams.orEmpty().toMutableList(),
|
||||||
playlistId!!,
|
playlistId!!,
|
||||||
isOwner
|
playlistType
|
||||||
)
|
)
|
||||||
|
|
||||||
// listen for playlist items to become deleted
|
// listen for playlist items to become deleted
|
||||||
@ -189,7 +187,7 @@ class PlaylistFragment : BaseFragment() {
|
|||||||
/**
|
/**
|
||||||
* listener for swiping to the left or right
|
* listener for swiping to the left or right
|
||||||
*/
|
*/
|
||||||
if (isOwner) {
|
if (playlistType != PlaylistType.PUBLIC) {
|
||||||
val itemTouchCallback = object : ItemTouchHelper.SimpleCallback(
|
val itemTouchCallback = object : ItemTouchHelper.SimpleCallback(
|
||||||
0,
|
0,
|
||||||
ItemTouchHelper.LEFT
|
ItemTouchHelper.LEFT
|
||||||
@ -219,34 +217,27 @@ class PlaylistFragment : BaseFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchNextPage() {
|
private fun fetchNextPage() {
|
||||||
fun run() {
|
lifecycleScope.launchWhenCreated {
|
||||||
lifecycleScope.launchWhenCreated {
|
val response = try {
|
||||||
val response = try {
|
// load locally stored playlists with the auth api
|
||||||
// load locally stored playlists with the auth api
|
if (playlistType == PlaylistType.OWNED) {
|
||||||
if (isOwner) {
|
RetrofitInstance.authApi.getPlaylistNextPage(
|
||||||
RetrofitInstance.authApi.getPlaylistNextPage(
|
playlistId!!,
|
||||||
playlistId!!,
|
nextPage!!
|
||||||
nextPage!!
|
)
|
||||||
)
|
} else {
|
||||||
} else {
|
RetrofitInstance.api.getPlaylistNextPage(
|
||||||
RetrofitInstance.api.getPlaylistNextPage(
|
playlistId!!,
|
||||||
playlistId!!,
|
nextPage!!
|
||||||
nextPage!!
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
} catch (e: IOException) {
|
|
||||||
println(e)
|
|
||||||
Log.e(TAG(), "IOException, you might not have internet connection")
|
|
||||||
return@launchWhenCreated
|
|
||||||
} catch (e: HttpException) {
|
|
||||||
Log.e(TAG(), "HttpException, unexpected response," + e.response())
|
|
||||||
return@launchWhenCreated
|
|
||||||
}
|
}
|
||||||
nextPage = response.nextpage
|
} catch (e: Exception) {
|
||||||
playlistAdapter?.updateItems(response.relatedStreams!!)
|
Log.e(TAG(), e.toString())
|
||||||
isLoading = false
|
return@launchWhenCreated
|
||||||
}
|
}
|
||||||
|
nextPage = response.nextpage
|
||||||
|
playlistAdapter?.updateItems(response.relatedStreams!!)
|
||||||
|
isLoading = false
|
||||||
}
|
}
|
||||||
run()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import com.github.libretube.R
|
|||||||
import com.github.libretube.api.RetrofitInstance
|
import com.github.libretube.api.RetrofitInstance
|
||||||
import com.github.libretube.api.obj.PlaylistId
|
import com.github.libretube.api.obj.PlaylistId
|
||||||
import com.github.libretube.databinding.DialogTextPreferenceBinding
|
import com.github.libretube.databinding.DialogTextPreferenceBinding
|
||||||
|
import com.github.libretube.enums.PlaylistType
|
||||||
import com.github.libretube.enums.ShareObjectType
|
import com.github.libretube.enums.ShareObjectType
|
||||||
import com.github.libretube.extensions.toID
|
import com.github.libretube.extensions.toID
|
||||||
import com.github.libretube.extensions.toastFromMainThread
|
import com.github.libretube.extensions.toastFromMainThread
|
||||||
@ -25,8 +26,8 @@ import java.io.IOException
|
|||||||
|
|
||||||
class PlaylistOptionsBottomSheet(
|
class PlaylistOptionsBottomSheet(
|
||||||
private val playlistId: String,
|
private val playlistId: String,
|
||||||
private val playlistName: String,
|
playlistName: String,
|
||||||
private val isOwner: Boolean
|
private val playlistType: PlaylistType
|
||||||
) : BaseBottomSheet() {
|
) : BaseBottomSheet() {
|
||||||
private val shareData = ShareData(currentPlaylist = playlistName)
|
private val shareData = ShareData(currentPlaylist = playlistName)
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
@ -37,7 +38,7 @@ class PlaylistOptionsBottomSheet(
|
|||||||
context?.getString(R.string.share)!!
|
context?.getString(R.string.share)!!
|
||||||
)
|
)
|
||||||
|
|
||||||
if (isOwner) {
|
if (playlistType != PlaylistType.PUBLIC) {
|
||||||
optionsList = optionsList +
|
optionsList = optionsList +
|
||||||
context?.getString(R.string.renamePlaylist)!! +
|
context?.getString(R.string.renamePlaylist)!! +
|
||||||
context?.getString(R.string.deletePlaylist)!! -
|
context?.getString(R.string.deletePlaylist)!! -
|
||||||
@ -50,7 +51,7 @@ class PlaylistOptionsBottomSheet(
|
|||||||
context?.getString(R.string.playOnBackground) -> {
|
context?.getString(R.string.playOnBackground) -> {
|
||||||
runBlocking {
|
runBlocking {
|
||||||
val playlist =
|
val playlist =
|
||||||
if (isOwner) {
|
if (playlistType == PlaylistType.OWNED) {
|
||||||
RetrofitInstance.authApi.getPlaylist(playlistId)
|
RetrofitInstance.authApi.getPlaylist(playlistId)
|
||||||
} else {
|
} else {
|
||||||
RetrofitInstance.api.getPlaylist(playlistId)
|
RetrofitInstance.api.getPlaylist(playlistId)
|
||||||
@ -82,7 +83,7 @@ class PlaylistOptionsBottomSheet(
|
|||||||
shareDialog.show(parentFragmentManager, ShareDialog::class.java.name)
|
shareDialog.show(parentFragmentManager, ShareDialog::class.java.name)
|
||||||
}
|
}
|
||||||
context?.getString(R.string.deletePlaylist) -> {
|
context?.getString(R.string.deletePlaylist) -> {
|
||||||
DeletePlaylistDialog(playlistId)
|
DeletePlaylistDialog(playlistId, playlistType)
|
||||||
.show(parentFragmentManager, null)
|
.show(parentFragmentManager, null)
|
||||||
}
|
}
|
||||||
context?.getString(R.string.renamePlaylist) -> {
|
context?.getString(R.string.renamePlaylist) -> {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.github.libretube.ui.sheets
|
package com.github.libretube.ui.sheets
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.widget.Toast
|
import androidx.core.os.bundleOf
|
||||||
import com.github.libretube.R
|
import com.github.libretube.R
|
||||||
import com.github.libretube.api.RetrofitInstance
|
import com.github.libretube.api.RetrofitInstance
|
||||||
import com.github.libretube.constants.IntentData
|
import com.github.libretube.constants.IntentData
|
||||||
@ -13,7 +13,6 @@ import com.github.libretube.ui.dialogs.DownloadDialog
|
|||||||
import com.github.libretube.ui.dialogs.ShareDialog
|
import com.github.libretube.ui.dialogs.ShareDialog
|
||||||
import com.github.libretube.util.BackgroundHelper
|
import com.github.libretube.util.BackgroundHelper
|
||||||
import com.github.libretube.util.PlayingQueue
|
import com.github.libretube.util.PlayingQueue
|
||||||
import com.github.libretube.util.PreferenceHelper
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -37,14 +36,6 @@ class VideoOptionsBottomSheet(
|
|||||||
context?.getString(R.string.share)!!
|
context?.getString(R.string.share)!!
|
||||||
)
|
)
|
||||||
|
|
||||||
// remove the add to playlist option if not logged in
|
|
||||||
if (PreferenceHelper.getToken() == "") {
|
|
||||||
optionsList.remove(
|
|
||||||
context?.getString(R.string.addToPlaylist)
|
|
||||||
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether the player is running and add queue options
|
* Check whether the player is running and add queue options
|
||||||
*/
|
*/
|
||||||
@ -61,19 +52,12 @@ class VideoOptionsBottomSheet(
|
|||||||
}
|
}
|
||||||
// Add Video to Playlist Dialog
|
// Add Video to Playlist Dialog
|
||||||
context?.getString(R.string.addToPlaylist) -> {
|
context?.getString(R.string.addToPlaylist) -> {
|
||||||
val token = PreferenceHelper.getToken()
|
AddToPlaylistDialog().apply {
|
||||||
if (token != "") {
|
arguments = bundleOf(IntentData.videoId to videoId)
|
||||||
val newFragment = AddToPlaylistDialog()
|
}.show(
|
||||||
val bundle = Bundle()
|
parentFragmentManager,
|
||||||
bundle.putString(IntentData.videoId, videoId)
|
AddToPlaylistDialog::class.java.name
|
||||||
newFragment.arguments = bundle
|
)
|
||||||
newFragment.show(
|
|
||||||
parentFragmentManager,
|
|
||||||
AddToPlaylistDialog::class.java.name
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
Toast.makeText(context, R.string.login_first, Toast.LENGTH_SHORT).show()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
context?.getString(R.string.download) -> {
|
context?.getString(R.string.download) -> {
|
||||||
val downloadDialog = DownloadDialog(videoId)
|
val downloadDialog = DownloadDialog(videoId)
|
||||||
|
@ -9,6 +9,7 @@ import androidx.appcompat.app.AppCompatActivity
|
|||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import com.github.libretube.R
|
import com.github.libretube.R
|
||||||
import com.github.libretube.constants.IntentData
|
import com.github.libretube.constants.IntentData
|
||||||
|
import com.github.libretube.enums.PlaylistType
|
||||||
import com.github.libretube.extensions.toID
|
import com.github.libretube.extensions.toID
|
||||||
import com.github.libretube.ui.activities.MainActivity
|
import com.github.libretube.ui.activities.MainActivity
|
||||||
import com.github.libretube.ui.fragments.PlayerFragment
|
import com.github.libretube.ui.fragments.PlayerFragment
|
||||||
@ -59,14 +60,14 @@ object NavigationHelper {
|
|||||||
fun navigatePlaylist(
|
fun navigatePlaylist(
|
||||||
context: Context,
|
context: Context,
|
||||||
playlistId: String?,
|
playlistId: String?,
|
||||||
isOwner: Boolean
|
playlistType: PlaylistType
|
||||||
) {
|
) {
|
||||||
if (playlistId == null) return
|
if (playlistId == null) return
|
||||||
|
|
||||||
val activity = context as MainActivity
|
val activity = context as MainActivity
|
||||||
val bundle = Bundle()
|
val bundle = Bundle()
|
||||||
bundle.putString(IntentData.playlistId, playlistId)
|
bundle.putString(IntentData.playlistId, playlistId)
|
||||||
bundle.putBoolean("isOwner", isOwner)
|
bundle.putSerializable(IntentData.playlistType, playlistType)
|
||||||
activity.navController.navigate(R.id.playlistFragment, bundle)
|
activity.navController.navigate(R.id.playlistFragment, bundle)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,9 +7,10 @@
|
|||||||
tools:context=".ui.fragments.LibraryFragment">
|
tools:context=".ui.fragments.LibraryFragment">
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:id="@+id/loginOrRegister"
|
android:id="@+id/nothing_here"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/boogh"
|
android:id="@+id/boogh"
|
||||||
@ -17,7 +18,7 @@
|
|||||||
android:layout_height="100dp"
|
android:layout_height="100dp"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
android:src="@drawable/ic_login" />
|
android:src="@drawable/ic_list" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/text_like"
|
android:id="@+id/text_like"
|
||||||
@ -27,7 +28,7 @@
|
|||||||
android:layout_centerHorizontal="true"
|
android:layout_centerHorizontal="true"
|
||||||
android:layout_marginHorizontal="10dp"
|
android:layout_marginHorizontal="10dp"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="@string/please_login"
|
android:text="@string/emptyList"
|
||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
android:textStyle="bold" />
|
android:textStyle="bold" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user