mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2026-05-16 04:52:39 +02:00
Deal with older Android versions
This commit is contained in:
+8
-2
@@ -8,6 +8,7 @@ import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
@@ -15,6 +16,7 @@ import android.view.ViewGroup
|
||||
import android.widget.*
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.animation.doOnEnd
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
@@ -109,6 +111,8 @@ class MenuBottomBarFragment : MainActivityFragment() {
|
||||
_toggleAirplaneMode = findViewById(R.id.container_toggle_airplane);
|
||||
_togglePrivacy = findViewById(R.id.container_toggle_privacy);
|
||||
|
||||
_toggleAirplaneMode.isVisible = false //TODO: Remove when airplane mode implemented
|
||||
|
||||
StateApp.instance.airplaneModeChanged.subscribe {
|
||||
if(!StateApp.instance.airplaneMode)
|
||||
_toggleAirplaneMode.setBackgroundResource(R.drawable.background_menu_toggle)
|
||||
@@ -575,7 +579,9 @@ class MenuBottomBarFragment : MainActivityFragment() {
|
||||
}
|
||||
}),
|
||||
ButtonDefinition(1, R.drawable.ic_subscriptions, R.drawable.ic_subscriptions_filled, R.string.subscriptions, canToggle = true, { it.currentMain is SubscriptionsFeedFragment }, { it.navigate<SubscriptionsFeedFragment>(withHistory = false) }),
|
||||
ButtonDefinition(12, R.drawable.ic_library, R.drawable.ic_library, R.string.library, canToggle = false, { it.currentMain is LibraryFragment }, { it.navigate<LibraryFragment>(withHistory = false) }),
|
||||
//if(Build.VERSION.SDK_INT > Build.VERSION_CODES.P)
|
||||
ButtonDefinition(12, R.drawable.ic_library, R.drawable.ic_library, R.string.library, canToggle = false, { it.currentMain is LibraryFragment }, { it.navigate<LibraryFragment>(withHistory = false) })
|
||||
,//else null,
|
||||
ButtonDefinition(2, R.drawable.ic_creators, R.drawable.ic_creators_filled, R.string.creators, canToggle = false, { it.currentMain is CreatorsFragment }, { it.navigate<CreatorsFragment>(withHistory = false) }),
|
||||
ButtonDefinition(3, R.drawable.ic_sources, R.drawable.ic_sources_filled, R.string.sources, canToggle = false, { it.currentMain is SourcesFragment }, { it.navigate<SourcesFragment>(withHistory = false) }),
|
||||
ButtonDefinition(4, R.drawable.ic_playlist, R.drawable.ic_playlist_filled, R.string.playlists, canToggle = false, { it.currentMain is PlaylistsFragment }, { it.navigate<PlaylistsFragment>(withHistory = false) }),
|
||||
@@ -613,7 +619,7 @@ class MenuBottomBarFragment : MainActivityFragment() {
|
||||
//96 is reserved for privacy button
|
||||
//98 is reserved for buy button
|
||||
//99 is reserved for more button
|
||||
);
|
||||
).filterNotNull();
|
||||
}
|
||||
|
||||
data class ButtonDefinition(
|
||||
|
||||
+3
-1
@@ -86,6 +86,7 @@ class LibraryFilesFragment : MainFragment() {
|
||||
}
|
||||
fun loadTop() {
|
||||
var initialDirectories = listOf<FileEntry>();
|
||||
var path = "";
|
||||
if(root == null) {
|
||||
initialDirectories = StateLibrary.instance.getFileDirectories();
|
||||
if (initialDirectories.size == 0) {
|
||||
@@ -109,9 +110,10 @@ class LibraryFilesFragment : MainFragment() {
|
||||
it.isVisible = false;
|
||||
}
|
||||
initialDirectories = root?.getSubFiles() ?: listOf();
|
||||
path = root?.path ?: "";
|
||||
}
|
||||
navStack.clear();
|
||||
val entry = FileStack("", initialDirectories);
|
||||
val entry = FileStack(path, initialDirectories);
|
||||
navStack.add(entry);
|
||||
openDirectory(navStack.last());
|
||||
fragment.topBar?.let {
|
||||
|
||||
+114
-35
@@ -2,6 +2,7 @@ package com.futo.platformplayer.fragment.mainactivity.main
|
||||
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.provider.MediaStore
|
||||
import android.util.AttributeSet
|
||||
@@ -16,6 +17,7 @@ import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.futo.platformplayer.R
|
||||
import com.futo.platformplayer.UIDialogs
|
||||
@@ -34,6 +36,7 @@ import com.futo.platformplayer.views.AnyInsertedAdapterView
|
||||
import com.futo.platformplayer.views.AnyInsertedAdapterView.Companion.asAnyWithTop
|
||||
import com.futo.platformplayer.views.AnyInsertedAdapterView.Companion.asAnyWithViews
|
||||
import com.futo.platformplayer.views.LibrarySection
|
||||
import com.futo.platformplayer.views.NoResultsView
|
||||
import com.futo.platformplayer.views.adapters.AnyAdapter
|
||||
import com.futo.platformplayer.views.adapters.InsertedViewAdapter
|
||||
import com.futo.platformplayer.views.adapters.viewholders.AlbumTileViewHolder
|
||||
@@ -41,6 +44,9 @@ import com.futo.platformplayer.views.adapters.viewholders.ArtistTileViewHolder
|
||||
import com.futo.platformplayer.views.adapters.viewholders.FileViewHolder
|
||||
import com.futo.platformplayer.views.adapters.viewholders.LocalVideoTileViewHolder
|
||||
import com.futo.platformplayer.views.buttons.BigButton
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import okhttp3.Dispatcher
|
||||
|
||||
|
||||
class LibraryFragment : MainFragment() {
|
||||
@@ -146,11 +152,12 @@ class LibraryFragment : MainFragment() {
|
||||
var sectionAlbums: LibrarySection;
|
||||
var sectionVideos: LibrarySection;
|
||||
var sectionFiles: LibrarySection;
|
||||
var noContent: NoResultsView;
|
||||
//var buttonFiles: BigButton;
|
||||
|
||||
val recycler: RecyclerView;
|
||||
|
||||
val adapterFiles: AnyInsertedAdapterView<FileEntry, FileViewHolder>;
|
||||
var adapterFiles: AnyInsertedAdapterView<FileEntry, FileViewHolder>? = null;
|
||||
|
||||
//var metaInfo: TextView;
|
||||
|
||||
@@ -186,6 +193,9 @@ class LibraryFragment : MainFragment() {
|
||||
//buttonFiles = findViewById<BigButton>(R.id.button_files);
|
||||
//metaInfo = findViewById(R.id.meta_info);
|
||||
|
||||
noContent = NoResultsView(context, "No directories", "No directories have been added.\nAdd them using the (+) icon.", -1, listOf());
|
||||
noContent.isVisible = false;
|
||||
|
||||
this.allowMusic = allowMusic ?: false;
|
||||
this.allowVideo = allowVideo ?: false;
|
||||
|
||||
@@ -195,14 +205,6 @@ class LibraryFragment : MainFragment() {
|
||||
else
|
||||
fragment.requestPermissionMusic();
|
||||
});
|
||||
val adapterArtists = sectionArtists.getAnyAdapter<Artist, ArtistTileViewHolder>({
|
||||
it.onClick.subscribe {
|
||||
if(it != null)
|
||||
fragment.navigate<LibraryArtistFragment>(it);
|
||||
}
|
||||
});
|
||||
val artists = StateLibrary.instance.getArtists(ArtistOrdering.TrackCount);
|
||||
adapterArtists.setData(artists);
|
||||
|
||||
sectionAlbums.setSection("Albums", {
|
||||
if(this.allowMusic)
|
||||
@@ -210,14 +212,6 @@ class LibraryFragment : MainFragment() {
|
||||
else
|
||||
fragment.requestPermissionMusic();
|
||||
});
|
||||
val adapterAlbums = sectionAlbums.getAnyAdapter<Album, AlbumTileViewHolder>({
|
||||
it.onClick.subscribe {
|
||||
if(it != null)
|
||||
fragment.navigate<LibraryAlbumFragment>(it);
|
||||
}
|
||||
});
|
||||
val albums = StateLibrary.instance.getAlbums();
|
||||
adapterAlbums.setData(albums);
|
||||
|
||||
|
||||
sectionVideos.setSection("Videos", {
|
||||
@@ -226,21 +220,112 @@ class LibraryFragment : MainFragment() {
|
||||
else
|
||||
fragment.requestPermissionVideo();
|
||||
});
|
||||
|
||||
reloadLibraryUI();
|
||||
|
||||
|
||||
/*
|
||||
buttonFiles.onClick.subscribe {
|
||||
fragment.navigate<LibraryFilesFragment>()
|
||||
} */
|
||||
//buttonFiles.setButtonEnabled(false);
|
||||
setMusicPermissions(allowMusic ?: false);
|
||||
setVideoPermissions(allowVideo ?: false);
|
||||
}
|
||||
|
||||
fun reloadFiles() {
|
||||
val files = StateLibrary.instance.getFileDirectories();
|
||||
adapterFiles?.setData(files);
|
||||
if(files.size == 0) {
|
||||
noContent.isVisible = true;
|
||||
}
|
||||
else
|
||||
noContent.isVisible = false;
|
||||
}
|
||||
|
||||
fun reloadLibraryUI() {
|
||||
|
||||
val adapterAlbums = sectionAlbums.getAnyAdapter<Album, AlbumTileViewHolder>({
|
||||
it.onClick.subscribe {
|
||||
if(it != null)
|
||||
fragment.navigate<LibraryAlbumFragment>(it);
|
||||
}
|
||||
});
|
||||
val adapterArtists = sectionArtists.getAnyAdapter<Artist, ArtistTileViewHolder>({
|
||||
it.onClick.subscribe {
|
||||
if(it != null)
|
||||
fragment.navigate<LibraryArtistFragment>(it);
|
||||
}
|
||||
});
|
||||
val adapterVideos = sectionVideos.getAnyAdapter<IPlatformVideo, LocalVideoTileViewHolder>({
|
||||
it.onClick.subscribe {
|
||||
if(it != null)
|
||||
fragment.navigate<VideoDetailFragment>(it);
|
||||
}
|
||||
});
|
||||
val videos = StateLibrary.instance.getRecentVideos(null, 20);
|
||||
adapterVideos.setData(videos);
|
||||
|
||||
if(this.allowMusic) {
|
||||
val artists = StateLibrary.instance.getArtists(ArtistOrdering.TrackCount);
|
||||
adapterArtists.setData(artists);
|
||||
if (artists.size == 0)
|
||||
sectionArtists.setEmpty(
|
||||
"No artists",
|
||||
"No artists were found on your device",
|
||||
-1
|
||||
);
|
||||
}
|
||||
else if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
|
||||
sectionAlbums.isVisible = false;
|
||||
}
|
||||
else {
|
||||
sectionArtists.setEmpty(
|
||||
"No Music Permissions",
|
||||
"You have not granted music access permissions to Grayjay",
|
||||
-1
|
||||
);
|
||||
}
|
||||
|
||||
if(this.allowMusic) {
|
||||
val albums = StateLibrary.instance.getAlbums();
|
||||
adapterAlbums.setData(albums);
|
||||
if (albums.size == 0)
|
||||
sectionAlbums.setEmpty("No albums", "No albums were found on your device", -1);
|
||||
}
|
||||
else if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
|
||||
sectionArtists.isVisible = false;
|
||||
}
|
||||
else {
|
||||
sectionAlbums.setEmpty(
|
||||
"No Music Permissions",
|
||||
"You have not granted music access permissions to Grayjay",
|
||||
-1
|
||||
);
|
||||
}
|
||||
|
||||
if(this.allowVideo) {
|
||||
val videos = StateLibrary.instance.getRecentVideos(null, 20);
|
||||
adapterVideos.setData(videos);
|
||||
if (videos.size == 0)
|
||||
sectionVideos.setEmpty("No videos", "No videos were found on your device", -1);
|
||||
}
|
||||
else if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) {
|
||||
sectionVideos.isVisible = false;
|
||||
}
|
||||
else {
|
||||
sectionVideos.setEmpty(
|
||||
"No Video Permissions",
|
||||
"You have not granted video access permissions to Grayjay",
|
||||
-1
|
||||
);
|
||||
}
|
||||
|
||||
adapterFiles = recycler.asAnyWithViews<FileEntry, FileViewHolder>(
|
||||
arrayListOf(
|
||||
sectionArtists,
|
||||
sectionAlbums,
|
||||
sectionVideos,
|
||||
sectionFiles
|
||||
sectionFiles,
|
||||
noContent
|
||||
),
|
||||
arrayListOf(View(context).apply { this.layoutParams = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 20.dp(resources)) }),
|
||||
RecyclerView.VERTICAL, false, {
|
||||
@@ -257,23 +342,8 @@ class LibraryFragment : MainFragment() {
|
||||
}
|
||||
);
|
||||
reloadFiles();
|
||||
|
||||
|
||||
/*
|
||||
buttonFiles.onClick.subscribe {
|
||||
fragment.navigate<LibraryFilesFragment>()
|
||||
} */
|
||||
//buttonFiles.setButtonEnabled(false);
|
||||
setMusicPermissions(allowMusic ?: false);
|
||||
setVideoPermissions(allowVideo ?: false);
|
||||
}
|
||||
|
||||
fun reloadFiles() {
|
||||
val files = StateLibrary.instance.getFileDirectories();
|
||||
adapterFiles.setData(files);
|
||||
}
|
||||
|
||||
|
||||
fun setMusicPermissions(access: Boolean) {
|
||||
allowMusic = access;
|
||||
sectionAlbums.setContentEmptyMessage(R.drawable.ic_library, "No mediastore permissions");
|
||||
@@ -283,6 +353,10 @@ class LibraryFragment : MainFragment() {
|
||||
// if(!allowMusic) "You did not give access to local music, so these options are disabled" else null,
|
||||
// if(!allowVideo) "You did not give access to local videos, so these options are disabled" else null
|
||||
//).filterNotNull().joinToString("\n");
|
||||
|
||||
fragment.lifecycleScope.launch(Dispatchers.Main) {
|
||||
reloadLibraryUI();
|
||||
}
|
||||
}
|
||||
fun setVideoPermissions(access: Boolean) {
|
||||
allowVideo = access;
|
||||
@@ -291,6 +365,11 @@ class LibraryFragment : MainFragment() {
|
||||
// if(!allowMusic) "You did not give access to local music, so these options are disabled" else null,
|
||||
// if(!allowVideo) "You did not give access to local videos, so these options are disabled" else null
|
||||
//).filterNotNull().joinToString("\n");
|
||||
// }
|
||||
|
||||
fragment.lifecycleScope.launch(Dispatchers.Main) {
|
||||
reloadLibraryUI();
|
||||
}
|
||||
}
|
||||
|
||||
fun onShown() {
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.content.ContentUris
|
||||
import android.content.Intent
|
||||
import android.database.Cursor
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.provider.MediaStore
|
||||
import android.provider.MediaStore.Audio.Artists
|
||||
import android.webkit.MimeTypeMap
|
||||
@@ -192,6 +193,8 @@ class StateLibrary {
|
||||
|
||||
private var _cacheBucketNames: List<Bucket>? = null;
|
||||
fun getVideoBucketNames(): List<Bucket> {
|
||||
if(Build.VERSION.SDK_INT <= Build.VERSION_CODES.P)
|
||||
return listOf();
|
||||
if(_cacheBucketNames != null)
|
||||
return _cacheBucketNames ?: listOf();
|
||||
try {
|
||||
@@ -236,7 +239,6 @@ class StateLibrary {
|
||||
val PROJECTION_VIDEO = arrayOf(
|
||||
MediaStore.Video.Media._ID,
|
||||
MediaStore.Video.Media.DISPLAY_NAME,
|
||||
MediaStore.Video.Media.AUTHOR,
|
||||
MediaStore.Video.Media.DATE_ADDED,
|
||||
MediaStore.Video.Media.MIME_TYPE,
|
||||
MediaStore.Video.Media.BUCKET_DISPLAY_NAME
|
||||
@@ -406,10 +408,10 @@ class StateLibrary {
|
||||
fun videoFromCursor(cursor: Cursor): IPlatformVideoDetails {
|
||||
val id = cursor.getString(0);
|
||||
val displayName = cursor.getString(1);
|
||||
val author = cursor.getString(2);
|
||||
val date = cursor.getLong(3);
|
||||
val contentType = cursor.getString(4);
|
||||
val category = cursor.getString(5);
|
||||
val author = null;//cursor.getString(2);
|
||||
val date = cursor.getLong(2);
|
||||
val contentType = cursor.getString(3);
|
||||
val category = cursor.getString(4);
|
||||
|
||||
val idLong = id.toLongOrNull();
|
||||
val contentUrl = if(idLong != null )
|
||||
|
||||
@@ -22,13 +22,14 @@ class LibrarySection: ConstraintLayout {
|
||||
val imageNavigate: ImageView;
|
||||
val recycler: RecyclerView;
|
||||
|
||||
val noContent: NoResultsView;
|
||||
|
||||
constructor(context: Context, attr: AttributeSet? = null) : super(context, attr) {
|
||||
inflate(context, R.layout.view_library_section, this);
|
||||
textName = findViewById(R.id.text_label)
|
||||
imageNavigate = findViewById(R.id.image_nav)
|
||||
recycler = findViewById(R.id.recycler_collection);
|
||||
|
||||
noContent = findViewById(R.id.container_no_content);
|
||||
}
|
||||
|
||||
fun setNavIcon(resId: Int) {
|
||||
@@ -46,4 +47,10 @@ class LibrarySection: ConstraintLayout {
|
||||
textName.text = title;
|
||||
imageNavigate.setOnClickListener { onOpen.invoke() };
|
||||
}
|
||||
|
||||
fun setEmpty(title: String, txt: String, iconId: Int) {
|
||||
noContent.isVisible = true;
|
||||
recycler.isVisible = false;
|
||||
noContent.setText(title, txt, iconId);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.futo.platformplayer.views
|
||||
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
@@ -15,6 +16,13 @@ class NoResultsView: ConstraintLayout {
|
||||
val icon: ImageView;
|
||||
val containerExtraViews: LinearLayout;
|
||||
|
||||
constructor(context: Context, attributes: AttributeSet? = null) : super(context, attributes){
|
||||
inflate(context, R.layout.view_no_results, this);
|
||||
textTitle = findViewById(R.id.text_title)
|
||||
textCentered = findViewById(R.id.text_centered);
|
||||
icon = findViewById(R.id.icon);
|
||||
containerExtraViews = findViewById(R.id.container_extra_views);
|
||||
}
|
||||
|
||||
constructor(context: Context, title: String, text: String, iconId: Int, extraViews: List<View>) : super(context) {
|
||||
inflate(context, R.layout.view_no_results, this);
|
||||
@@ -22,13 +30,21 @@ class NoResultsView: ConstraintLayout {
|
||||
textCentered = findViewById(R.id.text_centered);
|
||||
icon = findViewById(R.id.icon);
|
||||
containerExtraViews = findViewById(R.id.container_extra_views);
|
||||
|
||||
setText(title, text, iconId, extraViews);
|
||||
}
|
||||
|
||||
|
||||
fun setText(title: String, text: String, iconId: Int = -1, extraViews: List<View>? = null) {
|
||||
textTitle.text = title;
|
||||
textCentered.text = text;
|
||||
icon.setImageResource(iconId);
|
||||
if(iconId < 0)
|
||||
icon.visibility = GONE;
|
||||
else
|
||||
icon.setImageResource(iconId);
|
||||
|
||||
for(view in extraViews)
|
||||
containerExtraViews.addView(view);
|
||||
if(extraViews != null)
|
||||
for(view in extraViews)
|
||||
containerExtraViews.addView(view);
|
||||
}
|
||||
}
|
||||
@@ -75,7 +75,7 @@
|
||||
<ImageView
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:src="@drawable/ic_visibility_off" />
|
||||
android:src="@drawable/ic_disabled_visible" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -41,6 +41,16 @@
|
||||
android:layout_marginTop="10dp"
|
||||
android:orientation="horizontal" />
|
||||
|
||||
<com.futo.platformplayer.views.NoResultsView
|
||||
android:id="@+id/container_no_content"
|
||||
android:visibility="gone"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="20dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_label"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent" />
|
||||
|
||||
<!--
|
||||
<ImageButton
|
||||
android:id="@+id/button_play"
|
||||
|
||||
Reference in New Issue
Block a user