Skip to content

Commit ebee07e

Browse files
authored
feat(YouTube - Swipe controls): Add option for vertical progress bar (#4811)
1 parent 81999d8 commit ebee07e

File tree

11 files changed

+531
-164
lines changed

11 files changed

+531
-164
lines changed

extensions/shared/library/src/main/java/app/revanced/extension/shared/settings/Setting.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,9 +342,12 @@ protected final void removeFromPreferences() {
342342

343343
/**
344344
* Identical to calling {@link #save(Object)} using {@link #defaultValue}.
345+
*
346+
* @return The newly saved default value.
345347
*/
346-
public void resetToDefault() {
348+
public T resetToDefault() {
347349
save(defaultValue);
350+
return defaultValue;
348351
}
349352

350353
/**

extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/CustomPlayerOverlayOpacityPatch.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ public class CustomPlayerOverlayOpacityPatch {
1717

1818
if (opacity < 0 || opacity > 100) {
1919
Utils.showToastLong(str("revanced_player_overlay_opacity_invalid_toast"));
20-
Settings.PLAYER_OVERLAY_OPACITY.resetToDefault();
21-
opacity = Settings.PLAYER_OVERLAY_OPACITY.defaultValue;
20+
opacity = Settings.PLAYER_OVERLAY_OPACITY.resetToDefault();
2221
}
2322

2423
PLAYER_OVERLAY_OPACITY_LEVEL = (opacity * 255) / 100;

extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/MiniplayerPatch.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,7 @@ public boolean isModern() {
162162

163163
if (opacity < 0 || opacity > 100) {
164164
Utils.showToastLong(str("revanced_miniplayer_opacity_invalid_toast"));
165-
Settings.MINIPLAYER_OPACITY.resetToDefault();
166-
opacity = Settings.MINIPLAYER_OPACITY.defaultValue;
165+
opacity = Settings.MINIPLAYER_OPACITY.resetToDefault();
167166
}
168167

169168
OPACITY_LEVEL = (opacity * 255) / 100;

extensions/youtube/src/main/java/app/revanced/extension/youtube/patches/playback/speed/CustomPlaybackSpeedPatch.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,12 @@ public class CustomPlaybackSpeedPatch {
5454

5555
static {
5656
final float holdSpeed = Settings.SPEED_TAP_AND_HOLD.get();
57+
5758
if (holdSpeed > 0 && holdSpeed <= PLAYBACK_SPEED_MAXIMUM) {
5859
TAP_AND_HOLD_SPEED = holdSpeed;
5960
} else {
6061
showInvalidCustomSpeedToast();
61-
Settings.SPEED_TAP_AND_HOLD.resetToDefault();
62-
TAP_AND_HOLD_SPEED = Settings.SPEED_TAP_AND_HOLD.get();
62+
TAP_AND_HOLD_SPEED = Settings.SPEED_TAP_AND_HOLD.resetToDefault();
6363
}
6464

6565
loadCustomSpeeds();

extensions/youtube/src/main/java/app/revanced/extension/youtube/settings/Settings.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import static app.revanced.extension.youtube.sponsorblock.objects.CategoryBehaviour.MANUAL_SKIP;
2626
import static app.revanced.extension.youtube.sponsorblock.objects.CategoryBehaviour.SKIP_AUTOMATICALLY;
2727
import static app.revanced.extension.youtube.sponsorblock.objects.CategoryBehaviour.SKIP_AUTOMATICALLY_ONCE;
28+
import app.revanced.extension.youtube.swipecontrols.SwipeControlsConfigurationProvider.SwipeOverlayStyle;
2829

2930
import android.graphics.Color;
3031

@@ -323,12 +324,14 @@ public class Settings extends BaseSettings {
323324
public static final IntegerSetting SWIPE_MAGNITUDE_THRESHOLD = new IntegerSetting("revanced_swipe_threshold", 30, true,
324325
parentsAny(SWIPE_BRIGHTNESS, SWIPE_VOLUME));
325326
public static final IntegerSetting SWIPE_VOLUME_SENSITIVITY = new IntegerSetting("revanced_swipe_volume_sensitivity", 1, true, parent(SWIPE_VOLUME));
326-
public static final BooleanSetting SWIPE_SHOW_CIRCULAR_OVERLAY = new BooleanSetting("revanced_swipe_show_circular_overlay", FALSE, true,
327+
public static final EnumSetting<SwipeOverlayStyle> SWIPE_OVERLAY_STYLE = new EnumSetting<>("revanced_swipe_overlay_style", SwipeOverlayStyle.HORIZONTAL,true,
327328
parentsAny(SWIPE_BRIGHTNESS, SWIPE_VOLUME));
328-
public static final BooleanSetting SWIPE_OVERLAY_MINIMAL_STYLE = new BooleanSetting("revanced_swipe_overlay_minimal_style", FALSE, true,
329+
public static final IntegerSetting SWIPE_OVERLAY_TEXT_SIZE = new IntegerSetting("revanced_swipe_text_overlay_size", 14, true,
329330
parentsAny(SWIPE_BRIGHTNESS, SWIPE_VOLUME));
330331
public static final IntegerSetting SWIPE_OVERLAY_OPACITY = new IntegerSetting("revanced_swipe_overlay_background_opacity", 60, true,
331332
parentsAny(SWIPE_BRIGHTNESS, SWIPE_VOLUME));
333+
public static final StringSetting SWIPE_OVERLAY_PROGRESS_COLOR = new StringSetting("revanced_swipe_overlay_progress_color", "#FFFFFF", true,
334+
parentsAny(SWIPE_BRIGHTNESS, SWIPE_VOLUME));
332335
public static final LongSetting SWIPE_OVERLAY_TIMEOUT = new LongSetting("revanced_swipe_overlay_timeout", 500L, true,
333336
parentsAny(SWIPE_BRIGHTNESS, SWIPE_VOLUME));
334337
public static final BooleanSetting SWIPE_SAVE_AND_RESTORE_BRIGHTNESS = new BooleanSetting("revanced_swipe_save_and_restore_brightness", TRUE, true, parent(SWIPE_BRIGHTNESS));
Original file line numberDiff line numberDiff line change
@@ -1,160 +1,232 @@
11
package app.revanced.extension.youtube.swipecontrols
22

3+
import android.annotation.SuppressLint
34
import android.graphics.Color
5+
import app.revanced.extension.shared.Logger
46
import app.revanced.extension.shared.StringRef.str
57
import app.revanced.extension.shared.Utils
68
import app.revanced.extension.youtube.settings.Settings
79
import app.revanced.extension.youtube.shared.PlayerType
810

911
/**
10-
* provider for configuration for volume and brightness swipe controls
12+
* Provides configuration settings for volume and brightness swipe controls in the YouTube player.
13+
* Manages enabling/disabling gestures, overlay appearance, and behavior preferences.
1114
*/
1215
class SwipeControlsConfigurationProvider {
13-
//region swipe enable
16+
//region swipe enable
1417
/**
15-
* should swipe controls be enabled? (global setting)
18+
* Indicates whether swipe controls are enabled globally.
19+
* Returns true if either volume or brightness controls are enabled and the video is in fullscreen mode.
1620
*/
1721
val enableSwipeControls: Boolean
1822
get() = (enableVolumeControls || enableBrightnessControl) && isFullscreenVideo
1923

2024
/**
21-
* should swipe controls for volume be enabled?
25+
* Indicates whether swipe controls for adjusting volume are enabled.
2226
*/
2327
val enableVolumeControls = Settings.SWIPE_VOLUME.get()
2428

2529
/**
26-
* should swipe controls for volume be enabled?
30+
* Indicates whether swipe controls for adjusting brightness are enabled.
2731
*/
2832
val enableBrightnessControl = Settings.SWIPE_BRIGHTNESS.get()
2933

3034
/**
31-
* is the video player currently in fullscreen mode?
35+
* Checks if the video player is currently in fullscreen mode.
3236
*/
3337
private val isFullscreenVideo: Boolean
3438
get() = PlayerType.current == PlayerType.WATCH_WHILE_FULLSCREEN
35-
//endregion
39+
//endregion
3640

37-
//region keys enable
41+
//region keys enable
3842
/**
39-
* should volume key controls be overwritten? (global setting)
43+
* Indicates whether volume key controls should be overridden by swipe controls.
44+
* Returns true if volume controls are enabled and the video is in fullscreen mode.
4045
*/
4146
val overwriteVolumeKeyControls: Boolean
4247
get() = enableVolumeControls && isFullscreenVideo
43-
//endregion
48+
//endregion
4449

45-
//region gesture adjustments
50+
//region gesture adjustments
4651
/**
47-
* should press-to-swipe be enabled?
52+
* Indicates whether press-to-swipe mode is enabled, requiring a press before swiping to activate controls.
4853
*/
4954
val shouldEnablePressToSwipe: Boolean
5055
get() = Settings.SWIPE_PRESS_TO_ENGAGE.get()
5156

5257
/**
53-
* threshold for swipe detection
54-
* this may be called rapidly in onScroll, so we have to load it once and then leave it constant
58+
* The threshold for detecting swipe gestures, in pixels.
59+
* Loaded once to ensure consistent behavior during rapid scroll events.
5560
*/
5661
val swipeMagnitudeThreshold: Int
5762
get() = Settings.SWIPE_MAGNITUDE_THRESHOLD.get()
5863

5964
/**
60-
* How much volume will change by single swipe.
61-
* If it is set to 0, it will reset to the default value because 0 would disable swiping.
62-
* */
65+
* The sensitivity of volume swipe gestures, determining how much volume changes per swipe.
66+
* Resets to default if set to 0, as it would disable swiping.
67+
*/
6368
val volumeSwipeSensitivity: Int
6469
get() {
6570
val sensitivity = Settings.SWIPE_VOLUME_SENSITIVITY.get()
6671

6772
if (sensitivity < 1) {
68-
Settings.SWIPE_VOLUME_SENSITIVITY.resetToDefault()
69-
70-
return Settings.SWIPE_VOLUME_SENSITIVITY.get()
73+
return Settings.SWIPE_VOLUME_SENSITIVITY.resetToDefault()
7174
}
7275

7376
return sensitivity
7477
}
75-
//endregion
78+
//endregion
7679

77-
//region overlay adjustments
80+
//region overlay adjustments
7881
/**
79-
* should the overlay enable haptic feedback?
82+
* Indicates whether haptic feedback should be enabled for swipe control interactions.
8083
*/
8184
val shouldEnableHapticFeedback: Boolean
8285
get() = Settings.SWIPE_HAPTIC_FEEDBACK.get()
8386

8487
/**
85-
* how long the overlay should be shown on changes
88+
* The duration in milliseconds that the overlay should remain visible after a change.
8689
*/
8790
val overlayShowTimeoutMillis: Long
8891
get() = Settings.SWIPE_OVERLAY_TIMEOUT.get()
8992

9093
/**
91-
* Gets the opacity value (0-100%) is converted to an alpha value (0-255) for transparency.
92-
* If the opacity value is out of range, it resets to the default and displays a warning message.
94+
* The background opacity of the overlay, converted from a percentage (0-100) to an alpha value (0-255).
95+
* Resets to default and shows a toast if the value is out of range.
9396
*/
9497
val overlayBackgroundOpacity: Int
9598
get() {
9699
var opacity = Settings.SWIPE_OVERLAY_OPACITY.get()
97100

98101
if (opacity < 0 || opacity > 100) {
99102
Utils.showToastLong(str("revanced_swipe_overlay_background_opacity_invalid_toast"))
100-
Settings.SWIPE_OVERLAY_OPACITY.resetToDefault()
101-
opacity = Settings.SWIPE_OVERLAY_OPACITY.get()
103+
opacity = Settings.SWIPE_OVERLAY_OPACITY.resetToDefault()
102104
}
103105

104106
opacity = opacity * 255 / 100
105107
return Color.argb(opacity, 0, 0, 0)
106108
}
107109

108110
/**
109-
* The color of the progress overlay.
111+
* The color of the progress bar in the overlay.
112+
* Resets to default and shows a toast if the color string is invalid or empty.
110113
*/
111114
val overlayProgressColor: Int
112-
get() = 0xBFFFFFFF.toInt()
115+
get() {
116+
try {
117+
@SuppressLint("UseKtx")
118+
val color = Color.parseColor(Settings.SWIPE_OVERLAY_PROGRESS_COLOR.get())
119+
return (0xBF000000.toInt() or (color and 0xFFFFFF))
120+
} catch (ex: IllegalArgumentException) {
121+
Logger.printDebug({ "Could not parse color" }, ex)
122+
Utils.showToastLong(str("revanced_swipe_overlay_progress_color_invalid_toast"))
123+
Settings.SWIPE_OVERLAY_PROGRESS_COLOR.resetToDefault()
124+
return overlayProgressColor // Recursively return.
125+
}
126+
}
113127

114128
/**
115-
* The color used for the background of the progress overlay fill.
129+
* The background color used for the filled portion of the progress bar in the overlay.
116130
*/
117131
val overlayFillBackgroundPaint: Int
118132
get() = 0x80D3D3D3.toInt()
119133

120134
/**
121-
* The color used for the text and icons in the overlay.
135+
* The color used for text and icons in the overlay.
122136
*/
123137
val overlayTextColor: Int
124138
get() = Color.WHITE
125139

126140
/**
127-
* A flag that determines if the overlay should only show the icon.
141+
* The text size in the overlay, in density-independent pixels (dp).
142+
* Must be between 1 and 30 dp; resets to default and shows a toast if invalid.
128143
*/
129-
val overlayShowOverlayMinimalStyle: Boolean
130-
get() = Settings.SWIPE_OVERLAY_MINIMAL_STYLE.get()
144+
val overlayTextSize: Int
145+
get() {
146+
val size = Settings.SWIPE_OVERLAY_TEXT_SIZE.get()
147+
if (size < 1 || size > 30) {
148+
Utils.showToastLong(str("revanced_swipe_text_overlay_size_invalid_toast"))
149+
return Settings.SWIPE_OVERLAY_TEXT_SIZE.resetToDefault()
150+
}
151+
return size
152+
}
131153

132154
/**
133-
* A flag that determines if the progress bar should be circular.
155+
* Defines the style of the swipe controls overlay, determining its layout and appearance.
156+
*
157+
* @property isMinimal Indicates whether the style is minimalistic, omitting detailed progress indicators.
158+
* @property isHorizontalMinimalCenter Indicates whether the style is a minimal horizontal bar centered vertically.
159+
* @property isCircular Indicates whether the style uses a circular progress bar.
160+
* @property isVertical Indicates whether the style uses a vertical progress bar.
134161
*/
135-
val isCircularProgressBar: Boolean
136-
get() = Settings.SWIPE_SHOW_CIRCULAR_OVERLAY.get()
137-
//endregion
162+
@Suppress("unused")
163+
enum class SwipeOverlayStyle(
164+
val isMinimal: Boolean = false,
165+
val isHorizontalMinimalCenter: Boolean = false,
166+
val isCircular: Boolean = false,
167+
val isVertical: Boolean = false
168+
) {
169+
/**
170+
* A full horizontal progress bar with detailed indicators.
171+
*/
172+
HORIZONTAL,
138173

139-
//region behaviour
174+
/**
175+
* A minimal horizontal progress bar positioned at the top.
176+
*/
177+
HORIZONTAL_MINIMAL_TOP(isMinimal = true),
178+
179+
/**
180+
* A minimal horizontal progress bar centered vertically.
181+
*/
182+
HORIZONTAL_MINIMAL_CENTER(isMinimal = true, isHorizontalMinimalCenter = true),
183+
184+
/**
185+
* A full circular progress bar with detailed indicators.
186+
*/
187+
CIRCULAR(isCircular = true),
188+
189+
/**
190+
* A minimal circular progress bar.
191+
*/
192+
CIRCULAR_MINIMAL(isMinimal = true, isCircular = true),
193+
194+
/**
195+
* A full vertical progress bar with detailed indicators.
196+
*/
197+
VERTICAL(isVertical = true),
198+
199+
/**
200+
* A minimal vertical progress bar.
201+
*/
202+
VERTICAL_MINIMAL(isMinimal = true, isVertical = true)
203+
}
204+
205+
/**
206+
* The current style of the overlay, determining its layout and appearance.
207+
*/
208+
val overlayStyle: SwipeOverlayStyle
209+
get() = Settings.SWIPE_OVERLAY_STYLE.get()
210+
//endregion
140211

212+
//region behaviour
141213
/**
142-
* should the brightness be saved and restored when exiting or entering fullscreen
214+
* Indicates whether the brightness level should be saved and restored when entering or exiting fullscreen mode.
143215
*/
144216
val shouldSaveAndRestoreBrightness: Boolean
145217
get() = Settings.SWIPE_SAVE_AND_RESTORE_BRIGHTNESS.get()
146218

147219
/**
148-
* should auto-brightness be enabled at the lowest value of the brightness gesture
220+
* Indicates whether auto-brightness should be enabled when the brightness gesture reaches its lowest value.
149221
*/
150222
val shouldLowestValueEnableAutoBrightness: Boolean
151223
get() = Settings.SWIPE_LOWEST_VALUE_ENABLE_AUTO_BRIGHTNESS.get()
152224

153225
/**
154-
* variable that stores the brightness gesture value in the settings
226+
* The saved brightness value for the swipe gesture, used to restore brightness in fullscreen mode.
155227
*/
156228
var savedScreenBrightnessValue: Float
157229
get() = Settings.SWIPE_BRIGHTNESS_VALUE.get()
158230
set(value) = Settings.SWIPE_BRIGHTNESS_VALUE.save(value)
159-
//endregion
160-
}
231+
//endregion
232+
}

extensions/youtube/src/main/java/app/revanced/extension/youtube/swipecontrols/SwipeControlsHostActivity.kt

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,7 @@ import java.lang.ref.WeakReference
2323

2424
/**
2525
* The main controller for volume and brightness swipe controls.
26-
* note that the superclass is overwritten to the superclass of the MainActivity at patch time
27-
*
28-
* @smali Lapp/revanced/extension/swipecontrols/SwipeControlsHostActivity;
26+
* note that the superclass is overwritten to the superclass of the MainActivity at patch time.
2927
*/
3028
class SwipeControlsHostActivity : Activity() {
3129
/**

0 commit comments

Comments
 (0)