mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-04-20 11:35:46 +00:00
Language on all activities, Fix plugin initial state, Allow rotation prevention bypass, Settings warning support
This commit is contained in:
parent
439d339330
commit
5dcff29d8d
32 changed files with 210 additions and 69 deletions
|
@ -540,6 +540,8 @@
|
|||
<script>
|
||||
IS_TESTING = true;
|
||||
let lastScriptTag = null;
|
||||
let shouldDevLog = true;
|
||||
let shouldLoginCheck = true;
|
||||
new Vue({
|
||||
el: '#app',
|
||||
data: {
|
||||
|
@ -603,7 +605,7 @@
|
|||
};
|
||||
setInterval(()=>{
|
||||
try{
|
||||
if(!this.Plugin.currentPlugin)
|
||||
if(!this.Plugin.currentPlugin || !shouldDevLog)
|
||||
return;
|
||||
|
||||
getDevLogs(this.Integration.lastLogIndex, (newLogs)=> {
|
||||
|
@ -638,7 +640,8 @@
|
|||
}, 1000);
|
||||
setInterval(()=>{
|
||||
try{
|
||||
this.isTestLoggedIn();
|
||||
if(shouldLoginCheck)
|
||||
this.isTestLoggedIn();
|
||||
}catch(ex){}
|
||||
}, 2500);
|
||||
},
|
||||
|
|
|
@ -10,7 +10,8 @@ let Type = {
|
|||
Videos: "VIDEOS",
|
||||
Streams: "STREAMS",
|
||||
Mixed: "MIXED",
|
||||
Live: "LIVE"
|
||||
Live: "LIVE",
|
||||
Subscriptions: "SUBSCRIPTIONS"
|
||||
},
|
||||
Order: {
|
||||
Chronological: "CHRONOLOGICAL"
|
||||
|
|
|
@ -8,6 +8,7 @@ import android.webkit.CookieManager
|
|||
import androidx.lifecycle.lifecycleScope
|
||||
import com.futo.platformplayer.activities.*
|
||||
import com.futo.platformplayer.api.http.ManagedHttpClient
|
||||
import com.futo.platformplayer.cache.ChannelContentCache
|
||||
import com.futo.platformplayer.constructs.Event0
|
||||
import com.futo.platformplayer.fragment.mainactivity.bottombar.MenuBottomBarFragment
|
||||
import com.futo.platformplayer.logging.Logger
|
||||
|
@ -21,6 +22,7 @@ import com.futo.platformplayer.views.fields.DropdownFieldOptionsId
|
|||
import com.futo.platformplayer.views.fields.FormField
|
||||
import com.futo.platformplayer.views.fields.FieldForm
|
||||
import com.futo.platformplayer.views.fields.FormFieldButton
|
||||
import com.futo.platformplayer.views.fields.FormFieldWarning
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
@ -43,10 +45,7 @@ class Settings : FragmentedStorageFileJson() {
|
|||
@Transient
|
||||
val onTabsChanged = Event0();
|
||||
|
||||
@FormField(
|
||||
R.string.manage_polycentric_identity, FieldForm.BUTTON,
|
||||
R.string.manage_your_polycentric_identity, -5
|
||||
)
|
||||
@FormField(R.string.manage_polycentric_identity, FieldForm.BUTTON, R.string.manage_your_polycentric_identity, -5)
|
||||
@FormFieldButton(R.drawable.ic_person)
|
||||
fun managePolycentricIdentity() {
|
||||
SettingsActivity.getActivity()?.let {
|
||||
|
@ -58,10 +57,7 @@ class Settings : FragmentedStorageFileJson() {
|
|||
}
|
||||
}
|
||||
|
||||
@FormField(
|
||||
R.string.show_faq, FieldForm.BUTTON,
|
||||
R.string.get_answers_to_common_questions, -4
|
||||
)
|
||||
@FormField(R.string.show_faq, FieldForm.BUTTON, R.string.get_answers_to_common_questions, -4)
|
||||
@FormFieldButton(R.drawable.ic_quiz)
|
||||
fun openFAQ() {
|
||||
try {
|
||||
|
@ -71,10 +67,7 @@ class Settings : FragmentedStorageFileJson() {
|
|||
//Ignored
|
||||
}
|
||||
}
|
||||
@FormField(
|
||||
R.string.show_issues, FieldForm.BUTTON,
|
||||
R.string.a_list_of_user_reported_and_self_reported_issues, -3
|
||||
)
|
||||
@FormField(R.string.show_issues, FieldForm.BUTTON, R.string.a_list_of_user_reported_and_self_reported_issues, -3)
|
||||
@FormFieldButton(R.drawable.ic_data_alert)
|
||||
fun openIssues() {
|
||||
try {
|
||||
|
@ -106,10 +99,7 @@ class Settings : FragmentedStorageFileJson() {
|
|||
}
|
||||
}*/
|
||||
|
||||
@FormField(
|
||||
R.string.manage_tabs, FieldForm.BUTTON,
|
||||
R.string.change_tabs_visible_on_the_home_screen, -2
|
||||
)
|
||||
@FormField(R.string.manage_tabs, FieldForm.BUTTON, R.string.change_tabs_visible_on_the_home_screen, -2)
|
||||
@FormFieldButton(R.drawable.ic_tabs)
|
||||
fun manageTabs() {
|
||||
try {
|
||||
|
@ -263,6 +253,13 @@ class Settings : FragmentedStorageFileJson() {
|
|||
|
||||
@FormField(R.string.always_reload_from_cache, FieldForm.TOGGLE, R.string.always_reload_from_cache_description, 11)
|
||||
var alwaysReloadFromCache: Boolean = false;
|
||||
|
||||
@FormField(R.string.clear_channel_cache, FieldForm.BUTTON, R.string.clear_channel_cache_description, 12)
|
||||
fun clearChannelCache() {
|
||||
UIDialogs.toast(SettingsActivity.getActivity()!!, "Started clearing..");
|
||||
ChannelContentCache.instance.clear();
|
||||
UIDialogs.toast(SettingsActivity.getActivity()!!, "Finished clearing");
|
||||
}
|
||||
}
|
||||
|
||||
@FormField(R.string.player, "group", R.string.change_behavior_of_the_player, 4)
|
||||
|
@ -432,10 +429,7 @@ class Settings : FragmentedStorageFileJson() {
|
|||
@DropdownFieldOptionsId(R.array.log_levels)
|
||||
var logLevel: Int = 0;
|
||||
|
||||
@FormField(
|
||||
R.string.submit_logs, FieldForm.BUTTON,
|
||||
R.string.submit_logs_to_help_us_narrow_down_issues, 1
|
||||
)
|
||||
@FormField(R.string.submit_logs, FieldForm.BUTTON, R.string.submit_logs_to_help_us_narrow_down_issues, 1)
|
||||
fun submitLogs() {
|
||||
StateApp.instance.scopeOrNull?.launch(Dispatchers.IO) {
|
||||
try {
|
||||
|
@ -457,10 +451,7 @@ class Settings : FragmentedStorageFileJson() {
|
|||
var announcementSettings = AnnouncementSettings();
|
||||
@Serializable
|
||||
class AnnouncementSettings {
|
||||
@FormField(
|
||||
R.string.reset_announcements, FieldForm.BUTTON,
|
||||
R.string.reset_hidden_announcements, 1
|
||||
)
|
||||
@FormField(R.string.reset_announcements, FieldForm.BUTTON, R.string.reset_hidden_announcements, 1)
|
||||
fun resetAnnouncements() {
|
||||
StateAnnouncement.instance.resetAnnouncements();
|
||||
SettingsActivity.getActivity()?.let { UIDialogs.toast(it, it.getString(R.string.announcements_reset)); };
|
||||
|
@ -476,18 +467,12 @@ class Settings : FragmentedStorageFileJson() {
|
|||
@FormField(R.string.clear_cookies_on_logout, FieldForm.TOGGLE, R.string.clears_cookies_when_you_log_out, 0)
|
||||
var clearCookiesOnLogout: Boolean = true;
|
||||
|
||||
@FormField(
|
||||
R.string.clear_cookies, FieldForm.BUTTON,
|
||||
R.string.clears_in_app_browser_cookies, 1
|
||||
)
|
||||
@FormField(R.string.clear_cookies, FieldForm.BUTTON, R.string.clears_in_app_browser_cookies, 1)
|
||||
fun clearCookies() {
|
||||
val cookieManager: CookieManager = CookieManager.getInstance();
|
||||
cookieManager.removeAllCookies(null);
|
||||
}
|
||||
@FormField(
|
||||
R.string.reinstall_embedded_plugins, FieldForm.BUTTON,
|
||||
R.string.also_removes_any_data_related_plugin_like_login_or_settings, 1
|
||||
)
|
||||
@FormField(R.string.reinstall_embedded_plugins, FieldForm.BUTTON, R.string.also_removes_any_data_related_plugin_like_login_or_settings, 1)
|
||||
fun reinstallEmbedded() {
|
||||
StateApp.instance.scopeOrNull!!.launch(Dispatchers.IO) {
|
||||
try {
|
||||
|
@ -566,10 +551,7 @@ class Settings : FragmentedStorageFileJson() {
|
|||
return check == 0 && !BuildConfig.IS_PLAYSTORE_BUILD;
|
||||
}
|
||||
|
||||
@FormField(
|
||||
R.string.manual_check, FieldForm.BUTTON,
|
||||
R.string.manually_check_for_updates, 3
|
||||
)
|
||||
@FormField(R.string.manual_check, FieldForm.BUTTON, R.string.manually_check_for_updates, 3)
|
||||
fun manualCheck() {
|
||||
if (!BuildConfig.IS_PLAYSTORE_BUILD) {
|
||||
SettingsActivity.getActivity()?.let {
|
||||
|
@ -586,10 +568,7 @@ class Settings : FragmentedStorageFileJson() {
|
|||
}
|
||||
}
|
||||
|
||||
@FormField(
|
||||
R.string.view_changelog, FieldForm.BUTTON,
|
||||
R.string.review_the_current_and_past_changelogs, 4
|
||||
)
|
||||
@FormField(R.string.view_changelog, FieldForm.BUTTON, R.string.review_the_current_and_past_changelogs, 4)
|
||||
fun viewChangelog() {
|
||||
SettingsActivity.getActivity()?.let {
|
||||
UIDialogs.toast(it.getString(R.string.retrieving_changelog));
|
||||
|
@ -609,10 +588,7 @@ class Settings : FragmentedStorageFileJson() {
|
|||
};
|
||||
}
|
||||
|
||||
@FormField(
|
||||
R.string.remove_cached_version, FieldForm.BUTTON,
|
||||
R.string.remove_the_last_downloaded_version, 5
|
||||
)
|
||||
@FormField(R.string.remove_cached_version, FieldForm.BUTTON, R.string.remove_the_last_downloaded_version, 5)
|
||||
fun removeCachedVersion() {
|
||||
StateApp.withContext {
|
||||
val outputDirectory = File(it.filesDir, "autoupdate");
|
||||
|
@ -698,7 +674,16 @@ class Settings : FragmentedStorageFileJson() {
|
|||
}
|
||||
}
|
||||
|
||||
@FormField(R.string.info, FieldForm.GROUP, -1, 15)
|
||||
@FormField(R.string.other, FieldForm.GROUP, -1, 15)
|
||||
var other = Other();
|
||||
@Serializable
|
||||
class Other {
|
||||
@FormField(R.string.bypass_rotation_prevention, FieldForm.TOGGLE, R.string.bypass_rotation_prevention_description, 1)
|
||||
@FormFieldWarning(R.string.bypass_rotation_prevention_warning)
|
||||
var bypassRotationPrevention: Boolean = false;
|
||||
}
|
||||
|
||||
@FormField(R.string.info, FieldForm.GROUP, -1, 16)
|
||||
var info = Info();
|
||||
@Serializable
|
||||
class Info {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.futo.platformplayer.activities
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.drawable.Animatable
|
||||
import android.os.Bundle
|
||||
|
@ -45,6 +46,10 @@ class AddSourceActivity : AppCompatActivity() {
|
|||
private var _config: SourcePluginConfig? = null;
|
||||
private var _script: String? = null;
|
||||
|
||||
override fun attachBaseContext(newBase: Context?) {
|
||||
super.attachBaseContext(StateApp.instance.getLocaleContext(newBase))
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.futo.platformplayer.activities
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
|
@ -7,6 +8,7 @@ import android.widget.*
|
|||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.futo.platformplayer.*
|
||||
import com.futo.platformplayer.states.StateApp
|
||||
import com.futo.platformplayer.views.buttons.BigButton
|
||||
import com.google.zxing.integration.android.IntentIntegrator
|
||||
import com.journeyapps.barcodescanner.CaptureActivity
|
||||
|
@ -43,6 +45,10 @@ class AddSourceOptionsActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun attachBaseContext(newBase: Context?) {
|
||||
super.attachBaseContext(StateApp.instance.getLocaleContext(newBase))
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_add_source_options);
|
||||
|
|
|
@ -18,6 +18,7 @@ import com.futo.platformplayer.engine.IV8PluginConfig
|
|||
import com.futo.platformplayer.logging.Logger
|
||||
import com.futo.platformplayer.others.CaptchaWebViewClient
|
||||
import com.futo.platformplayer.others.LoginWebViewClient
|
||||
import com.futo.platformplayer.states.StateApp
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.decodeFromString
|
||||
|
@ -31,6 +32,10 @@ class CaptchaActivity : AppCompatActivity() {
|
|||
private lateinit var _webView: WebView;
|
||||
private lateinit var _buttonClose: Button;
|
||||
|
||||
override fun attachBaseContext(newBase: Context?) {
|
||||
super.attachBaseContext(StateApp.instance.getLocaleContext(newBase))
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_captcha);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.futo.platformplayer.activities
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
|
@ -11,6 +12,7 @@ import androidx.lifecycle.lifecycleScope
|
|||
import com.futo.platformplayer.*
|
||||
import com.futo.platformplayer.logging.LogLevel
|
||||
import com.futo.platformplayer.logging.Logging
|
||||
import com.futo.platformplayer.states.StateApp
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
@ -27,6 +29,10 @@ class ExceptionActivity : AppCompatActivity() {
|
|||
private var _file: File? = null;
|
||||
private var _submitted = false;
|
||||
|
||||
override fun attachBaseContext(newBase: Context?) {
|
||||
super.attachBaseContext(StateApp.instance.getLocaleContext(newBase))
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_exception);
|
||||
|
|
|
@ -17,6 +17,7 @@ import com.futo.platformplayer.api.media.platforms.js.SourcePluginAuthConfig
|
|||
import com.futo.platformplayer.api.media.platforms.js.SourcePluginConfig
|
||||
import com.futo.platformplayer.logging.Logger
|
||||
import com.futo.platformplayer.others.LoginWebViewClient
|
||||
import com.futo.platformplayer.states.StateApp
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.decodeFromString
|
||||
|
@ -28,6 +29,9 @@ class LoginActivity : AppCompatActivity() {
|
|||
private lateinit var _textUrl: TextView;
|
||||
private lateinit var _buttonClose: ImageButton;
|
||||
|
||||
override fun attachBaseContext(newBase: Context?) {
|
||||
super.attachBaseContext(StateApp.instance.getLocaleContext(newBase))
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
|
|
@ -327,6 +327,15 @@ class MainActivity : AppCompatActivity, IWithResultLauncher {
|
|||
fragCurrent.onOrientationChanged(it);
|
||||
if(_fragVideoDetail.state == VideoDetailFragment.State.MAXIMIZED)
|
||||
_fragVideoDetail.onOrientationChanged(it);
|
||||
else if(Settings.instance.other.bypassRotationPrevention)
|
||||
{
|
||||
requestedOrientation = when(orientation) {
|
||||
OrientationManager.Orientation.PORTRAIT -> ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
||||
OrientationManager.Orientation.LANDSCAPE -> ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
|
||||
OrientationManager.Orientation.REVERSED_PORTRAIT -> ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT
|
||||
OrientationManager.Orientation.REVERSED_LANDSCAPE -> ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE
|
||||
}
|
||||
}
|
||||
};
|
||||
_orientationManager.enable();
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.futo.platformplayer.activities
|
||||
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.widget.ImageButton
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
|
@ -10,6 +11,7 @@ import com.futo.platformplayer.R
|
|||
import com.futo.platformplayer.Settings
|
||||
import com.futo.platformplayer.fragment.mainactivity.bottombar.MenuBottomBarFragment
|
||||
import com.futo.platformplayer.setNavigationBarColorAndIcons
|
||||
import com.futo.platformplayer.states.StateApp
|
||||
import com.futo.platformplayer.views.AnyAdapterView
|
||||
import com.futo.platformplayer.views.AnyAdapterView.Companion.asAny
|
||||
import com.futo.platformplayer.views.adapters.ItemMoveCallback
|
||||
|
@ -23,6 +25,10 @@ class ManageTabsActivity : AppCompatActivity() {
|
|||
private lateinit var _recyclerTabs: RecyclerView;
|
||||
private lateinit var _touchHelper: ItemTouchHelper;
|
||||
|
||||
override fun attachBaseContext(newBase: Context?) {
|
||||
super.attachBaseContext(StateApp.instance.getLocaleContext(newBase))
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_manage_tabs);
|
||||
|
|
|
@ -16,6 +16,7 @@ import androidx.appcompat.app.AppCompatActivity
|
|||
import com.futo.platformplayer.R
|
||||
import com.futo.platformplayer.logging.Logger
|
||||
import com.futo.platformplayer.setNavigationBarColorAndIcons
|
||||
import com.futo.platformplayer.states.StateApp
|
||||
import com.futo.platformplayer.states.StatePolycentric
|
||||
import com.futo.platformplayer.views.buttons.BigButton
|
||||
import com.futo.polycentric.core.*
|
||||
|
@ -33,6 +34,10 @@ class PolycentricBackupActivity : AppCompatActivity() {
|
|||
private lateinit var _exportBundle: String;
|
||||
private lateinit var _textQR: TextView;
|
||||
|
||||
override fun attachBaseContext(newBase: Context?) {
|
||||
super.attachBaseContext(StateApp.instance.getLocaleContext(newBase))
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_polycentric_backup);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.futo.platformplayer.activities
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.widget.EditText
|
||||
|
@ -11,6 +12,7 @@ import com.futo.platformplayer.R
|
|||
import com.futo.platformplayer.UIDialogs
|
||||
import com.futo.platformplayer.logging.Logger
|
||||
import com.futo.platformplayer.setNavigationBarColorAndIcons
|
||||
import com.futo.platformplayer.states.StateApp
|
||||
import com.futo.platformplayer.states.StatePolycentric
|
||||
import com.futo.polycentric.core.ProcessHandle
|
||||
import com.futo.polycentric.core.Store
|
||||
|
@ -28,6 +30,10 @@ class PolycentricCreateProfileActivity : AppCompatActivity() {
|
|||
|
||||
private var _creating = false;
|
||||
|
||||
override fun attachBaseContext(newBase: Context?) {
|
||||
super.attachBaseContext(StateApp.instance.getLocaleContext(newBase))
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_polycentric_create_profile);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.futo.platformplayer.activities
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.drawable.Drawable
|
||||
|
@ -15,6 +16,7 @@ import com.futo.platformplayer.R
|
|||
import com.futo.platformplayer.dp
|
||||
import com.futo.platformplayer.selectBestImage
|
||||
import com.futo.platformplayer.setNavigationBarColorAndIcons
|
||||
import com.futo.platformplayer.states.StateApp
|
||||
import com.futo.platformplayer.states.StatePolycentric
|
||||
import com.futo.platformplayer.views.buttons.BigButton
|
||||
import com.futo.polycentric.core.Store
|
||||
|
@ -27,6 +29,10 @@ class PolycentricHomeActivity : AppCompatActivity() {
|
|||
private lateinit var _buttonImportProfile: BigButton;
|
||||
private lateinit var _layoutButtons: LinearLayout;
|
||||
|
||||
override fun attachBaseContext(newBase: Context?) {
|
||||
super.attachBaseContext(StateApp.instance.getLocaleContext(newBase))
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_polycentric_home);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.futo.platformplayer.activities
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.widget.EditText
|
||||
|
@ -12,6 +13,7 @@ import com.futo.platformplayer.R
|
|||
import com.futo.platformplayer.UIDialogs
|
||||
import com.futo.platformplayer.logging.Logger
|
||||
import com.futo.platformplayer.setNavigationBarColorAndIcons
|
||||
import com.futo.platformplayer.states.StateApp
|
||||
import com.futo.platformplayer.states.StatePolycentric
|
||||
import com.futo.polycentric.core.*
|
||||
import com.google.zxing.integration.android.IntentIntegrator
|
||||
|
@ -39,6 +41,10 @@ class PolycentricImportProfileActivity : AppCompatActivity() {
|
|||
}
|
||||
}
|
||||
|
||||
override fun attachBaseContext(newBase: Context?) {
|
||||
super.attachBaseContext(StateApp.instance.getLocaleContext(newBase))
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_polycentric_import_profile);
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.futo.platformplayer.activities
|
|||
|
||||
import android.app.Activity
|
||||
import android.content.ContentResolver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.BitmapFactory
|
||||
|
@ -48,6 +49,10 @@ class PolycentricProfileActivity : AppCompatActivity() {
|
|||
private lateinit var _imagePolycentric: ImageView;
|
||||
private var _avatarUri: Uri? = null;
|
||||
|
||||
override fun attachBaseContext(newBase: Context?) {
|
||||
super.attachBaseContext(StateApp.instance.getLocaleContext(newBase))
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_polycentric_profile);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.futo.platformplayer.activities
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
|
@ -7,12 +8,17 @@ import android.widget.ImageButton
|
|||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.futo.platformplayer.R
|
||||
import com.futo.platformplayer.setNavigationBarColorAndIcons
|
||||
import com.futo.platformplayer.states.StateApp
|
||||
import com.futo.platformplayer.views.buttons.BigButton
|
||||
|
||||
class PolycentricWhyActivity : AppCompatActivity() {
|
||||
private lateinit var _buttonVideo: BigButton;
|
||||
private lateinit var _buttonTechnical: BigButton;
|
||||
|
||||
override fun attachBaseContext(newBase: Context?) {
|
||||
super.attachBaseContext(StateApp.instance.getLocaleContext(newBase))
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_polycentric_why);
|
||||
|
|
|
@ -190,7 +190,9 @@ class HttpContext : AutoCloseable {
|
|||
do {
|
||||
read = readContentBytes(buffer, buffer.size);
|
||||
writer.write(buffer, 0, read);
|
||||
} while(read > 0);
|
||||
} while(read > 0);// && _stream.ready());
|
||||
//if(!_stream.ready())
|
||||
// _totalRead = contentLength;
|
||||
return writer.toString();
|
||||
}
|
||||
inline fun <reified T> readContentJson() : T {
|
||||
|
|
|
@ -200,7 +200,7 @@ class ManagedHttpServer(private val _requestedPort: Int = 0) {
|
|||
handler(req);
|
||||
|
||||
requestsTotal++;
|
||||
if(req.keepAlive) {
|
||||
if(req.keepAlive){// && requestReader.ready()) {
|
||||
keepAlive = true;
|
||||
if(req.keepAliveMax > 0)
|
||||
requestsMax = req.keepAliveMax;
|
||||
|
|
|
@ -29,6 +29,7 @@ class ResultCapabilities(
|
|||
const val TYPE_LIVE = "LIVE";
|
||||
const val TYPE_POSTS = "POSTS";
|
||||
const val TYPE_MIXED = "MIXED";
|
||||
const val TYPE_SUBSCRIPTIONS = "SUBSCRIPTIONS";
|
||||
|
||||
const val ORDER_CHONOLOGICAL = "CHRONOLOGICAL";
|
||||
|
||||
|
|
|
@ -51,6 +51,14 @@ class ChannelContentCache {
|
|||
Logger.i(TAG, "ChannelContentCache time: ${initializeTime}ms channels: ${allFiles.size}, videos: ${totalItems}, trimmed: ${trimmed}, total: ${totalItems - trimmed}");
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
synchronized(_channelContents) {
|
||||
for(channel in _channelContents)
|
||||
for(content in channel.value.getItems())
|
||||
uncacheContent(content);
|
||||
}
|
||||
}
|
||||
|
||||
fun getChannelCachePager(channelUrl: String): PlatformContentPager {
|
||||
val validID = channelUrl.toSafeFileName();
|
||||
|
||||
|
|
|
@ -287,7 +287,6 @@ class DeveloperEndpoints(private val context: Context) {
|
|||
@HttpPOST("/plugin/remoteCall")
|
||||
fun pluginRemoteCall(context: HttpContext) {
|
||||
try {
|
||||
val parameters = context.readContentString();
|
||||
val objId = context.query.get("id")
|
||||
val method = context.query.get("method")
|
||||
|
||||
|
@ -299,12 +298,15 @@ class DeveloperEndpoints(private val context: Context) {
|
|||
context.respondCode(400, "Missing method");
|
||||
return;
|
||||
}
|
||||
if(method != "isLoggedIn")
|
||||
Logger.i(TAG, "Remote Call [${objId}].${method}(...)");
|
||||
|
||||
val parameters = context.readContentString(); //TODO: Temporary
|
||||
|
||||
val remoteObj = getRemoteObject(objId);
|
||||
val paras = JsonParser.parseString(parameters);
|
||||
if(!paras.isJsonArray)
|
||||
throw IllegalArgumentException("Expected json array as body");
|
||||
if(method != "isLoggedIn")
|
||||
Logger.i(TAG, "Remote Call [${objId}].${method}(...)");
|
||||
val callResult = remoteObj.call(method, paras as JsonArray);
|
||||
val json = wrapRemoteResult(callResult, false);
|
||||
context.respondCode(200, json, "application/json");
|
||||
|
|
|
@ -105,6 +105,8 @@ class VideoDetailFragment : MainFragment {
|
|||
return;
|
||||
}
|
||||
|
||||
if(Settings.instance.other.bypassRotationPrevention && orientation == OrientationManager.Orientation.PORTRAIT)
|
||||
changeOrientation(OrientationManager.Orientation.PORTRAIT);
|
||||
if(lastOrientation == newOrientation)
|
||||
return;
|
||||
|
||||
|
|
|
@ -125,6 +125,14 @@ class Subscription {
|
|||
lastVideo = OffsetDateTime.MIN;
|
||||
lastVideoUpdate = OffsetDateTime.now();
|
||||
}
|
||||
ResultCapabilities.TYPE_SUBSCRIPTIONS -> {
|
||||
uploadInterval = interval;
|
||||
if(mostRecent != null)
|
||||
lastVideo = mostRecent;
|
||||
else if(lastVideo.year > 3000)
|
||||
lastVideo = OffsetDateTime.MIN;
|
||||
lastVideoUpdate = OffsetDateTime.now();
|
||||
}
|
||||
ResultCapabilities.TYPE_STREAMS -> {
|
||||
uploadStreamInterval = interval;
|
||||
if(mostRecent != null)
|
||||
|
|
|
@ -35,6 +35,8 @@ class SmartSubscriptionAlgorithm(
|
|||
|
||||
if(capabilities.hasType(ResultCapabilities.TYPE_MIXED) || capabilities.types.isEmpty())
|
||||
return@flatMap listOf(SubscriptionTask(client, sub, it.key, ResultCapabilities.TYPE_MIXED));
|
||||
else if(capabilities.hasType(ResultCapabilities.TYPE_SUBSCRIPTIONS))
|
||||
return@flatMap listOf(SubscriptionTask(client, sub, it.key, ResultCapabilities.TYPE_SUBSCRIPTIONS))
|
||||
else {
|
||||
val types = listOf(
|
||||
if(sub.shouldFetchVideos()) ResultCapabilities.TYPE_VIDEOS else null,
|
||||
|
|
|
@ -26,6 +26,8 @@ class ButtonField : BigButton, IField {
|
|||
|
||||
override var reference: Any? = null;
|
||||
|
||||
override val value: Any? = null;
|
||||
|
||||
override val obj : Any? get() {
|
||||
if(this._obj == null)
|
||||
throw java.lang.IllegalStateException("Can only be called if fromField is used");
|
||||
|
|
|
@ -39,6 +39,8 @@ class DropdownField : TableRow, IField {
|
|||
|
||||
override val onChanged = Event3<IField, Any, Any>();
|
||||
|
||||
override val value: Any? get() = _selected;
|
||||
|
||||
constructor(context: Context, attrs: AttributeSet? = null) : super(context, attrs){
|
||||
inflate(context, R.layout.field_dropdown, this);
|
||||
_spinner = findViewById(R.id.field_spinner);
|
||||
|
|
|
@ -9,11 +9,16 @@ import java.lang.reflect.Field
|
|||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class FormField(val title: Int, val type: String, val subtitle: Int = -1, val order: Int = 0, val id: String = "")
|
||||
|
||||
@Target(AnnotationTarget.FIELD, AnnotationTarget.PROPERTY)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
annotation class FormFieldWarning(val messageRes: Int)
|
||||
|
||||
interface IField {
|
||||
var descriptor: FormField?;
|
||||
val obj : Any?;
|
||||
val field : Field?;
|
||||
|
||||
val value: Any?;
|
||||
val onChanged : Event3<IField, Any, Any>;
|
||||
|
||||
var reference: Any?;
|
||||
|
@ -22,4 +27,17 @@ interface IField {
|
|||
fun setField();
|
||||
|
||||
fun setValue(value: Any);
|
||||
|
||||
companion object {
|
||||
fun isValueTrue(value: Any?): Boolean {
|
||||
if(value == null)
|
||||
return false;
|
||||
return when(value) {
|
||||
is Int -> value > 0;
|
||||
is Boolean -> value;
|
||||
is String -> value.toIntOrNull()?.let { it > 0 } ?: false || value.lowercase() == "true";
|
||||
else -> false
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ import kotlinx.serialization.encodeToString
|
|||
import kotlinx.serialization.json.Json
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Method
|
||||
import kotlin.reflect.KProperty
|
||||
import kotlin.reflect.full.declaredMemberProperties
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
import kotlin.reflect.full.hasAnnotation
|
||||
|
@ -103,7 +104,7 @@ class FieldForm : LinearLayout {
|
|||
onChanged.emit(field, value);
|
||||
|
||||
setting.warningDialog?.let {
|
||||
if(it.isNotBlank() && isValueTrue(value))
|
||||
if(it.isNotBlank() && IField.isValueTrue(value))
|
||||
UIDialogs.showDialog(context, R.drawable.ic_warning_yellow, setting.warningDialog, null, null, 0,
|
||||
UIDialogs.Action("Cancel", {
|
||||
field.setValue(oldValue);
|
||||
|
@ -118,8 +119,11 @@ class FieldForm : LinearLayout {
|
|||
if(dependentField == null || dependentField.second !is View)
|
||||
(field as View).visibility = View.GONE;
|
||||
else {
|
||||
val dependencyReady = IField.isValueTrue(dependentField.second.value);
|
||||
if(!dependencyReady)
|
||||
(field as View).visibility = View.GONE;
|
||||
dependentField.second.onChanged.subscribe { dependentField, value, oldValue ->
|
||||
val isValid = isValueTrue(value);
|
||||
val isValid = IField.isValueTrue(value);
|
||||
if(isValid)
|
||||
(field as View).visibility = View.VISIBLE;
|
||||
else
|
||||
|
@ -128,14 +132,6 @@ class FieldForm : LinearLayout {
|
|||
}
|
||||
}
|
||||
}
|
||||
private fun isValueTrue(value: Any): Boolean {
|
||||
return when(value) {
|
||||
is Int -> value > 0;
|
||||
is Boolean -> value;
|
||||
is String -> value.toIntOrNull()?.let { it > 0 } ?: false || value.lowercase() == "true";
|
||||
else -> false
|
||||
};
|
||||
}
|
||||
|
||||
fun setObjectValues(){
|
||||
val fields = _fields;
|
||||
|
@ -213,21 +209,42 @@ class FieldForm : LinearLayout {
|
|||
.asSequence()
|
||||
.asStream()
|
||||
.filter { it.hasAnnotation<FormField>() && it.javaField != null }
|
||||
.map { Pair<Field, FormField>(it.javaField!!, it.findAnnotation()!!) }
|
||||
.map { Pair<KProperty<*>, FormField>(it, it.findAnnotation()!!) }
|
||||
.toList()
|
||||
|
||||
//TODO: Rewrite fields to properties so no map is required
|
||||
val propertyMap = mutableMapOf<Field, KProperty<*>>();
|
||||
val fields = mutableListOf<IField>();
|
||||
for(prop in objFields) {
|
||||
prop.first.isAccessible = true;
|
||||
prop.first.javaField!!.isAccessible = true;
|
||||
|
||||
val field = when(prop.second.type) {
|
||||
GROUP -> GroupField(context).fromField(obj, prop.first, prop.second);
|
||||
DROPDOWN -> DropdownField(context).fromField(obj, prop.first, prop.second);
|
||||
TOGGLE -> ToggleField(context).fromField(obj, prop.first, prop.second);
|
||||
READONLYTEXT -> ReadOnlyTextField(context).fromField(obj, prop.first, prop.second);
|
||||
GROUP -> GroupField(context).fromField(obj, prop.first.javaField!!, prop.second);
|
||||
DROPDOWN -> DropdownField(context).fromField(obj, prop.first.javaField!!, prop.second);
|
||||
TOGGLE -> ToggleField(context).fromField(obj, prop.first.javaField!!, prop.second);
|
||||
READONLYTEXT -> ReadOnlyTextField(context).fromField(obj, prop.first.javaField!!, prop.second);
|
||||
else -> throw java.lang.IllegalStateException("Unknown field type ${prop.second.type} for ${prop.second.title}")
|
||||
}
|
||||
fields.add(field as IField);
|
||||
propertyMap.put(prop.first.javaField!!, prop.first);
|
||||
}
|
||||
|
||||
for(field in fields) {
|
||||
if(field.field != null) {
|
||||
val warning = propertyMap[field.field]?.findAnnotation<FormFieldWarning>();
|
||||
if(warning != null) {
|
||||
field.onChanged.subscribe { field, value, oldValue ->
|
||||
if(IField.isValueTrue(value))
|
||||
UIDialogs.showDialog(context, R.drawable.ic_warning_yellow, context.getString(warning.messageRes), null, null, 0,
|
||||
UIDialogs.Action("Cancel", {
|
||||
field.setValue(oldValue);
|
||||
}, UIDialogs.ActionStyle.NONE),
|
||||
UIDialogs.Action("Ok", {
|
||||
|
||||
}, UIDialogs.ActionStyle.PRIMARY));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val objProps = obj::class.declaredMemberProperties
|
||||
|
|
|
@ -9,6 +9,7 @@ import com.futo.platformplayer.R
|
|||
import com.futo.platformplayer.constructs.Event2
|
||||
import com.futo.platformplayer.constructs.Event3
|
||||
import java.lang.reflect.Field
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class GroupField : LinearLayout, IField {
|
||||
override var descriptor : FormField? = null;
|
||||
|
@ -36,6 +37,8 @@ class GroupField : LinearLayout, IField {
|
|||
|
||||
override var reference: Any? = null;
|
||||
|
||||
override val value: Any? = null;
|
||||
|
||||
constructor(context : Context, attrs : AttributeSet? = null) : super(context, attrs) {
|
||||
inflate(context, R.layout.field_group, this);
|
||||
_title = findViewById(R.id.field_group_title);
|
||||
|
|
|
@ -31,6 +31,9 @@ class ReadOnlyTextField : TableRow, IField {
|
|||
override val onChanged = Event3<IField, Any, Any>();
|
||||
|
||||
override var reference: Any? = null;
|
||||
|
||||
override val value: Any? = null;
|
||||
|
||||
constructor(context : Context, attrs : AttributeSet? = null) : super(context, attrs){
|
||||
inflate(context, R.layout.field_readonly_text, this);
|
||||
_title = findViewById(R.id.field_title);
|
||||
|
|
|
@ -36,6 +36,8 @@ class ToggleField : TableRow, IField {
|
|||
|
||||
override val onChanged = Event3<IField, Any, Any>();
|
||||
|
||||
override val value: Any get() = _lastValue;
|
||||
|
||||
constructor(context : Context, attrs : AttributeSet? = null) : super(context, attrs){
|
||||
inflate(context, R.layout.field_toggle, this);
|
||||
_toggle = findViewById(R.id.field_toggle);
|
||||
|
|
|
@ -338,6 +338,9 @@
|
|||
<string name="number_of_concurrent_threads_to_multiply_download_speeds_from_throttled_sources">Number of concurrent threads to multiply download speeds from throttled sources</string>
|
||||
<string name="payment">Payment</string>
|
||||
<string name="payment_status">Payment Status</string>
|
||||
<string name="bypass_rotation_prevention">Bypass Rotation Prevention</string>
|
||||
<string name="bypass_rotation_prevention_description">Allows for rotation on non-video views.\nWARNING: Not designed for it</string>
|
||||
<string name="bypass_rotation_prevention_warning">This may cause unexpected behavior, and is mostly untested.</string>
|
||||
<string name="player">Player</string>
|
||||
<string name="plugins">Plugins</string>
|
||||
<string name="preferred_casting_quality">Preferred Casting Quality</string>
|
||||
|
@ -362,6 +365,8 @@
|
|||
<string name="specify_how_many_threads_are_used_to_fetch_channels">Specify how many threads are used to fetch channels</string>
|
||||
<string name="submit_feedback">Submit feedback</string>
|
||||
<string name="submit_logs">Submit logs</string>
|
||||
<string name="clear_channel_cache">Clear Channel Cache</string>
|
||||
<string name="clear_channel_cache_description">Deletes all content from subscription channel cache</string>
|
||||
<string name="submit_logs_to_help_us_narrow_down_issues">Submit logs to help us narrow down issues</string>
|
||||
<string name="subscription_concurrency">Subscription Concurrency</string>
|
||||
<string name="track_playtime_locally">Track Playtime Locally</string>
|
||||
|
|
Loading…
Add table
Reference in a new issue