mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-04-20 03:24:50 +00:00
Merge branch 'master' of gitlab.futo.org:videostreaming/grayjay
This commit is contained in:
commit
7c1d0a7f88
11 changed files with 92 additions and 18 deletions
|
@ -16,6 +16,7 @@ class AddSourceOptionsActivity : AppCompatActivity() {
|
|||
lateinit var _buttonBack: ImageButton;
|
||||
|
||||
lateinit var _buttonQR: BigButton;
|
||||
lateinit var _buttonBrowse: BigButton;
|
||||
lateinit var _buttonURL: BigButton;
|
||||
lateinit var _buttonPlugins: BigButton;
|
||||
|
||||
|
@ -56,6 +57,7 @@ class AddSourceOptionsActivity : AppCompatActivity() {
|
|||
_buttonBack = findViewById(R.id.button_back);
|
||||
|
||||
_buttonQR = findViewById(R.id.option_qr);
|
||||
_buttonBrowse = findViewById(R.id.option_browse);
|
||||
_buttonURL = findViewById(R.id.option_url);
|
||||
_buttonPlugins = findViewById(R.id.option_plugins);
|
||||
|
||||
|
@ -74,6 +76,9 @@ class AddSourceOptionsActivity : AppCompatActivity() {
|
|||
integrator.setCaptureActivity(QRCaptureActivity::class.java);
|
||||
_qrCodeResultLauncher.launch(integrator.createScanIntent())
|
||||
}
|
||||
_buttonBrowse.onClick.subscribe {
|
||||
startActivity(MainActivity.getTabIntent(this, "BROWSE_PLUGINS"));
|
||||
}
|
||||
|
||||
_buttonURL.onClick.subscribe {
|
||||
UIDialogs.toast(this, getString(R.string.not_implemented_yet));
|
||||
|
|
|
@ -535,6 +535,9 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
|
|||
navigate(_fragMainSources);
|
||||
}
|
||||
};
|
||||
"BROWSE_PLUGINS" -> {
|
||||
navigate(_fragBrowser, "https://plugins.grayjay.app");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,9 @@ package com.futo.platformplayer.api.media.platforms.js
|
|||
|
||||
import com.futo.platformplayer.R
|
||||
import com.futo.platformplayer.constructs.Event0
|
||||
import com.futo.platformplayer.logging.Logger
|
||||
import com.futo.platformplayer.states.AnnouncementType
|
||||
import com.futo.platformplayer.states.StateAnnouncement
|
||||
import com.futo.platformplayer.views.fields.DropdownFieldOptions
|
||||
import com.futo.platformplayer.views.fields.FieldForm
|
||||
import com.futo.platformplayer.views.fields.FormField
|
||||
|
@ -55,7 +58,16 @@ class SourcePluginDescriptor {
|
|||
onCaptchaChanged.emit();
|
||||
}
|
||||
fun getCaptchaData(): SourceCaptchaData? {
|
||||
return SourceCaptchaData.fromEncrypted(captchaEncrypted);
|
||||
try {
|
||||
return SourceCaptchaData.fromEncrypted(captchaEncrypted);
|
||||
}
|
||||
catch(ex: Throwable) {
|
||||
Logger.e("SourcePluginDescriptor", "Captcha decode failed, disabling auth.", ex);
|
||||
StateAnnouncement.instance.registerAnnouncement("CAP_BROKEN_" + config.id,
|
||||
"Captcha corrupted for plugin [${config.name}]",
|
||||
"Something went wrong in the stored captcha, you'll have to login again", AnnouncementType.SESSION);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
fun updateAuth(str: SourceAuth?) {
|
||||
|
@ -63,7 +75,16 @@ class SourcePluginDescriptor {
|
|||
onAuthChanged.emit();
|
||||
}
|
||||
fun getAuth(): SourceAuth? {
|
||||
return SourceAuth.fromEncrypted(authEncrypted);
|
||||
try {
|
||||
return SourceAuth.fromEncrypted(authEncrypted);
|
||||
}
|
||||
catch(ex: Throwable) {
|
||||
Logger.e("SourcePluginDescriptor", "Authentication decode failed, disabling auth.", ex);
|
||||
StateAnnouncement.instance.registerAnnouncement("AUTH_BROKEN_" + config.id,
|
||||
"Authentication corrupted for plugin [${config.name}]",
|
||||
"Something went wrong in the stored authentication, you'll have to login again", AnnouncementType.SESSION);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
|
|
|
@ -154,8 +154,14 @@ class ContentSearchResultsFragment : MainFragment() {
|
|||
};
|
||||
|
||||
onSearch.subscribe(this) {
|
||||
if(it.isHttpUrl())
|
||||
navigate<VideoDetailFragment>(it);
|
||||
if(it.isHttpUrl()) {
|
||||
if(StatePlatform.instance.hasEnabledPlaylistClient(it))
|
||||
navigate<PlaylistFragment>(it);
|
||||
else if(StatePlatform.instance.hasEnabledChannelClient(it))
|
||||
navigate<ChannelFragment>(it);
|
||||
else
|
||||
navigate<VideoDetailFragment>(it);
|
||||
}
|
||||
else
|
||||
setQuery(it, true);
|
||||
};
|
||||
|
|
|
@ -157,9 +157,12 @@ class HomeFragment : MainFragment() {
|
|||
val dp10 = 10.dp(resources);
|
||||
val dp30 = 30.dp(resources);
|
||||
|
||||
if(!StatePlatform.instance.getEnabledClients().isEmpty())
|
||||
val pluginsExist = StatePlatform.instance.getAvailableClients().isNotEmpty();
|
||||
if(StatePlatform.instance.getEnabledClients().isEmpty())
|
||||
//Initial setup
|
||||
return NoResultsView(context, "You have no Sources", "Enable or install some sources", R.drawable.ic_sources,
|
||||
return NoResultsView(context, "No enabled Sources", if(pluginsExist)
|
||||
"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(
|
||||
Pair("grayjay") { req ->
|
||||
|
@ -170,7 +173,10 @@ class HomeFragment : MainFragment() {
|
|||
};
|
||||
}
|
||||
)));
|
||||
}.withMargin(dp10, dp30).withBackground(R.drawable.background_big_primary))
|
||||
}.withMargin(dp10, dp30),
|
||||
if(pluginsExist) BigButton(context, "Sources", "Go to the sources tab", R.drawable.ic_creators) {
|
||||
fragment.navigate<SourcesFragment>();
|
||||
}.withMargin(dp10, dp30) else null).filterNotNull()
|
||||
);
|
||||
else
|
||||
return NoResultsView(context, "Nothing to see here", "The enabled sources do not have any results.", R.drawable.ic_help,
|
||||
|
|
|
@ -295,17 +295,24 @@ class SourceDetailFragment : MainFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
val isEmbedded = StatePlugins.instance.getEmbeddedSources(context).any { it.key == config.id };
|
||||
|
||||
val clientIfExists = if(config.id != StateDeveloper.DEV_ID)
|
||||
StatePlugins.instance.getPlugin(config.id);
|
||||
else null;
|
||||
groups.add(
|
||||
BigButtonGroup(c, context.getString(R.string.management),
|
||||
BigButton(c, context.getString(R.string.uninstall), context.getString(R.string.removes_the_plugin_from_the_app), R.drawable.ic_block) {
|
||||
if(!isEmbedded) BigButton(c, context.getString(R.string.uninstall), context.getString(R.string.removes_the_plugin_from_the_app), R.drawable.ic_block) {
|
||||
uninstallSource();
|
||||
}.withBackground(R.drawable.background_big_button_red).apply {
|
||||
this.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||
setMargins(0, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5f, resources.displayMetrics).toInt(), 0, 0);
|
||||
};
|
||||
} else BigButton(c, context.getString(R.string.uninstall), "Cannot uninstall embedded plugins", R.drawable.ic_block, {}).apply {
|
||||
this.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||
setMargins(0, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5f, resources.displayMetrics).toInt(), 0, 0);
|
||||
};
|
||||
this.alpha = 0.5f
|
||||
},
|
||||
if(clientIfExists?.captchaEncrypted != null)
|
||||
BigButton(c, context.getString(R.string.delete_captcha), context.getString(R.string.deletes_stored_captcha_answer_for_this_plugin), R.drawable.ic_block) {
|
||||
|
@ -325,7 +332,6 @@ class SourceDetailFragment : MainFragment() {
|
|||
_sourceButtons.addView(group);
|
||||
}
|
||||
|
||||
val isEmbedded = StatePlugins.instance.getEmbeddedSources(context).any { it.key == config.id };
|
||||
val advancedButtons = BigButtonGroup(c, "Advanced",
|
||||
BigButton(c, "Edit Code", "Modify the source of this plugin", R.drawable.ic_code) {
|
||||
|
||||
|
@ -333,9 +339,15 @@ class SourceDetailFragment : MainFragment() {
|
|||
this.alpha = 0.5f;
|
||||
},
|
||||
if(isEmbedded) BigButton(c, "Reinstall", "Modify the source of this plugin", R.drawable.ic_refresh) {
|
||||
StatePlugins.instance.updateEmbeddedPlugins(context, listOf(config.id), true);
|
||||
reloadSource(config.id);
|
||||
UIDialogs.toast(context, "Embedded plugin reinstalled, may require refresh");
|
||||
val embeddedConfig = StatePlugins.instance.getEmbeddedPluginConfigFromID(context, config.id);
|
||||
|
||||
UIDialogs.showDialog(context, R.drawable.ic_warning_yellow, "Are you sure you want to downgrade (${config.version}=>${embeddedConfig?.version})?",
|
||||
"This will revert the plugin back to the originally embedded version.\nVersion change: ${config.version}=>${embeddedConfig?.version}", null,
|
||||
0, UIDialogs.Action("Cancel", {}), UIDialogs.Action("Reinstall", {
|
||||
StatePlugins.instance.updateEmbeddedPlugins(context, listOf(config.id), true);
|
||||
reloadSource(config.id);
|
||||
UIDialogs.toast(context, "Embedded plugin reinstalled, may require refresh");
|
||||
}, UIDialogs.ActionStyle.DANGEROUS));
|
||||
}.apply {
|
||||
this.layoutParams = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT).apply {
|
||||
setMargins(0, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5f, resources.displayMetrics).toInt(), 0, 0);
|
||||
|
|
|
@ -424,6 +424,7 @@ class VideoDetailFragment : MainFragment {
|
|||
changeOrientation(OrientationManager.Orientation.PORTRAIT);
|
||||
}
|
||||
isFullscreen = fullscreen;
|
||||
_view?.allowMotion = !fullscreen;
|
||||
}
|
||||
private fun changeOrientation(orientation: OrientationManager.Orientation) {
|
||||
Logger.i(TAG, "Orientation Change:" + orientation.name);
|
||||
|
|
|
@ -160,6 +160,13 @@ class StatePlugins {
|
|||
val configJson = StateAssets.readAsset(context, assetConfigPath) ?: return null;
|
||||
return SourcePluginConfig.fromJson(configJson, "");
|
||||
}
|
||||
fun getEmbeddedPluginConfigFromID(context: Context, pluginId: String): SourcePluginConfig? {
|
||||
val embedded = getEmbeddedSources(context);
|
||||
if(!embedded.containsKey(pluginId))
|
||||
return null;
|
||||
return getEmbeddedPluginConfig(context, embedded[pluginId]!!);
|
||||
}
|
||||
|
||||
fun installEmbeddedPlugin(context: Context, assetConfigPath: String, id: String? = null): Boolean {
|
||||
try {
|
||||
val configJson = StateAssets.readAsset(context, assetConfigPath) ?:
|
||||
|
|
|
@ -691,7 +691,7 @@ class FutoVideoPlayer : FutoVideoPlayerBase {
|
|||
|
||||
val viewWidth = Math.min(metrics.widthPixels, metrics.heightPixels); //TODO: Get parent width. was this.width
|
||||
val deviceHeight = Math.max(metrics.widthPixels, metrics.heightPixels);
|
||||
val maxHeight = deviceHeight * 0.6;
|
||||
val maxHeight = deviceHeight * 0.4;
|
||||
|
||||
val determinedHeight = if(w > h)
|
||||
((h * (viewWidth.toDouble() / w)).toInt())
|
||||
|
|
|
@ -55,6 +55,15 @@
|
|||
app:buttonText="@string/install_by_qr"
|
||||
app:buttonSubText="@string/install_a_plugin_by_scanning_a_qr_code"
|
||||
app:buttonIcon="@drawable/ic_qr" />
|
||||
<com.futo.platformplayer.views.buttons.BigButton
|
||||
android:id="@+id/option_browse"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="5dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
app:buttonText="Browse Online Sources"
|
||||
app:buttonSubText="Install a plugin by browsing official plugins"
|
||||
app:buttonIcon="@drawable/ic_explore" />
|
||||
<com.futo.platformplayer.views.buttons.BigButton
|
||||
android:id="@+id/option_url"
|
||||
android:layout_width="match_parent"
|
||||
|
|
|
@ -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-->
|
||||
|
|
Loading…
Add table
Reference in a new issue