mirror of
https://github.com/revanced/revanced-integrations.git
synced 2025-01-06 01:55:50 +01:00
chore: merge branch dev
to main
(#437)
This commit is contained in:
commit
59f7733f99
49
CHANGELOG.md
49
CHANGELOG.md
@ -1,3 +1,52 @@
|
||||
# [0.113.0-dev.5](https://github.com/ReVanced/revanced-integrations/compare/v0.113.0-dev.4...v0.113.0-dev.5) (2023-07-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Spoof client:** show video time and chapters while using seekbar ([#435](https://github.com/ReVanced/revanced-integrations/issues/435)) ([a0f831a](https://github.com/ReVanced/revanced-integrations/commit/a0f831ac3f3773a0b47a0fb532d0bf58f6aa96d7))
|
||||
|
||||
# [0.113.0-dev.4](https://github.com/ReVanced/revanced-integrations/compare/v0.113.0-dev.3...v0.113.0-dev.4) (2023-07-19)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **Tiktok - Settings:** bump compatibility ([#440](https://github.com/ReVanced/revanced-integrations/issues/440)) ([821a32e](https://github.com/ReVanced/revanced-integrations/commit/821a32ee40d7795cabedc40f24356c1c1069ddec))
|
||||
|
||||
# [0.113.0-dev.3](https://github.com/ReVanced/revanced-integrations/compare/v0.113.0-dev.2...v0.113.0-dev.3) (2023-07-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/return-youtube-dislike:** fix dislikes not showing in some situations ([#439](https://github.com/ReVanced/revanced-integrations/issues/439)) ([7a28c2f](https://github.com/ReVanced/revanced-integrations/commit/7a28c2fa13438947931b8c41ef73b128a32530eb))
|
||||
|
||||
# [0.113.0-dev.2](https://github.com/ReVanced/revanced-integrations/compare/v0.113.0-dev.1...v0.113.0-dev.2) (2023-07-16)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **YouTube - Hide ads:** hide new type of buttoned ad ([9f21c72](https://github.com/ReVanced/revanced-integrations/commit/9f21c7268e5a08f542f5b090316486aadf4a5acd))
|
||||
|
||||
# [0.113.0-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.112.1-dev.2...v0.113.0-dev.1) (2023-07-15)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **youtube:** rename `video-speed` to `playback-speed` ([#438](https://github.com/revanced/revanced-integrations/issues/438)) ([630776f](https://github.com/revanced/revanced-integrations/commit/630776fd3514435dd83ef1c765a4f5b007e8e2f2))
|
||||
|
||||
## [0.112.1-dev.2](https://github.com/revanced/revanced-integrations/compare/v0.112.1-dev.1...v0.112.1-dev.2) (2023-07-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **YouTube - Hide Shorts Components:** hide sound button ([a2b1630](https://github.com/revanced/revanced-integrations/commit/a2b1630df8d330f3c0cbf77e9ea46b9d1c51adde))
|
||||
|
||||
## [0.112.1-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.112.0...v0.112.1-dev.1) (2023-07-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **youtube/sponsorblock:** fix some segments skipping slightly too late ([#436](https://github.com/revanced/revanced-integrations/issues/436)) ([f694928](https://github.com/revanced/revanced-integrations/commit/f69492819e52e0fd99c4e10390fd39f26c3a9c48))
|
||||
|
||||
# [0.112.0](https://github.com/revanced/revanced-integrations/compare/v0.111.2...v0.112.0) (2023-07-08)
|
||||
|
||||
|
||||
|
@ -202,7 +202,13 @@ public class ReturnYouTubeDislikePatch {
|
||||
*/
|
||||
public static boolean setShortsDislikes(@NonNull View likeDislikeView) {
|
||||
try {
|
||||
if (!SettingsEnum.RYD_ENABLED.getBoolean() || !SettingsEnum.RYD_SHORTS.getBoolean()) {
|
||||
if (!SettingsEnum.RYD_ENABLED.getBoolean()) {
|
||||
return false;
|
||||
}
|
||||
if (!SettingsEnum.RYD_SHORTS.getBoolean()) {
|
||||
// Must clear the data here, in case a new video was loaded while PlayerType
|
||||
// suggested the video was not a short (can happen when spoofing to an old app version).
|
||||
ReturnYouTubeDislike.setCurrentVideoId(null);
|
||||
return false;
|
||||
}
|
||||
LogHelper.printDebug(() -> "setShortsDislikes");
|
||||
@ -302,7 +308,7 @@ public class ReturnYouTubeDislikePatch {
|
||||
if (!videoId.equals(currentVideoId)) {
|
||||
currentVideoId = videoId;
|
||||
|
||||
final boolean noneHiddenOrMinimized = PlayerType.getCurrent().isNoneHiddenOrMinimized();
|
||||
final boolean noneHiddenOrMinimized = PlayerType.getCurrent().isNoneOrHidden();
|
||||
if (noneHiddenOrMinimized && !SettingsEnum.RYD_SHORTS.getBoolean()) {
|
||||
ReturnYouTubeDislike.setCurrentVideoId(null);
|
||||
return;
|
||||
|
@ -2,6 +2,10 @@ package app.revanced.integrations.patches;
|
||||
|
||||
import static app.revanced.integrations.utils.ReVancedUtils.containsAny;
|
||||
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import app.revanced.integrations.shared.PlayerType;
|
||||
import app.revanced.integrations.utils.LogHelper;
|
||||
@ -67,4 +71,25 @@ public class SpoofSignatureVerificationPatch {
|
||||
return originalValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*/
|
||||
public static boolean getSeekbarThumbnailOverrideValue() {
|
||||
return SettingsEnum.SPOOF_SIGNATURE_VERIFICATION.getBoolean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
*
|
||||
* @param view seekbar thumbnail view. Includes both shorts and regular videos.
|
||||
*/
|
||||
public static void seekbarImageViewCreated(ImageView view) {
|
||||
if (SettingsEnum.SPOOF_SIGNATURE_VERIFICATION.getBoolean()) {
|
||||
view.setVisibility(View.GONE);
|
||||
// Also hide the border around the thumbnail (otherwise a 1 pixel wide bordered frame is visible).
|
||||
ViewGroup parentLayout = (ViewGroup) view.getParent();
|
||||
parentLayout.setPadding(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ public final class VideoInformation {
|
||||
@NonNull
|
||||
private static String videoId = "";
|
||||
private static long videoLength = 0;
|
||||
private static volatile long videoTime = -1; // must be volatile. Value is set off main thread from high precision patch hook
|
||||
private static long videoTime = -1;
|
||||
/**
|
||||
* The current playback speed
|
||||
*/
|
||||
@ -98,17 +98,17 @@ public final class VideoInformation {
|
||||
|
||||
/**
|
||||
* Injection point.
|
||||
* Called off the main thread approximately every 50ms to 100ms
|
||||
* Called on the main thread every 1000ms.
|
||||
*
|
||||
* @param currentPlaybackTime The current playback time of the video in milliseconds.
|
||||
*/
|
||||
public static void setVideoTimeHighPrecision(final long currentPlaybackTime) {
|
||||
public static void setVideoTime(final long currentPlaybackTime) {
|
||||
videoTime = currentPlaybackTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Seek on the current video.
|
||||
* Does not function for playback of Shorts or Stories.
|
||||
* Does not function for playback of Shorts.
|
||||
*
|
||||
* Caution: If called from a videoTimeHook() callback,
|
||||
* this will cause a recursive call into the same videoTimeHook() callback.
|
||||
@ -118,11 +118,6 @@ public final class VideoInformation {
|
||||
*/
|
||||
public static boolean seekTo(final long millisecond) {
|
||||
ReVancedUtils.verifyOnMainThread();
|
||||
if (seekMethod == null) {
|
||||
LogHelper.printException(() -> "seekMethod was null");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
LogHelper.printDebug(() -> "Seeking to " + millisecond);
|
||||
return (Boolean) seekMethod.invoke(playerControllerRef.get(), millisecond);
|
||||
@ -137,7 +132,7 @@ public final class VideoInformation {
|
||||
}
|
||||
|
||||
/**
|
||||
* Id of the current video playing. Includes Shorts and YouTube Stories.
|
||||
* Id of the current video playing. Includes Shorts.
|
||||
*
|
||||
* @return The id of the video. Empty string if not set yet.
|
||||
*/
|
||||
@ -154,7 +149,7 @@ public final class VideoInformation {
|
||||
}
|
||||
|
||||
/**
|
||||
* Length of the current video playing. Includes Shorts and YouTube Stories.
|
||||
* Length of the current video playing. Includes Shorts.
|
||||
*
|
||||
* @return The length of the video in milliseconds.
|
||||
* If the video is not yet loaded, or if the video is playing in the background with no video visible,
|
||||
@ -165,14 +160,14 @@ public final class VideoInformation {
|
||||
}
|
||||
|
||||
/**
|
||||
* Playback time of the current video playing.
|
||||
* Value can lag up to approximately 100ms behind the actual current video playback time.
|
||||
* Playback time of the current video playing. Includes Shorts.
|
||||
*
|
||||
* Note: Code inside a videoTimeHook patch callback
|
||||
* should use the callback video time and avoid using this method
|
||||
* (in situations of recursive hook callbacks, the value returned here may be outdated).
|
||||
* Value will lag behind the actual playback time by a variable amount based on the playback speed.
|
||||
*
|
||||
* Includes Shorts and YouTube Stories.
|
||||
* If playback speed is 2.0x, this value may be up to 2000ms behind the actual playback time.
|
||||
* If playback speed is 1.0x, this value may be up to 1000ms behind the actual playback time.
|
||||
* If playback speed is 0.5x, this value may be up to 500ms behind the actual playback time.
|
||||
* Etc.
|
||||
*
|
||||
* @return The time of the video in milliseconds. -1 if not set yet.
|
||||
*/
|
||||
@ -192,7 +187,7 @@ public final class VideoInformation {
|
||||
* @see VideoState
|
||||
*/
|
||||
public static boolean isAtEndOfVideo() {
|
||||
return videoTime > 0 && videoLength > 0 && videoTime >= videoLength;
|
||||
return videoTime >= videoLength && videoLength > 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ public final class AdsFilter extends Filter {
|
||||
"_buttoned_layout",
|
||||
"full_width_square_image_layout",
|
||||
"_ad_with",
|
||||
"text_image_button_group_layout",
|
||||
"video_display_button_group_layout",
|
||||
"landscape_image_wide_button_layout"
|
||||
);
|
||||
|
@ -1,11 +1,11 @@
|
||||
package app.revanced.integrations.patches.components;
|
||||
|
||||
// Abuse LithoFilter for CustomVideoSpeedPatch.
|
||||
public final class VideoSpeedMenuFilterPatch extends Filter {
|
||||
// Abuse LithoFilter for CustomPlaybackSpeedPatch.
|
||||
public final class PlaybackSpeedMenuFilterPatch extends Filter {
|
||||
// Must be volatile or synchronized, as litho filtering runs off main thread and this field is then access from the main thread.
|
||||
public static volatile boolean isVideoSpeedMenuVisible;
|
||||
public static volatile boolean isPlaybackSpeedMenuVisible;
|
||||
|
||||
public VideoSpeedMenuFilterPatch() {
|
||||
public PlaybackSpeedMenuFilterPatch() {
|
||||
pathFilterGroups.addAll(new StringFilterGroup(
|
||||
null,
|
||||
"playback_speed_sheet_content.eml-js"
|
||||
@ -14,7 +14,7 @@ public final class VideoSpeedMenuFilterPatch extends Filter {
|
||||
|
||||
@Override
|
||||
boolean isFiltered(final String path, final String identifier, final byte[] protobufBufferArray) {
|
||||
isVideoSpeedMenuVisible = super.isFiltered(path, identifier, protobufBufferArray);
|
||||
isPlaybackSpeedMenuVisible = super.isFiltered(path, identifier, protobufBufferArray);
|
||||
|
||||
return false;
|
||||
}
|
@ -1,33 +1,22 @@
|
||||
package app.revanced.integrations.patches.components;
|
||||
|
||||
import android.view.View;
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import com.google.android.libraries.youtube.rendering.ui.pivotbar.PivotBar;
|
||||
|
||||
import static app.revanced.integrations.utils.ReVancedUtils.hideViewBy1dpUnderCondition;
|
||||
import static app.revanced.integrations.utils.ReVancedUtils.hideViewUnderCondition;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.os.Build;
|
||||
import android.view.View;
|
||||
|
||||
import com.google.android.libraries.youtube.rendering.ui.pivotbar.PivotBar;
|
||||
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
|
||||
public final class ShortsFilter extends Filter {
|
||||
// Set by patch.
|
||||
public static PivotBar pivotBar;
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
|
||||
final StringFilterGroupList shortsFilterGroup = new StringFilterGroupList();
|
||||
private final StringFilterGroup reelChannelBar = new StringFilterGroup(
|
||||
null,
|
||||
"reel_channel_bar"
|
||||
);
|
||||
|
||||
private final StringFilterGroup infoPanel = new StringFilterGroup(
|
||||
SettingsEnum.HIDE_SHORTS_INFO_PANEL,
|
||||
"shorts_info_panel_overview"
|
||||
);
|
||||
|
||||
public ShortsFilter() {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return;
|
||||
|
||||
final var thanksButton = new StringFilterGroup(
|
||||
SettingsEnum.HIDE_SHORTS_THANKS_BUTTON,
|
||||
"suggested_action"
|
||||
@ -48,6 +37,11 @@ public final class ShortsFilter extends Filter {
|
||||
"reel_pivot_button"
|
||||
);
|
||||
|
||||
final var infoPanel = new StringFilterGroup(
|
||||
SettingsEnum.HIDE_SHORTS_INFO_PANEL,
|
||||
"shorts_info_panel_overview"
|
||||
);
|
||||
|
||||
final var channelBar = new StringFilterGroup(
|
||||
SettingsEnum.HIDE_SHORTS_CHANNEL_BAR,
|
||||
"reel_channel_bar"
|
||||
@ -61,19 +55,20 @@ public final class ShortsFilter extends Filter {
|
||||
"shorts_video_cell"
|
||||
);
|
||||
|
||||
this.pathFilterGroups.addAll(joinButton, subscribeButton, soundButton, channelBar);
|
||||
this.identifierFilterGroups.addAll(shorts, thanksButton);
|
||||
shortsFilterGroup.addAll(soundButton, infoPanel);
|
||||
pathFilterGroups.addAll(joinButton, subscribeButton, channelBar);
|
||||
identifierFilterGroups.addAll(shorts, thanksButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isFiltered(final String path, final String identifier,
|
||||
final byte[] protobufBufferArray) {
|
||||
|
||||
// Filter the path only when reelChannelBar is visible.
|
||||
if (reelChannelBar.check(path).isFiltered())
|
||||
if (this.pathFilterGroups.contains(path)) return true;
|
||||
|
||||
// Shorts info panel path appears outside of reelChannelBar path.
|
||||
if (infoPanel.isEnabled() && infoPanel.check(path).isFiltered()) return true;
|
||||
if (shortsFilterGroup.contains(path)) return true;
|
||||
|
||||
return this.identifierFilterGroups.contains(identifier);
|
||||
}
|
||||
|
@ -13,12 +13,12 @@ import com.facebook.litho.ComponentHost;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import app.revanced.integrations.patches.components.VideoSpeedMenuFilterPatch;
|
||||
import app.revanced.integrations.patches.components.PlaybackSpeedMenuFilterPatch;
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import app.revanced.integrations.utils.LogHelper;
|
||||
import app.revanced.integrations.utils.ReVancedUtils;
|
||||
|
||||
public class CustomVideoSpeedPatch {
|
||||
public class CustomPlaybackSpeedPatch {
|
||||
/**
|
||||
* Maximum playback speed, exclusive value. Custom speeds must be less than this value.
|
||||
*/
|
||||
@ -27,17 +27,17 @@ public class CustomVideoSpeedPatch {
|
||||
/**
|
||||
* Custom playback speeds.
|
||||
*/
|
||||
public static float[] customVideoSpeeds;
|
||||
public static float[] customPlaybackSpeeds;
|
||||
|
||||
/**
|
||||
* Minimum value of {@link #customVideoSpeeds}
|
||||
* Minimum value of {@link #customPlaybackSpeeds}
|
||||
*/
|
||||
public static float minVideoSpeed;
|
||||
public static float minPlaybackSpeed;
|
||||
|
||||
/**
|
||||
* Maxium value of {@link #customVideoSpeeds}
|
||||
* Maxium value of {@link #customPlaybackSpeeds}
|
||||
*/
|
||||
public static float maxVideoSpeed;
|
||||
public static float maxPlaybackSpeed;
|
||||
|
||||
/**
|
||||
* PreferenceList entries and values, of all available playback speeds.
|
||||
@ -60,10 +60,10 @@ public class CustomVideoSpeedPatch {
|
||||
if (speedStrings.length == 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
customVideoSpeeds = new float[speedStrings.length];
|
||||
customPlaybackSpeeds = new float[speedStrings.length];
|
||||
for (int i = 0, length = speedStrings.length; i < length; i++) {
|
||||
final float speed = Float.parseFloat(speedStrings[i]);
|
||||
if (speed <= 0 || arrayContains(customVideoSpeeds, speed)) {
|
||||
if (speed <= 0 || arrayContains(customPlaybackSpeeds, speed)) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
if (speed >= MAXIMUM_PLAYBACK_SPEED) {
|
||||
@ -72,13 +72,13 @@ public class CustomVideoSpeedPatch {
|
||||
loadCustomSpeeds();
|
||||
return;
|
||||
}
|
||||
minVideoSpeed = Math.min(minVideoSpeed, speed);
|
||||
maxVideoSpeed = Math.max(maxVideoSpeed, speed);
|
||||
customVideoSpeeds[i] = speed;
|
||||
minPlaybackSpeed = Math.min(minPlaybackSpeed, speed);
|
||||
maxPlaybackSpeed = Math.max(maxPlaybackSpeed, speed);
|
||||
customPlaybackSpeeds[i] = speed;
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
LogHelper.printInfo(() -> "parse error", ex);
|
||||
resetCustomSpeeds("Invalid custom video speeds. Using default values.");
|
||||
resetCustomSpeeds("Invalid custom playback speeds. Using default values.");
|
||||
loadCustomSpeeds();
|
||||
}
|
||||
}
|
||||
@ -95,10 +95,10 @@ public class CustomVideoSpeedPatch {
|
||||
*/
|
||||
public static void initializeListPreference(ListPreference preference) {
|
||||
if (preferenceListEntries == null) {
|
||||
preferenceListEntries = new String[customVideoSpeeds.length];
|
||||
preferenceListEntryValues = new String[customVideoSpeeds.length];
|
||||
preferenceListEntries = new String[customPlaybackSpeeds.length];
|
||||
preferenceListEntryValues = new String[customPlaybackSpeeds.length];
|
||||
int i = 0;
|
||||
for (float speed : customVideoSpeeds) {
|
||||
for (float speed : customPlaybackSpeeds) {
|
||||
String speedString = String.valueOf(speed);
|
||||
preferenceListEntries[i] = speedString + "x";
|
||||
preferenceListEntryValues[i] = speedString;
|
||||
@ -115,14 +115,14 @@ public class CustomVideoSpeedPatch {
|
||||
public static void onFlyoutMenuCreate(final LinearLayout linearLayout) {
|
||||
// The playback rate menu is a RecyclerView with 2 children. The third child is the "Advanced" quality menu.
|
||||
addRecyclerListener(linearLayout, 2, 1, recyclerView -> {
|
||||
if (VideoSpeedMenuFilterPatch.isVideoSpeedMenuVisible &&
|
||||
if (PlaybackSpeedMenuFilterPatch.isPlaybackSpeedMenuVisible &&
|
||||
recyclerView.getChildCount() == 1 &&
|
||||
recyclerView.getChildAt(0) instanceof ComponentHost
|
||||
) {
|
||||
linearLayout.setVisibility(View.GONE);
|
||||
|
||||
// Close the new video speed menu and instead show the old one.
|
||||
showOldVideoSpeedMenu();
|
||||
// Close the new Playback speed menu and instead show the old one.
|
||||
showOldPlaybackSpeedMenu();
|
||||
|
||||
// DismissView [R.id.touch_outside] is the 1st ChildView of the 3rd ParentView.
|
||||
((ViewGroup) linearLayout.getParent().getParent().getParent())
|
||||
@ -131,7 +131,7 @@ public class CustomVideoSpeedPatch {
|
||||
});
|
||||
}
|
||||
|
||||
public static void showOldVideoSpeedMenu() {
|
||||
public static void showOldPlaybackSpeedMenu() {
|
||||
LogHelper.printDebug(() -> "Old video quality menu shown");
|
||||
|
||||
// Rest of the implementation added by patch.
|
@ -255,7 +255,7 @@ public class ReturnYouTubeDislike {
|
||||
// If a Short is opened while a regular video is on screen, this will incorrectly set this as false.
|
||||
// But this check is needed to fix unusual situations of opening/closing the app
|
||||
// while both a regular video and a short are on screen.
|
||||
dislikeDataIsShort = currentPlayerType.isNoneHiddenOrMinimized();
|
||||
dislikeDataIsShort = currentPlayerType.isNoneOrHidden();
|
||||
|
||||
RYDCachedFetch entry = futureCache.get(videoId);
|
||||
if (entry != null && entry.futureInProgressOrFinishedSuccessfully()) {
|
||||
@ -371,7 +371,7 @@ public class ReturnYouTubeDislike {
|
||||
// Must make a local copy of videoId, since it may change between now and when the vote thread runs.
|
||||
String videoIdToVoteFor = getCurrentVideoId();
|
||||
if (videoIdToVoteFor == null ||
|
||||
(SettingsEnum.RYD_SHORTS.getBoolean() && dislikeDataIsShort != PlayerType.getCurrent().isNoneHiddenOrMinimized())) {
|
||||
(SettingsEnum.RYD_SHORTS.getBoolean() && dislikeDataIsShort != PlayerType.getCurrent().isNoneOrHidden())) {
|
||||
// User enabled RYD after starting playback of a video.
|
||||
// Or shorts was loaded with regular video present, then shorts was closed,
|
||||
// and then user voted on the now visible original video.
|
||||
|
@ -152,7 +152,8 @@ public enum SettingsEnum {
|
||||
EXTERNAL_BROWSER("revanced_external_browser", BOOLEAN, TRUE, true),
|
||||
AUTO_REPEAT("revanced_auto_repeat", BOOLEAN, FALSE),
|
||||
SEEKBAR_TAPPING("revanced_seekbar_tapping", BOOLEAN, TRUE),
|
||||
SPOOF_SIGNATURE_VERIFICATION("revanced_spoof_signature_verification", BOOLEAN, TRUE, "revanced_spoof_signature_verification_user_dialog_message"),
|
||||
SPOOF_SIGNATURE_VERIFICATION("revanced_spoof_signature_verification", BOOLEAN, TRUE, true,
|
||||
"revanced_spoof_signature_verification_user_dialog_message"),
|
||||
|
||||
// Swipe controls
|
||||
SWIPE_BRIGHTNESS("revanced_swipe_brightness", BOOLEAN, TRUE),
|
||||
|
@ -24,7 +24,7 @@ import androidx.annotation.Nullable;
|
||||
|
||||
import com.google.android.apps.youtube.app.application.Shell_HomeActivity;
|
||||
|
||||
import app.revanced.integrations.patches.playback.speed.CustomVideoSpeedPatch;
|
||||
import app.revanced.integrations.patches.playback.speed.CustomPlaybackSpeedPatch;
|
||||
import app.revanced.integrations.settings.SettingsEnum;
|
||||
import app.revanced.integrations.settings.SharedPrefCategory;
|
||||
import app.revanced.integrations.utils.LogHelper;
|
||||
@ -135,7 +135,7 @@ public class ReVancedSettingsFragment extends PreferenceFragment {
|
||||
// if the preference was included, then initialize it based on the available playback speed
|
||||
Preference defaultSpeedPreference = findPreference(SettingsEnum.PLAYBACK_SPEED_DEFAULT.path);
|
||||
if (defaultSpeedPreference instanceof ListPreference) {
|
||||
CustomVideoSpeedPatch.initializeListPreference((ListPreference) defaultSpeedPreference);
|
||||
CustomPlaybackSpeedPatch.initializeListPreference((ListPreference) defaultSpeedPreference);
|
||||
}
|
||||
|
||||
// Set current value from SettingsEnum
|
||||
|
@ -18,7 +18,7 @@ enum class PlayerType {
|
||||
HIDDEN,
|
||||
/**
|
||||
* When spoofing to 16.x YouTube and watching a short with a regular video in the background,
|
||||
* the type will be this (and not [HIDDEN]).
|
||||
* the type can be this (and not [HIDDEN]).
|
||||
*/
|
||||
WATCH_WHILE_MINIMIZED,
|
||||
WATCH_WHILE_MAXIMIZED,
|
||||
|
@ -58,6 +58,7 @@ public class SegmentPlaybackController {
|
||||
/**
|
||||
* Because loading can take time, show the skip to highlight for a few seconds after the segments load.
|
||||
* This is the system time (in milliseconds) to no longer show the initial display skip to highlight.
|
||||
* Value will be zero if no highlight segment exists, or if the system time to show the highlight has passed.
|
||||
*/
|
||||
private static long highlightSegmentInitialShowEndTime;
|
||||
|
||||
@ -198,7 +199,7 @@ public class SegmentPlaybackController {
|
||||
return;
|
||||
}
|
||||
if (PlayerType.getCurrent().isNoneOrHidden()) {
|
||||
LogHelper.printDebug(() -> "ignoring short or story");
|
||||
LogHelper.printDebug(() -> "ignoring Short");
|
||||
return;
|
||||
}
|
||||
if (!ReVancedUtils.isNetworkConnected()) {
|
||||
@ -238,14 +239,20 @@ public class SegmentPlaybackController {
|
||||
setSegments(segments);
|
||||
|
||||
final long videoTime = VideoInformation.getVideoTime();
|
||||
// if the current video time is before the highlight
|
||||
if (highlightSegment != null && videoTime < highlightSegment.end) {
|
||||
if (highlightSegment.shouldAutoSkip()) {
|
||||
skipSegment(highlightSegment, false);
|
||||
return;
|
||||
if (highlightSegment != null) {
|
||||
// If the current video time is before the highlight.
|
||||
final long timeUntilHighlight = highlightSegment.start - videoTime;
|
||||
if (timeUntilHighlight > 0) {
|
||||
if (highlightSegment.shouldAutoSkip()) {
|
||||
skipSegment(highlightSegment, false);
|
||||
return;
|
||||
}
|
||||
highlightSegmentInitialShowEndTime = System.currentTimeMillis() + Math.min(
|
||||
(long) (timeUntilHighlight / VideoInformation.getPlaybackSpeed()),
|
||||
DURATION_TO_SHOW_SKIP_BUTTON);
|
||||
}
|
||||
highlightSegmentInitialShowEndTime = System.currentTimeMillis() + DURATION_TO_SHOW_SKIP_BUTTON;
|
||||
}
|
||||
|
||||
// check for any skips now, instead of waiting for the next update to setVideoTime()
|
||||
setVideoTime(videoTime);
|
||||
});
|
||||
@ -262,7 +269,7 @@ public class SegmentPlaybackController {
|
||||
public static void setVideoTime(long millis) {
|
||||
try {
|
||||
if (!SettingsEnum.SB_ENABLED.getBoolean()
|
||||
|| PlayerType.getCurrent().isNoneOrHidden() // shorts playback
|
||||
|| PlayerType.getCurrent().isNoneOrHidden() // Shorts playback.
|
||||
|| segments == null || segments.length == 0) {
|
||||
return;
|
||||
}
|
||||
@ -270,11 +277,17 @@ public class SegmentPlaybackController {
|
||||
|
||||
updateHiddenSegments(millis);
|
||||
|
||||
// to debug the timing logic, set this to a very large value (5000 or more)
|
||||
// then try manually seeking just playback reaches a skip/hide of different segments
|
||||
final long lookAheadMilliseconds = 1500; // must be larger than the average time between calls to this method
|
||||
final float playbackSpeed = VideoInformation.getPlaybackSpeed();
|
||||
final long startTimerLookAheadThreshold = millis + (long)(playbackSpeed * lookAheadMilliseconds);
|
||||
// Amount of time to look ahead for the next segment,
|
||||
// and the threshold to determine if a scheduled show/hide is at the correct video time when it's run.
|
||||
//
|
||||
// This value must be greater than largest time between calls to this method (1000ms),
|
||||
// and must be adjusted for the video speed.
|
||||
//
|
||||
// To debug the stale skip logic, set this to a very large value (5000 or more)
|
||||
// then try manually seeking just before playback reaches a segment skip.
|
||||
final long speedAdjustedTimeThreshold = (long)(playbackSpeed * 1200);
|
||||
final long startTimerLookAheadThreshold = millis + speedAdjustedTimeThreshold;
|
||||
|
||||
SponsorSegment foundSegmentCurrentlyPlaying = null;
|
||||
SponsorSegment foundUpcomingSegment = null;
|
||||
@ -344,9 +357,11 @@ public class SegmentPlaybackController {
|
||||
}
|
||||
|
||||
if (highlightSegment != null) {
|
||||
if (millis < DURATION_TO_SHOW_SKIP_BUTTON || System.currentTimeMillis() < highlightSegmentInitialShowEndTime) {
|
||||
if (millis < DURATION_TO_SHOW_SKIP_BUTTON || (highlightSegmentInitialShowEndTime != 0
|
||||
&& System.currentTimeMillis() < highlightSegmentInitialShowEndTime)) {
|
||||
SponsorBlockViewController.showSkipHighlightButton(highlightSegment);
|
||||
} else {
|
||||
highlightSegmentInitialShowEndTime = 0;
|
||||
SponsorBlockViewController.hideSkipHighlightButton();
|
||||
}
|
||||
}
|
||||
@ -361,12 +376,9 @@ public class SegmentPlaybackController {
|
||||
SponsorBlockViewController.hideSkipSegmentButton();
|
||||
}
|
||||
|
||||
// must be greater than the average time between updates to VideoInformation time
|
||||
final long videoInformationTimeUpdateThresholdMilliseconds = 250;
|
||||
|
||||
// schedule a hide, only if the segment end is near
|
||||
final SponsorSegment segmentToHide =
|
||||
(foundSegmentCurrentlyPlaying != null && foundSegmentCurrentlyPlaying.endIsNear(millis, lookAheadMilliseconds))
|
||||
(foundSegmentCurrentlyPlaying != null && foundSegmentCurrentlyPlaying.endIsNear(millis, speedAdjustedTimeThreshold))
|
||||
? foundSegmentCurrentlyPlaying
|
||||
: null;
|
||||
|
||||
@ -384,9 +396,13 @@ public class SegmentPlaybackController {
|
||||
return;
|
||||
}
|
||||
scheduledHideSegment = null;
|
||||
if (VideoState.getCurrent() != VideoState.PLAYING) {
|
||||
LogHelper.printDebug(() -> "Ignoring scheduled hide segment as video is paused: " + segmentToHide);
|
||||
return;
|
||||
}
|
||||
|
||||
final long videoTime = VideoInformation.getVideoTime();
|
||||
if (!segmentToHide.endIsNear(videoTime, videoInformationTimeUpdateThresholdMilliseconds)) {
|
||||
if (!segmentToHide.endIsNear(videoTime, speedAdjustedTimeThreshold)) {
|
||||
// current video time is not what's expected. User paused playback
|
||||
LogHelper.printDebug(() -> "Ignoring outdated scheduled hide: " + segmentToHide
|
||||
+ " videoInformation time: " + videoTime);
|
||||
@ -419,10 +435,13 @@ public class SegmentPlaybackController {
|
||||
return;
|
||||
}
|
||||
scheduledUpcomingSegment = null;
|
||||
if (VideoState.getCurrent() != VideoState.PLAYING) {
|
||||
LogHelper.printDebug(() -> "Ignoring scheduled hide segment as video is paused: " + segmentToSkip);
|
||||
return;
|
||||
}
|
||||
|
||||
final long videoTime = VideoInformation.getVideoTime();
|
||||
if (!segmentToSkip.startIsNear(videoTime,
|
||||
videoInformationTimeUpdateThresholdMilliseconds)) {
|
||||
if (!segmentToSkip.startIsNear(videoTime, speedAdjustedTimeThreshold)) {
|
||||
// current video time is not what's expected. User paused playback
|
||||
LogHelper.printDebug(() -> "Ignoring outdated scheduled segment: " + segmentToSkip
|
||||
+ " videoInformation time: " + videoTime);
|
||||
@ -488,10 +507,10 @@ public class SegmentPlaybackController {
|
||||
SponsorBlockViewController.hideSkipHighlightButton();
|
||||
SponsorBlockViewController.hideSkipSegmentButton();
|
||||
|
||||
// If trying to seek to end of the video, YouTube can seek just short of the actual end.
|
||||
// If trying to seek to end of the video, YouTube can seek just before of the actual end.
|
||||
// (especially if the video does not end on a whole second boundary).
|
||||
// This causes additional segment skip attempts, even though it cannot seek any closer to the desired time.
|
||||
// Check for and ignore repeated skip attempts of the same segment over a short time period.
|
||||
// Check for and ignore repeated skip attempts of the same segment over a small time period.
|
||||
final long now = System.currentTimeMillis();
|
||||
final long minimumMillisecondsBetweenSkippingSameSegment = 500;
|
||||
if ((lastSegmentSkipped == segmentToSkip) && (now - lastSegmentSkippedTime < minimumMillisecondsBetweenSkippingSameSegment)) {
|
||||
|
@ -6,36 +6,65 @@ import android.preference.PreferenceFragment;
|
||||
import android.view.View;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import com.bytedance.ies.ugc.aweme.commercialize.compliance.personalization.AdPersonalizationActivity;
|
||||
|
||||
import app.revanced.tiktok.utils.LogHelper;
|
||||
import app.revanced.tiktok.utils.ReVancedUtils;
|
||||
import com.bytedance.ies.ugc.aweme.commercialize.compliance.personalization.AdPersonalizationActivity;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
|
||||
public class SettingsMenu {
|
||||
public static void initializeSettings(AdPersonalizationActivity base) {
|
||||
public static Object createSettingsEntry(String entryClazzName, String entryInfoClazzName) {
|
||||
try {
|
||||
Class<?> entryClazz = Class.forName(entryClazzName);
|
||||
Class<?> entryInfoClazz = Class.forName(entryInfoClazzName);
|
||||
Constructor<?> entryConstructor = entryClazz.getConstructor(entryInfoClazz);
|
||||
Constructor<?> entryInfoConstructor = entryInfoClazz.getDeclaredConstructors()[0];
|
||||
Object buttonInfo = entryInfoConstructor.newInstance("Revanced settings", null, (View.OnClickListener) view -> startSettingsActivity());
|
||||
return entryConstructor.newInstance(buttonInfo);
|
||||
} catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | IllegalAccessException |
|
||||
InstantiationException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/***
|
||||
* Initialize the settings menu.
|
||||
* @param base The activity to initialize the settings menu on.
|
||||
* @return Whether the settings menu should be initialized.
|
||||
*/
|
||||
public static boolean initializeSettings(AdPersonalizationActivity base) {
|
||||
if (!base.getIntent().getExtras().getBoolean("revanced", false)) return false;
|
||||
|
||||
SettingsStatus.load();
|
||||
|
||||
LinearLayout linearLayout = new LinearLayout(base);
|
||||
linearLayout.setLayoutParams(new LinearLayout.LayoutParams(-1, -1));
|
||||
linearLayout.setOrientation(LinearLayout.VERTICAL);
|
||||
linearLayout.setFitsSystemWindows(true);
|
||||
linearLayout.setTransitionGroup(true);
|
||||
|
||||
FrameLayout fragment = new FrameLayout(base);
|
||||
fragment.setLayoutParams(new FrameLayout.LayoutParams(-1, -1));
|
||||
int fragmentId = View.generateViewId();
|
||||
fragment.setId(fragmentId);
|
||||
|
||||
linearLayout.addView(fragment);
|
||||
base.setContentView(linearLayout);
|
||||
|
||||
PreferenceFragment preferenceFragment = new ReVancedSettingsFragment();
|
||||
base.getFragmentManager().beginTransaction().replace(fragmentId, preferenceFragment).commit();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void startSettingsActivity() {
|
||||
private static void startSettingsActivity() {
|
||||
Context appContext = ReVancedUtils.getAppContext();
|
||||
if (appContext != null) {
|
||||
Intent intent = new Intent(appContext, AdPersonalizationActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.putExtra("revanced", true);
|
||||
appContext.startActivity(intent);
|
||||
} else {
|
||||
LogHelper.debug(SettingsMenu.class, "ReVancedUtils.getAppContext() return null");
|
||||
|
@ -1,4 +1,4 @@
|
||||
org.gradle.parallel = true
|
||||
org.gradle.caching = true
|
||||
android.useAndroidX = true
|
||||
version = 0.112.0
|
||||
version = 0.113.0-dev.5
|
||||
|
Loading…
Reference in New Issue
Block a user