-
-
Notifications
You must be signed in to change notification settings - Fork 262
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: settings
patch
#2366
Comments
ProposalMy proposal is to keep runtime preference handling (so definition preferences & screen layout) in Prerequisites / ToDothe following points are definitively missing for this implementation to work well:
APISo, when writing a integration for a patch, you'd create a /**
* every patch gets their own Preferences class that handles creating the settings screen & housing the preference wrappers
*
* the [PatchPreferencesScreen] class gets a reference to the patch name & can decide if it should enable or disable the patch
*/
class MyPatchPreferences : PatchPreferencesScreen("swipe-controls") {
/**
* preferences are defined per- patch in a companion object
* (behaves similar to static class members)
*/
companion object {
// 'PreferenceWrapper' is a generic class, it's type is inferred from the defaultValue parameter
val myBooleanPreference = PreferenceWrapper("my_boolean", false)
// all primitives (string, boolean, int, long, double, float) + enums are supported, more can be added
val myEnumPreference = PreferenceWrapper("my_enum", FooBar.NONE)
// patch preferences using this api should be written in kotlin (makes stuff easier)
// when using java for the rest of the patch, mark the preference as @JvmStatic
@JvmStatic
val myOtherBooleanPreference = PreferenceWrapper("my_other_more_different_boolean", true)
}
} the layout on the preference screen is written per-patch in a DSL, either as a loose wrapper around /**
* createScreen handles creating the settings screen.
* Each patch has it's own sub-screen that is shown on a common 'ReVanced Settings' screen, so only one entry must be injected into xml
*/
override fun initScreen() = screen {
// screens are created in a dsl, either directly
// exposing components from android.preference.* (easiest) or wrappers for custom controls (harder)
title = "My Patch's Preferences"
summary = "Idk, something about how great this sample patch is and what it does..."
// preference screens can be divided into categories
category {
title = "My category"
// controls are automagically bound to the preferences and update when the preference changes (and vise-versa)
enum(myEnumPreference) {
title = "Enums are fun!"
// mapping from enum ordinal to display names shown to the user
mapOf(
FooBar.NONE to "No FooBar for you!",
FooBar.FOO to "Enable Foo",
FooBar.BAR to "Okay, just a bit of Bar"
)
}
// dependencies to other preferences (or state in general) can be expressed
// with a 'dependsOn' statement at any level in the hierarchy
switch(myBooleanPreference) {
title = "This is a switch, only for 'BAR' enjoyers!"
summaryOff = "you turned stuff off"
summaryOn = "and now it's turned back on"
// the switch for 'myBooleanPreference' is only enabled if 'myEnumPreference' is set to 'BAR'
dependsOn(myEnumPreference) { myEnumPreference.value == FooBar.BAR }
}
}
// you can have multiple categories, and they can also have dependencies
category {
title = "Debug settings"
// preferences are automatically updated when changed, so when this checkbox is checked...
checkBox(myOtherBooleanPreference) {
title = "Another boolean, this time a checkbox"
summaryOff = "it's off"
summaryOn = "you get the idea..."
}
// ... this switch will toggle at the same time
switch(myOtherBooleanPreference) {
title = "running out of text..."
}
// only enable 'debug settings' category when in a debug build
dependsOn { BuildConfig.DEBUG }
}
} accessing the preferences is possible in a type-safe (and typo- free) way from both java and kotlin: class MyPatch {
fun foobar() {
// preferences can be accessed in a type-safe manner
if (MyPatchPreferences.myBooleanPreference.value) {
// 'myBooleanPreference' is set to 'true'
}
// if the preference value is accessed very frequently, use the cached value (read- only)
for (i in 0..100000) {
// vv this effectively only loads the preference once, and serves the cached value on all other accesses
if (MyPatchPreferences.myOtherBooleanPreference.valueCached) {
Log.i("Fast", "i am speed")
}
}
// you can also set the preference, ofc
// it is automatically written to SharedPreferences
MyPatchPreferences.myEnumPreference.value = FooBar.FOO
}
} public class MyJavaPatch {
public void foobar() {
// accessing preference not marked with @JvmStatic from java code
if (MyPatchPreferences.Companion.getMyBooleanPreference().getValue()) {
}
// vs. accessing with @JvmStatic
if (MyPatchPreferences.getMyOtherBooleanPreference().getValue()) {
}
}
} as you may tell, i used something similar in a different app already. Relevant snippets can be found here. |
@shadow578 Your proposal looks better. If we want to go this route, we need to figure out how to tightly couple integrations and patches together so it will work that way. The patches will have to depend on integrations as a dependency, while |
I don't actually see the reason for all this hassle. Why not just keep the current (working system). Inject all the installed patches with a patch into the integrations, and then only show the prefScreens that are actually installed? Would save so much time and work because its already nearly finished. |
exactly what i was thinking too. That way, patches stays (mostly) the same with a On the note of localisation, if we leave revanced (or just preferences, for that matter) english only, we can just use string constants. Otherwise, we'd have to inject string resources for every patch that has preferences (tho that's a one-liner with |
okay, so @oSumAtrIX have been in a voicecall now and discussed about all that. I understand what he's trying to do and it makes sense to prevent future problems from the beginning. Maybe he can explain to you |
π This issue has been resolved in version 2.40.0 π The release is available on:
Your semantic-release bot π¦π |
π Issue
Currently, no patch to display settings in the YouTube application exists. Patches that depend on a settings menu will not work correctly.
β Solution
Add a patch to integrate the settings into the application.
β Additional context
The implementation of this patch will have to be discussed thoroughly. It will work as a dependency for other patches and should support a basic framework for other patches to include their settings.
Pseudo implementation in other patches:
The text was updated successfully, but these errors were encountered: