mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2026-05-16 21:12:39 +02:00
Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6d9c1e17b5 | |||
| 507ad105c0 | |||
| 40a283017e | |||
| be14597670 | |||
| 837609abb9 | |||
| d64cd98b43 | |||
| 0081ff1483 | |||
| f78ca6c7ed | |||
| cfc7cbcaa4 | |||
| e533eb7778 | |||
| 7c1d0a7f88 | |||
| 01ef471708 | |||
| 2fd0a9a41d |
@@ -1,9 +1,6 @@
|
||||
[submodule "dep/polycentricandroid"]
|
||||
path = dep/polycentricandroid
|
||||
url = ../polycentricandroid.git
|
||||
[submodule "app/src/playstore/assets/sources/peertube"]
|
||||
path = app/src/playstore/assets/sources/peertube
|
||||
url = ../plugins/peertube.git
|
||||
[submodule "app/src/stable/assets/sources/kick"]
|
||||
path = app/src/stable/assets/sources/kick
|
||||
url = ../plugins/kick.git
|
||||
|
||||
+10
-10
@@ -151,7 +151,7 @@ dependencies {
|
||||
//Core
|
||||
implementation 'androidx.core:core-ktx:1.12.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||
implementation 'com.google.android.material:material:1.10.0'
|
||||
implementation 'com.google.android.material:material:1.11.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
|
||||
//Images
|
||||
@@ -172,15 +172,15 @@ dependencies {
|
||||
implementation("com.caoccao.javet:javet-android:3.0.2")
|
||||
|
||||
//Exoplayer
|
||||
implementation 'androidx.media3:media3-exoplayer:1.2.0'
|
||||
implementation 'androidx.media3:media3-exoplayer-dash:1.2.0'
|
||||
implementation 'androidx.media3:media3-ui:1.2.0'
|
||||
implementation 'androidx.media3:media3-exoplayer-hls:1.2.0'
|
||||
implementation 'androidx.media3:media3-exoplayer-rtsp:1.2.0'
|
||||
implementation 'androidx.media3:media3-exoplayer-smoothstreaming:1.2.0'
|
||||
implementation 'androidx.media3:media3-transformer:1.2.0'
|
||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.7.5'
|
||||
implementation 'androidx.navigation:navigation-ui-ktx:2.7.5'
|
||||
implementation 'androidx.media3:media3-exoplayer:1.2.1'
|
||||
implementation 'androidx.media3:media3-exoplayer-dash:1.2.1'
|
||||
implementation 'androidx.media3:media3-ui:1.2.1'
|
||||
implementation 'androidx.media3:media3-exoplayer-hls:1.2.1'
|
||||
implementation 'androidx.media3:media3-exoplayer-rtsp:1.2.1'
|
||||
implementation 'androidx.media3:media3-exoplayer-smoothstreaming:1.2.1'
|
||||
implementation 'androidx.media3:media3-transformer:1.2.1'
|
||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.7.6'
|
||||
implementation 'androidx.navigation:navigation-ui-ktx:2.7.6'
|
||||
implementation 'androidx.media:media:1.7.0'
|
||||
|
||||
//Other
|
||||
|
||||
@@ -686,7 +686,7 @@ class UISlideOverlays {
|
||||
}
|
||||
|
||||
|
||||
fun showAddToOverlay(video: IPlatformVideo, container: ViewGroup): SlideUpMenuOverlay {
|
||||
fun showAddToOverlay(video: IPlatformVideo, container: ViewGroup, slideUpMenuOverlayUpdated: (SlideUpMenuOverlay) -> Unit): SlideUpMenuOverlay {
|
||||
|
||||
val items = arrayListOf<View>();
|
||||
|
||||
@@ -718,10 +718,10 @@ class UISlideOverlays {
|
||||
|
||||
val playlistItems = arrayListOf<SlideUpMenuItem>();
|
||||
playlistItems.add(SlideUpMenuItem(container.context, R.drawable.ic_playlist_add, container.context.getString(R.string.new_playlist), container.context.getString(R.string.add_to_new_playlist), "add_to_new_playlist", {
|
||||
showCreatePlaylistOverlay(container) {
|
||||
slideUpMenuOverlayUpdated(showCreatePlaylistOverlay(container) {
|
||||
val playlist = Playlist(it, arrayListOf(SerializedPlatformVideo.fromVideo(video)));
|
||||
StatePlaylists.instance.createOrUpdatePlaylist(playlist);
|
||||
};
|
||||
});
|
||||
}, false))
|
||||
|
||||
for (playlist in allPlaylists) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import android.widget.ScrollView
|
||||
import android.widget.TextView
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.futo.platformplayer.R
|
||||
import com.futo.platformplayer.UIDialogs
|
||||
@@ -37,8 +38,10 @@ class AddSourceActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var _sourceHeader: SourceHeaderView;
|
||||
|
||||
|
||||
private lateinit var _sourcePermissions: LinearLayout;
|
||||
private lateinit var _sourceWarnings: LinearLayout;
|
||||
private lateinit var _sourceWarningsContainer: LinearLayout;
|
||||
|
||||
private lateinit var _container: ScrollView;
|
||||
private lateinit var _loader: ImageView;
|
||||
@@ -79,6 +82,7 @@ class AddSourceActivity : AppCompatActivity() {
|
||||
|
||||
_sourcePermissions = findViewById(R.id.source_permissions);
|
||||
_sourceWarnings = findViewById(R.id.source_warnings);
|
||||
_sourceWarningsContainer = findViewById(R.id.container_source_warnings);
|
||||
|
||||
_container = findViewById(R.id.configContainer);
|
||||
_loader = findViewById(R.id.loader);
|
||||
@@ -203,21 +207,28 @@ class AddSourceActivity : AppCompatActivity() {
|
||||
|
||||
val pastelRed = ContextCompat.getColor(this, R.color.pastel_red);
|
||||
|
||||
for(warning in config.getWarnings(script))
|
||||
val warnings = config.getWarnings(script);
|
||||
for(warning in warnings)
|
||||
_sourceWarnings.addView(
|
||||
SourceInfoView(this,
|
||||
R.drawable.ic_security_pred,
|
||||
warning.first,
|
||||
warning.second)
|
||||
.withDescriptionColor(pastelRed));
|
||||
_sourceWarningsContainer.isVisible = warnings.isNotEmpty();
|
||||
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
fun install(config: SourcePluginConfig, script: String) {
|
||||
val isNew = !StatePlatform.instance.getAvailableClients().any { it.id == config.id };
|
||||
StatePlugins.instance.installPlugin(this, lifecycleScope, config, script) {
|
||||
if(it) {
|
||||
StatePlatform.instance.clearUpdateAvailable(config)
|
||||
if(isNew)
|
||||
lifecycleScope.launch {
|
||||
StatePlatform.instance.enableClient(listOf(config.id));
|
||||
}
|
||||
backToSources();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -536,7 +536,15 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
|
||||
}
|
||||
};
|
||||
"BROWSE_PLUGINS" -> {
|
||||
navigate(_fragBrowser, "https://plugins.grayjay.app");
|
||||
navigate(_fragBrowser, BrowserFragment.NavigateOptions("https://plugins.grayjay.app/phone.html", mapOf(
|
||||
Pair("grayjay") { req ->
|
||||
StateApp.instance.contextOrNull?.let {
|
||||
if(it is MainActivity) {
|
||||
it.handleUrlAll(req.url.toString());
|
||||
}
|
||||
};
|
||||
}
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -90,6 +90,9 @@ class SourcePluginDescriptor {
|
||||
@Serializable
|
||||
class AppPluginSettings {
|
||||
|
||||
@FormField(R.string.check_for_updates_setting, FieldForm.TOGGLE, R.string.check_for_updates_setting_description, 1)
|
||||
var checkForUpdates: Boolean = true;
|
||||
|
||||
@FormField(R.string.visibility, "group", R.string.enable_where_this_plugins_content_are_visible, 2)
|
||||
var tabEnabled = TabEnabled();
|
||||
@Serializable
|
||||
|
||||
+1
-1
@@ -164,7 +164,7 @@ class HomeFragment : MainFragment() {
|
||||
"Enable or install some Sources"
|
||||
else "This Grayjay version comes without any sources, install sources externally or using the button below.", R.drawable.ic_sources,
|
||||
listOf(BigButton(context, "Browse Online Sources", "View official sources online", R.drawable.ic_explore) {
|
||||
fragment.navigate<BrowserFragment>(BrowserFragment.NavigateOptions("https://plugins.grayjay.app/", mapOf(
|
||||
fragment.navigate<BrowserFragment>(BrowserFragment.NavigateOptions("https://plugins.grayjay.app/phone.html", mapOf(
|
||||
Pair("grayjay") { req ->
|
||||
StateApp.instance.contextOrNull?.let {
|
||||
if(it is MainActivity) {
|
||||
|
||||
+2
-2
@@ -315,7 +315,7 @@ class PostDetailFragment : MainFragment {
|
||||
_rating.visibility = View.GONE;
|
||||
|
||||
val ref = Models.referenceFromBuffer((_post?.url ?: _postOverview?.url)?.toByteArray() ?: return)
|
||||
val extraBytesRef = (_post?.id?.value ?: _postOverview?.id?.value)?.toByteArray()
|
||||
val extraBytesRef = (_post?.id?.value ?: _postOverview?.id?.value)?.let { if (it.isNotEmpty()) it.toByteArray() else null }
|
||||
val version = _version;
|
||||
|
||||
_rating.onLikeDislikeUpdated.remove(this);
|
||||
@@ -663,7 +663,7 @@ class PostDetailFragment : MainFragment {
|
||||
Logger.i(TAG, "fetchPolycentricComments")
|
||||
val post = _post;
|
||||
val ref = (_post?.url ?: _postOverview?.url)?.toByteArray()?.let { Models.referenceFromBuffer(it) }
|
||||
val extraBytesRef = (_post?.id?.value ?: _postOverview?.id?.value)?.toByteArray()
|
||||
val extraBytesRef = (_post?.id?.value ?: _postOverview?.id?.value)?.let { if (it.isNotEmpty()) it.toByteArray() else null }
|
||||
|
||||
if (ref == null) {
|
||||
Logger.w(TAG, "Failed to fetch polycentric comments because url was not set null")
|
||||
|
||||
+10
-7
@@ -8,6 +8,7 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.LinearLayout
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
@@ -25,6 +26,7 @@ import com.futo.platformplayer.views.adapters.DisabledSourceView
|
||||
import com.futo.platformplayer.views.adapters.EnabledSourceAdapter
|
||||
import com.futo.platformplayer.views.adapters.EnabledSourceViewHolder
|
||||
import com.futo.platformplayer.views.adapters.ItemMoveCallback
|
||||
import com.futo.platformplayer.views.buttons.BigButton
|
||||
import com.futo.platformplayer.views.sources.SourceUnderConstructionView
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import java.util.Collections
|
||||
@@ -86,6 +88,14 @@ class SourcesFragment : MainFragment() {
|
||||
_containerDisabledViews = findViewById(R.id.container_disabled_views);
|
||||
_containerConstruction = findViewById(R.id.container_construction);
|
||||
|
||||
if(StatePlatform.instance.getAvailableClients().isEmpty()) {
|
||||
findViewById<LinearLayout>(R.id.no_sources).isVisible = true;
|
||||
findViewById<LinearLayout>(R.id.plugin_disclaimer).isVisible = false;
|
||||
}
|
||||
findViewById<BigButton>(R.id.button_add_sources).onClick.subscribe {
|
||||
fragment.startActivity(Intent(context, AddSourceOptionsActivity::class.java));
|
||||
};
|
||||
|
||||
for(inConstructSource in StatePlugins.instance.getSourcesUnderConstruction(context))
|
||||
_containerConstruction.addView(SourceUnderConstructionView(context, inConstructSource.key, inConstructSource.value));
|
||||
|
||||
@@ -111,8 +121,6 @@ class SourcesFragment : MainFragment() {
|
||||
|
||||
adapterSourcesEnabled.notifyItemMoved(fromPosition, toPosition);
|
||||
onEnabledChanged(enabledSources);
|
||||
if(toPosition == 0)
|
||||
onPrimaryChanged(enabledSources.first());
|
||||
|
||||
StatePlatform.instance.setPlatformOrder(enabledSources.map { it.name });
|
||||
};
|
||||
@@ -133,8 +141,6 @@ class SourcesFragment : MainFragment() {
|
||||
|
||||
updateContainerVisibility();
|
||||
onEnabledChanged(enabledSources);
|
||||
if(index == 0)
|
||||
onPrimaryChanged(enabledSources.first());
|
||||
|
||||
if(enabledSources.size <= 1)
|
||||
setCanRemove(false);
|
||||
@@ -221,9 +227,6 @@ class SourcesFragment : MainFragment() {
|
||||
_adapterSourcesEnabled.canRemove = canRemove;
|
||||
}
|
||||
|
||||
private fun onPrimaryChanged(client: IPlatformClient) {
|
||||
StatePlatform.instance.selectPrimaryClient(client.id);
|
||||
}
|
||||
private fun onEnabledChanged(clients: List<IPlatformClient>) {
|
||||
runBlocking {
|
||||
StatePlatform.instance.selectClients(*clients.map { it.id }.toTypedArray());
|
||||
|
||||
+7
-5
@@ -761,7 +761,9 @@ class VideoDetailView : ConstraintLayout {
|
||||
fun updateMoreButtons() {
|
||||
val buttons = listOf(RoundButton(context, R.drawable.ic_add, context.getString(R.string.add), TAG_ADD) {
|
||||
(video ?: _searchVideo)?.let {
|
||||
_slideUpOverlay = UISlideOverlays.showAddToOverlay(it, _overlayContainer);
|
||||
_slideUpOverlay = UISlideOverlays.showAddToOverlay(it, _overlayContainer) {
|
||||
_slideUpOverlay = it
|
||||
};
|
||||
}
|
||||
},
|
||||
if(video?.isLive ?: false)
|
||||
@@ -1228,7 +1230,7 @@ class VideoDetailView : ConstraintLayout {
|
||||
}
|
||||
|
||||
val ref = Models.referenceFromBuffer(video.url.toByteArray())
|
||||
val extraBytesRef = video.id.value?.toByteArray()
|
||||
val extraBytesRef = video.id.value?.let { if (it.isNotEmpty()) it.toByteArray() else null }
|
||||
_addCommentView.setContext(video.url, ref)
|
||||
_player.setMetadata(video.name, video.author.name);
|
||||
|
||||
@@ -1978,14 +1980,14 @@ class VideoDetailView : ConstraintLayout {
|
||||
Logger.i(TAG, "fetchPolycentricComments")
|
||||
val video = video;
|
||||
val idValue = video?.id?.value
|
||||
if (idValue == null) {
|
||||
Logger.w(TAG, "Failed to fetch polycentric comments because id was null")
|
||||
if (video?.url?.isEmpty() != false) {
|
||||
Logger.w(TAG, "Failed to fetch polycentric comments because url was null")
|
||||
_commentsList.clear()
|
||||
return
|
||||
}
|
||||
|
||||
val ref = Models.referenceFromBuffer(video.url.toByteArray())
|
||||
val extraBytesRef = video.id.value?.toByteArray()
|
||||
val extraBytesRef = idValue?.let { if (it.isNotEmpty()) it.toByteArray() else null }
|
||||
_commentsList.load(false) { StatePolycentric.instance.getCommentPager(video.url, ref, listOfNotNull(extraBytesRef)); };
|
||||
}
|
||||
private fun fetchVideo() {
|
||||
|
||||
@@ -12,7 +12,6 @@ import kotlinx.coroutines.withContext
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.Json
|
||||
import java.time.OffsetDateTime
|
||||
import java.util.Random
|
||||
import java.util.UUID
|
||||
|
||||
class StateAnnouncement {
|
||||
@@ -252,41 +251,6 @@ class StateAnnouncement {
|
||||
|
||||
}
|
||||
|
||||
fun registerDidYouKnow() {
|
||||
val random = Random();
|
||||
val message: String? = when (random.nextInt(4 * 18 + 1)) {
|
||||
0 -> "You can login to different platforms and unify your content experience. Check it out in the source settings!"
|
||||
1 -> "Importing your playlists and subscriptions from other platforms to Grayjay is quick and easy. Check it out in the source settings!"
|
||||
2 -> "Want to cast to a big screen? Try out FCast (https://fcast.org/)."
|
||||
3 -> "Explore Grayjay's gesture controls. When in full-screen swipe on the left to change brightness, swipe on the right to change volume."
|
||||
4 -> "Explore Grayjay's gesture controls. Swipe up in the center of a video to toggle full-screen."
|
||||
5 -> "Grayjay's multi-platform search lets you find content from various sources."
|
||||
6 -> "Grayjay's multi-platform search filters will unify filters across platforms. If your expected filters are not there, try toggling some platforms off in the search filters."
|
||||
7 -> "You can share playlists with friends on the playlist page and make full-backups in the settings page."
|
||||
8 -> "Discover Grayjay's offline playback feature. Save content for when you're on the go!"
|
||||
9 -> "Paid content from your favorite creators gets seamlessly integrated into your Grayjay feed. Login to a platform to seamlessly see content you paid for."
|
||||
10 -> "Explore Grayjay's plugin features! Login, import playlists, and tweak plugin settings for a tailored experience."
|
||||
11 -> "Directly engage with content by liking, disliking, or leaving comments on the Polycentric network."
|
||||
12 -> "With Grayjay's rotation lock, you can watch videos in your preferred orientation regardless of device settings. Check it out during playback!"
|
||||
13 -> "Grayjay supports background play. Listen to your favorite content even while multitasking!"
|
||||
14 -> "Use Grayjay's quality selection to adjust video resolution. Save data or watch in high definition – it's up to you."
|
||||
15 -> "Customize your Grayjay experience by changing playback speed. Watch content at your own pace."
|
||||
16 -> "Save time by adding videos to your 'Watch Later' list. Perfect for catching up on content during your free time."
|
||||
17 -> "On Grayjay, your playlists, subscriptions, and settings are stored offline for privacy and quick access."
|
||||
18 -> "Explore and engage with live content using Grayjay's live stream feature."
|
||||
else -> null
|
||||
};
|
||||
|
||||
if (message != null) {
|
||||
registerAnnouncement(
|
||||
"did-you-know?",
|
||||
"Did you know?",
|
||||
message,
|
||||
AnnouncementType.SESSION_RECURRING
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fun registerDefaultHandlerAnnouncement() {
|
||||
registerAnnouncement(
|
||||
"default-url-handler",
|
||||
|
||||
@@ -5,7 +5,6 @@ import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.graphics.Color
|
||||
import android.media.AudioManager
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.Network
|
||||
@@ -42,7 +41,6 @@ import com.futo.platformplayer.stores.v2.ManagedStore
|
||||
import com.futo.platformplayer.views.ToastView
|
||||
import kotlinx.coroutines.*
|
||||
import java.io.File
|
||||
import java.time.OffsetDateTime
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import kotlin.system.measureTimeMillis
|
||||
@@ -427,8 +425,6 @@ class StateApp {
|
||||
}
|
||||
}
|
||||
|
||||
StateAnnouncement.instance.registerAnnouncement("fa4647d3-36fa-4c8c-832d-85b00fc72dca", "Disclaimer", "This is an early alpha build of the application, expect bugs and unfinished features.", AnnouncementType.DELETABLE, OffsetDateTime.now())
|
||||
|
||||
if(SettingsDev.instance.developerMode && SettingsDev.instance.devServerSettings.devServerOnBoot)
|
||||
StateDeveloper.instance.runServer();
|
||||
|
||||
@@ -557,7 +553,6 @@ class StateApp {
|
||||
}
|
||||
|
||||
StateAnnouncement.instance.registerDefaultHandlerAnnouncement();
|
||||
StateAnnouncement.instance.registerDidYouKnow();
|
||||
Logger.i(TAG, "MainApp Started: Finished");
|
||||
|
||||
StatePlaylists.instance.toMigrateCheck();
|
||||
@@ -580,24 +575,9 @@ class StateApp {
|
||||
null,
|
||||
"Plugin updates available"
|
||||
));
|
||||
|
||||
StateAnnouncement.instance.registerAnnouncement(
|
||||
"plugin-update",
|
||||
"Plugin updates available",
|
||||
"There are ${updateAvailable.size} plugin updates available.",
|
||||
AnnouncementType.SESSION_RECURRING
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
UIDialogs.appToast("This is a test", false);
|
||||
UIDialogs.appToast("This is a test 2", false);
|
||||
UIDialogs.appToastError("This is a test 3 (Error)", false);
|
||||
UIDialogs.appToast(ToastView.Toast("This is a test 4, with title", false, Color.WHITE, "Test title"));
|
||||
UIDialogs.appToast("This is a test 5 Long text\nWith enters\nasdh asfh fds h rwe h fxh sdfh sdf h dsfh sdf hasdfhsdhg ads as", true);
|
||||
*/
|
||||
}
|
||||
|
||||
fun mainAppStartedWithExternalFiles(context: Context) {
|
||||
|
||||
@@ -94,11 +94,6 @@ class StatePlatform {
|
||||
private val _liveEventClientPool = PlatformMultiClientPool("LiveEvents", 1); //Used exclusively for live events
|
||||
|
||||
|
||||
private val _primaryClientPersistent = FragmentedStorage.get<StringStorage>("primaryClient");
|
||||
private var _primaryClientObj : IPlatformClient? = null;
|
||||
val primaryClient : IPlatformClient get() = _primaryClientObj ?: throw IllegalStateException("PlatformState not yet initialized");
|
||||
|
||||
|
||||
private val _icons : HashMap<String, ImageVariable> = HashMap();
|
||||
|
||||
val hasClients: Boolean get() = _availableClients.size > 0;
|
||||
@@ -207,20 +202,6 @@ class StatePlatform {
|
||||
.filter { id -> _availableClients.any { it.id == id } }
|
||||
.toTypedArray();
|
||||
}
|
||||
|
||||
|
||||
val primary = _primaryClientPersistent.value;
|
||||
if(primary.isEmpty() || primary == StateDeveloper.DEV_ID) {
|
||||
selectPrimaryClient(enabled.firstOrNull() ?: _availableClients.first().id);
|
||||
} else if(!_availableClients.any { it.id == primary }) {
|
||||
selectPrimaryClient(_availableClients.firstOrNull()?.id!!);
|
||||
} else {
|
||||
selectPrimaryClient(primary);
|
||||
}
|
||||
|
||||
if(!enabled.any { it == primaryClient.id }) {
|
||||
enabled = enabled.concat(primaryClient.id);
|
||||
}
|
||||
}
|
||||
selectClients(*enabled);
|
||||
};
|
||||
@@ -323,8 +304,6 @@ class StatePlatform {
|
||||
newClient.initialize();
|
||||
_enabledClients.add(newClient);
|
||||
}
|
||||
if (_primaryClientObj == client)
|
||||
_primaryClientObj = newClient;
|
||||
|
||||
_availableClients.removeIf { it.id == id };
|
||||
_availableClients.add(newClient);
|
||||
@@ -333,6 +312,11 @@ class StatePlatform {
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
suspend fun enableClient(ids: List<String>) {
|
||||
val currentClients = getEnabledClients().map { it.id };
|
||||
selectClients(*(currentClients + ids).distinct().toTypedArray());
|
||||
}
|
||||
/**
|
||||
* Selects the enabled clients, meaning all clients that data is actively requested from.
|
||||
* If a client is disabled, NO requests are made to said client
|
||||
@@ -365,17 +349,6 @@ class StatePlatform {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the primary client, meaning the first target for requests.
|
||||
* At the moment, since multi-client requests are not yet implemented, this is the goto client.
|
||||
*/
|
||||
fun selectPrimaryClient(id: String) {
|
||||
synchronized(_clientsLock) {
|
||||
_primaryClientObj = getClient(id);
|
||||
_primaryClientPersistent.setAndSave(id);
|
||||
}
|
||||
}
|
||||
|
||||
fun getHome(): IPager<IPlatformContent> {
|
||||
Logger.i(TAG, "Platform - getHome");
|
||||
var clientIdsOngoing = mutableListOf<String>();
|
||||
@@ -448,14 +421,12 @@ class StatePlatform {
|
||||
toAwait.map { PlaceholderPager(5, { PlatformContentPlaceholder(it.first.id) }) });
|
||||
}
|
||||
|
||||
fun getHomePrimary(): IPager<IPlatformContent> {
|
||||
return primaryClient.getHome();
|
||||
}
|
||||
|
||||
//Search
|
||||
fun searchSuggestions(query: String): Array<String> {
|
||||
Logger.i(TAG, "Platform - searchSuggestions");
|
||||
return primaryClient.searchSuggestions(query);
|
||||
//TODO: hasSearchSuggestions
|
||||
return getEnabledClients().firstOrNull()?.searchSuggestions(query) ?: arrayOf();
|
||||
}
|
||||
|
||||
fun search(query: String, type: String? = null, sort: String? = null, filters: Map<String, List<String>> = mapOf(), clientIds: List<String>? = null): IPager<IPlatformContent> {
|
||||
@@ -887,7 +858,6 @@ class StatePlatform {
|
||||
synchronized(_clientsLock) {
|
||||
val enabledExisting = _enabledClients.filter { it is DevJSClient };
|
||||
val isEnabled = !enabledExisting.isEmpty()
|
||||
val isPrimary = _primaryClientObj is DevJSClient;
|
||||
|
||||
for (enabled in enabledExisting) {
|
||||
enabled.disable();
|
||||
@@ -902,11 +872,7 @@ class StatePlatform {
|
||||
devId = newClient.devID;
|
||||
try {
|
||||
StateDeveloper.instance.initializeDev(devId!!);
|
||||
if (isPrimary) {
|
||||
_primaryClientObj = newClient;
|
||||
_enabledClients.add(0, newClient);
|
||||
newClient.initialize();
|
||||
} else if (isEnabled) {
|
||||
if (isEnabled) {
|
||||
_enabledClients.add(newClient);
|
||||
newClient.initialize();
|
||||
}
|
||||
@@ -945,7 +911,7 @@ class StatePlatform {
|
||||
suspend fun checkForUpdates(): List<SourcePluginConfig> = withContext(Dispatchers.IO) {
|
||||
var configs = mutableListOf<SourcePluginConfig>()
|
||||
val updatesAvailableFor = hashSetOf<String>()
|
||||
for (availableClient in getAvailableClients()) {
|
||||
for (availableClient in getAvailableClients().filter { it is JSClient && it.descriptor.appSettings.checkForUpdates }) {
|
||||
if (availableClient !is JSClient) {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -388,8 +388,8 @@ class GestureControlView : LinearLayout {
|
||||
return Math.max(width / w, height / h)
|
||||
}
|
||||
|
||||
private val _snapTranslationTolerance = 0.04f;
|
||||
private val _snapZoomTolerance = 0.04f;
|
||||
private val _snapTranslationTolerance = 0.1f;
|
||||
private val _snapZoomTolerance = 0.1f;
|
||||
|
||||
private fun willSnapFill(): Boolean {
|
||||
val surfaceView = _surfaceView
|
||||
|
||||
@@ -110,6 +110,7 @@
|
||||
|
||||
<!--Security Warnings-->
|
||||
<LinearLayout
|
||||
android:id="@+id/container_source_warnings"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
@@ -128,13 +128,17 @@
|
||||
tools:text="(7 playlists, 85 videos)"
|
||||
/>
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:id="@+id/downloads_playlist_list"
|
||||
<HorizontalScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<!--Fill Programmatically-->
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:orientation="horizontal"
|
||||
android:id="@+id/downloads_playlist_list"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
<!--Fill Programmatically-->
|
||||
</LinearLayout>
|
||||
</HorizontalScrollView>
|
||||
</LinearLayout>
|
||||
|
||||
<!--Videos-->
|
||||
|
||||
@@ -17,6 +17,40 @@
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="20dp"
|
||||
android:paddingEnd="20dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/no_sources"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="visible"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginBottom="10dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:srcCompat="@drawable/ic_error"
|
||||
app:tint="#FFF" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="#FFF"
|
||||
android:textSize="12dp"
|
||||
android:fontFamily="@font/inter_light"
|
||||
android:text="@string/no_sources_installed"
|
||||
android:layout_gravity="center"
|
||||
android:layout_marginStart="8dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/container_enabled"
|
||||
android:layout_width="match_parent"
|
||||
@@ -91,6 +125,7 @@
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/plugin_disclaimer"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginBottom="10dp">
|
||||
@@ -113,6 +148,15 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.futo.platformplayer.views.buttons.BigButton
|
||||
android:id="@+id/button_add_sources"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:buttonIcon="@drawable/ic_explore"
|
||||
app:buttonText="Add Sources"
|
||||
app:buttonSubText="Install new sources to see more content."
|
||||
/>
|
||||
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
|
||||
|
||||
@@ -214,6 +214,7 @@
|
||||
<string name="videos">Videos</string>
|
||||
<string name="clear_history">Clear history</string>
|
||||
<string name="nothing_to_import">Nothing to import</string>
|
||||
<string name="no_sources_installed">You have no sources installed, please add sources to use the app as intended.</string>
|
||||
<string name="enabling_lots_of_sources_can_reduce_the_loading_speed_of_your_application">Enabling lots of sources can reduce the loading speed of your application.</string>
|
||||
<string name="support">Support</string>
|
||||
<string name="membership">Membership</string>
|
||||
@@ -484,6 +485,8 @@
|
||||
<string name="various_tests_against_a_custom_source">Various tests against a custom source</string>
|
||||
<string name="writes_to_disk_till_no_space_is_left">Writes to disk till no space is left</string>
|
||||
<string name="visibility">Visibility</string>
|
||||
<string name="check_for_updates_setting">Check for updates</string>
|
||||
<string name="check_for_updates_setting_description">If a plugin should be checked for updates on startup</string>
|
||||
<string name="ratelimit">Rate-limit</string>
|
||||
<string name="ratelimit_description">Settings related to rate-limiting this plugin\'s behavior</string>
|
||||
<string name="ratelimit_sub_setting">Rate-limit Subscriptions</string>
|
||||
|
||||
Submodule app/src/playstore/assets/sources/peertube deleted from cfabdc97ab
@@ -1,7 +1,5 @@
|
||||
{
|
||||
"SOURCES_EMBEDDED": {
|
||||
"1c291164-294c-4c2d-800d-7bc6d31d0019": "sources/peertube/PeerTubeConfig.json"
|
||||
},
|
||||
"SOURCES_EMBEDDED_DEFAULT": ["1c291164-294c-4c2d-800d-7bc6d31d0019"],
|
||||
"SOURCES_EMBEDDED": {},
|
||||
"SOURCES_EMBEDDED_DEFAULT": [],
|
||||
"SOURCES_UNDER_CONSTRUCTION": {}
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Array of directories to look in
|
||||
dirs=("app/src/unstable/assets/sources" "app/src/stable/assets/sources" "app/src/playstore/assets/sources")
|
||||
dirs=("app/src/unstable/assets/sources" "app/src/stable/assets/sources")
|
||||
|
||||
# Loop through each directory
|
||||
for dir in "${dirs[@]}"; do
|
||||
|
||||
Reference in New Issue
Block a user