mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2026-05-16 04:52:39 +02:00
Dialog input support, configurable relay server, radio views select/deselect all long press
This commit is contained in:
@@ -25,6 +25,7 @@ import com.futo.platformplayer.states.StateCache
|
|||||||
import com.futo.platformplayer.states.StateMeta
|
import com.futo.platformplayer.states.StateMeta
|
||||||
import com.futo.platformplayer.states.StatePayment
|
import com.futo.platformplayer.states.StatePayment
|
||||||
import com.futo.platformplayer.states.StatePolycentric
|
import com.futo.platformplayer.states.StatePolycentric
|
||||||
|
import com.futo.platformplayer.states.StateSync
|
||||||
import com.futo.platformplayer.states.StateUpdate
|
import com.futo.platformplayer.states.StateUpdate
|
||||||
import com.futo.platformplayer.stores.FragmentedStorage
|
import com.futo.platformplayer.stores.FragmentedStorage
|
||||||
import com.futo.platformplayer.stores.FragmentedStorageFileJson
|
import com.futo.platformplayer.stores.FragmentedStorageFileJson
|
||||||
@@ -1092,6 +1093,38 @@ class Settings : FragmentedStorageFileJson() {
|
|||||||
|
|
||||||
@FormField(R.string.local_connections, FieldForm.TOGGLE, R.string.local_connections_description, 3)
|
@FormField(R.string.local_connections, FieldForm.TOGGLE, R.string.local_connections_description, 3)
|
||||||
var localConnections: Boolean = true;
|
var localConnections: Boolean = true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var syncServerUrl: String? = null;
|
||||||
|
@FormField(R.string.payment_status, FieldForm.READONLYTEXT, -1, 6)
|
||||||
|
val syncServer: String get() = if(syncServerUrl?.isBlank() == true) StateSync.RELAY_SERVER else syncServerUrl ?: StateSync.RELAY_SERVER;
|
||||||
|
|
||||||
|
@FormField(R.string.configure_sync_server, FieldForm.BUTTON, R.string.configure_sync_server_description, 7)
|
||||||
|
fun configureSyncServer() {
|
||||||
|
SettingsActivity.getActivity()?.let { context ->
|
||||||
|
UIDialogs.showDialog(context, R.drawable.device_sync, false,
|
||||||
|
"Enter the url to your relay server",
|
||||||
|
"Using your own relay server requires a proper setup with portforwarding.\nUse at your own risk.",
|
||||||
|
null,
|
||||||
|
syncServerUrl ?: "",
|
||||||
|
"YourRelayServerDomain.com", 0,
|
||||||
|
UIDialogs.Action("Cancel", {}),
|
||||||
|
UIDialogs.Action("Reset", {
|
||||||
|
syncServerUrl = null;
|
||||||
|
instance.save();
|
||||||
|
context.reloadSettings();
|
||||||
|
UIDialogs.toast("Sync server changes require a restart");
|
||||||
|
}, UIDialogs.ActionStyle.ACCENT),
|
||||||
|
UIDialogs.Action.withInput("Configure", {
|
||||||
|
syncServerUrl = it?.text
|
||||||
|
instance.save();
|
||||||
|
context.reloadSettings();
|
||||||
|
UIDialogs.toast("Sync server changes require a restart");
|
||||||
|
}, UIDialogs.ActionStyle.PRIMARY),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@FormField(R.string.info, FieldForm.GROUP, -1, 21)
|
@FormField(R.string.info, FieldForm.GROUP, -1, 21)
|
||||||
|
|||||||
@@ -113,8 +113,8 @@ class UIDialogs {
|
|||||||
currentDialog.code,
|
currentDialog.code,
|
||||||
currentDialog.defaultCloseAction,
|
currentDialog.defaultCloseAction,
|
||||||
*currentDialog.actions.map {
|
*currentDialog.actions.map {
|
||||||
return@map Action(it.text, {
|
return@map Action.withInput(it.text, { str ->
|
||||||
it.action();
|
it.invokeAction(str);
|
||||||
multiShowDialog(context, dialogDescriptor.drop(1), finally);
|
multiShowDialog(context, dialogDescriptor.drop(1), finally);
|
||||||
}, it.style);
|
}, it.style);
|
||||||
}.toTypedArray());
|
}.toTypedArray());
|
||||||
@@ -203,7 +203,9 @@ class UIDialogs {
|
|||||||
fun showDialog(context: Context, icon: Int, text: String, textDetails: String? = null, code: String? = null, defaultCloseAction: Int, vararg actions: Action): AlertDialog {
|
fun showDialog(context: Context, icon: Int, text: String, textDetails: String? = null, code: String? = null, defaultCloseAction: Int, vararg actions: Action): AlertDialog {
|
||||||
return showDialog(context, icon, false, text, textDetails, code, defaultCloseAction, *actions);
|
return showDialog(context, icon, false, text, textDetails, code, defaultCloseAction, *actions);
|
||||||
}
|
}
|
||||||
fun showDialog(context: Context, icon: Int, animated: Boolean, text: String, textDetails: String? = null, code: String? = null, defaultCloseAction: Int, vararg actions: Action): AlertDialog {
|
fun showDialog(context: Context, icon: Int, animated: Boolean, text: String, textDetails: String? = null, code: String? = null, defaultCloseAction: Int, vararg actions: Action): AlertDialog
|
||||||
|
= showDialog(context, icon, animated, text, textDetails, code, null, null, defaultCloseAction, *actions);
|
||||||
|
fun showDialog(context: Context, icon: Int, animated: Boolean, text: String, textDetails: String? = null, code: String? = null, input: String?, placeholder: String?, defaultCloseAction: Int, vararg actions: Action): AlertDialog {
|
||||||
val builder = AlertDialog.Builder(context);
|
val builder = AlertDialog.Builder(context);
|
||||||
val view = LayoutInflater.from(context).inflate(R.layout.dialog_multi_button, null);
|
val view = LayoutInflater.from(context).inflate(R.layout.dialog_multi_button, null);
|
||||||
builder.setView(view);
|
builder.setView(view);
|
||||||
@@ -226,6 +228,16 @@ class UIDialogs {
|
|||||||
this.text = textDetails;
|
this.text = textDetails;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
var inputView = view.findViewById<TextView>(R.id.dialog_text_input);
|
||||||
|
inputView.apply {
|
||||||
|
if (input == null && placeholder == null) this.visibility = View.GONE;
|
||||||
|
else {
|
||||||
|
this.text = input ?: "";
|
||||||
|
this.hint = placeholder ?: "";
|
||||||
|
this.visibility = View.VISIBLE;
|
||||||
|
this.textAlignment = View.TEXT_ALIGNMENT_VIEW_START
|
||||||
|
}
|
||||||
|
};
|
||||||
view.findViewById<TextView>(R.id.dialog_text_code).apply {
|
view.findViewById<TextView>(R.id.dialog_text_code).apply {
|
||||||
if (code == null) this.visibility = View.GONE;
|
if (code == null) this.visibility = View.GONE;
|
||||||
else {
|
else {
|
||||||
@@ -250,7 +262,7 @@ class UIDialogs {
|
|||||||
buttonView.textSize = 14f;
|
buttonView.textSize = 14f;
|
||||||
buttonView.typeface = resources.getFont(R.font.inter_regular);
|
buttonView.typeface = resources.getFont(R.font.inter_regular);
|
||||||
buttonView.text = act.text;
|
buttonView.text = act.text;
|
||||||
buttonView.setOnClickListener { act.action(); dialog.dismiss(); };
|
buttonView.setOnClickListener { act.invokeAction(DialogResult(inputView?.text?.toString())); dialog.dismiss(); };
|
||||||
when(act.style) {
|
when(act.style) {
|
||||||
ActionStyle.PRIMARY -> buttonView.setBackgroundResource(R.drawable.background_button_primary);
|
ActionStyle.PRIMARY -> buttonView.setBackgroundResource(R.drawable.background_button_primary);
|
||||||
ActionStyle.ACCENT -> buttonView.setBackgroundResource(R.drawable.background_button_accent);
|
ActionStyle.ACCENT -> buttonView.setBackgroundResource(R.drawable.background_button_accent);
|
||||||
@@ -275,7 +287,7 @@ class UIDialogs {
|
|||||||
};
|
};
|
||||||
dialog.setOnCancelListener {
|
dialog.setOnCancelListener {
|
||||||
if(defaultCloseAction >= 0 && defaultCloseAction < actions.size)
|
if(defaultCloseAction >= 0 && defaultCloseAction < actions.size)
|
||||||
actions[defaultCloseAction].action();
|
actions[defaultCloseAction].invokeAction(DialogResult(inputView?.text?.toString()));
|
||||||
}
|
}
|
||||||
dialog.setOnDismissListener {
|
dialog.setOnDismissListener {
|
||||||
registerDialogClosed(dialog);
|
registerDialogClosed(dialog);
|
||||||
@@ -535,17 +547,36 @@ class UIDialogs {
|
|||||||
}
|
}
|
||||||
class Action {
|
class Action {
|
||||||
val text: String;
|
val text: String;
|
||||||
val action: ()->Unit;
|
val action: ((DialogResult?)->Unit);
|
||||||
val style: ActionStyle;
|
val style: ActionStyle;
|
||||||
var center: Boolean;
|
var center: Boolean;
|
||||||
|
|
||||||
constructor(text: String, action: ()->Unit, style: ActionStyle = ActionStyle.NONE, center: Boolean = false) {
|
constructor(text: String, action: ()->Unit, style: ActionStyle = ActionStyle.NONE, center: Boolean = false) {
|
||||||
|
this.text = text;
|
||||||
|
this.action = { action() };
|
||||||
|
this.style = style;
|
||||||
|
this.center = center;
|
||||||
|
}
|
||||||
|
protected constructor(text: String, action: (DialogResult?)->Unit, style: ActionStyle = ActionStyle.NONE, center: Boolean = false) {
|
||||||
this.text = text;
|
this.text = text;
|
||||||
this.action = action;
|
this.action = action;
|
||||||
this.style = style;
|
this.style = style;
|
||||||
this.center = center;
|
this.center = center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun invokeAction(input: DialogResult? = null) {
|
||||||
|
this.action(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun withInput(text: String, action: (DialogResult?)->Unit, style: ActionStyle = ActionStyle.NONE, center: Boolean = false): Action {
|
||||||
|
return Action(text, action, style, center);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
class DialogResult(
|
||||||
|
val text: String?
|
||||||
|
);
|
||||||
enum class ActionStyle {
|
enum class ActionStyle {
|
||||||
NONE,
|
NONE,
|
||||||
PRIMARY,
|
PRIMARY,
|
||||||
|
|||||||
@@ -57,9 +57,12 @@ class StateSync {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var relayServerUrl = Settings.instance.synchronization.syncServer;
|
||||||
|
Logger.i(TAG, "Relay used: ${relayServerUrl}");
|
||||||
|
|
||||||
syncService = SyncService(
|
syncService = SyncService(
|
||||||
SERVICE_NAME,
|
SERVICE_NAME,
|
||||||
RELAY_SERVER,
|
relayServerUrl,
|
||||||
RELAY_PUBLIC_KEY,
|
RELAY_PUBLIC_KEY,
|
||||||
APP_ID,
|
APP_ID,
|
||||||
StoreBasedSyncDatabaseProvider(),
|
StoreBasedSyncDatabaseProvider(),
|
||||||
|
|||||||
@@ -50,6 +50,29 @@ class RadioGroupView : FlexboxLayout {
|
|||||||
radioView.layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
|
radioView.layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
|
||||||
radioView.setInfo(option.first, initiallySelectedOptions.contains(option.second));
|
radioView.setInfo(option.first, initiallySelectedOptions.contains(option.second));
|
||||||
radioView.setPadding(_padding_px, _padding_px, _padding_px, _padding_px);
|
radioView.setPadding(_padding_px, _padding_px, _padding_px, _padding_px);
|
||||||
|
if(multiSelect)
|
||||||
|
radioView.onLongClick.subscribe {
|
||||||
|
val selected = !radioView.selected;
|
||||||
|
if (selected) {
|
||||||
|
selectedOptions.clear();
|
||||||
|
for(v in radioViews)
|
||||||
|
v.setIsSelected(true);
|
||||||
|
selectedOptions.addAll(options.map { it.second });
|
||||||
|
} else {
|
||||||
|
if(atLeastOne) {
|
||||||
|
for(v in radioViews)
|
||||||
|
v.setIsSelected(false);
|
||||||
|
selectedOptions.clear();
|
||||||
|
selectedOptions.add(option.second);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for(v in radioViews)
|
||||||
|
v.setIsSelected(false);
|
||||||
|
selectedOptions.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onSelectedChange.emit(selectedOptions);
|
||||||
|
}
|
||||||
radioView.onClick.subscribe {
|
radioView.onClick.subscribe {
|
||||||
val selected = !radioView.selected;
|
val selected = !radioView.selected;
|
||||||
if (selected) {
|
if (selected) {
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ class RadioView : LinearLayout {
|
|||||||
|
|
||||||
val selected get() = _selected;
|
val selected get() = _selected;
|
||||||
var onClick = Event0();
|
var onClick = Event0();
|
||||||
|
var onLongClick = Event0();
|
||||||
var onSelectedChange = Event1<Boolean>();
|
var onSelectedChange = Event1<Boolean>();
|
||||||
|
|
||||||
constructor(context: Context, attrs: AttributeSet? = null) : super(context, attrs) {
|
constructor(context: Context, attrs: AttributeSet? = null) : super(context, attrs) {
|
||||||
@@ -32,6 +33,13 @@ class RadioView : LinearLayout {
|
|||||||
setIsSelected(!_selected)
|
setIsSelected(!_selected)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
_root.setOnLongClickListener {
|
||||||
|
onLongClick.emit();
|
||||||
|
if (_handleClick) {
|
||||||
|
setIsSelected(!_selected)
|
||||||
|
}
|
||||||
|
return@setOnLongClickListener true;
|
||||||
|
}
|
||||||
|
|
||||||
_root.setBackgroundResource(R.drawable.background_radio_unselected);
|
_root.setBackgroundResource(R.drawable.background_radio_unselected);
|
||||||
_textTag.setTextColor(ContextCompat.getColor(context, R.color.gray_67));
|
_textTag.setTextColor(ContextCompat.getColor(context, R.color.gray_67));
|
||||||
|
|||||||
@@ -63,6 +63,16 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
tools:ignore="HardcodedText" />
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/dialog_text_input"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="10dp"
|
||||||
|
android:layout_marginRight="10dp"
|
||||||
|
android:layout_marginTop="10dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/dialog_buttons"
|
android:id="@+id/dialog_buttons"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@@ -338,6 +338,8 @@
|
|||||||
<string name="test_background_worker">Test Background Worker</string>
|
<string name="test_background_worker">Test Background Worker</string>
|
||||||
<string name="test_background_worker_description"></string>
|
<string name="test_background_worker_description"></string>
|
||||||
<string name="clear_payment">Clear Payment</string>
|
<string name="clear_payment">Clear Payment</string>
|
||||||
|
<string name="configure_sync_server">Configure Sync Server</string>
|
||||||
|
<string name="configure_sync_server_description">Allows you to change the Sync Server to a self-hosted one.</string>
|
||||||
<string name="clears_cookies_when_you_log_out">Clears cookies when you log out</string>
|
<string name="clears_cookies_when_you_log_out">Clears cookies when you log out</string>
|
||||||
<string name="clears_in_app_browser_cookies">Clears in-app browser cookies</string>
|
<string name="clears_in_app_browser_cookies">Clears in-app browser cookies</string>
|
||||||
<string name="configure_browsing_behavior">Configure browsing behavior</string>
|
<string name="configure_browsing_behavior">Configure browsing behavior</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user