chore: merge branch dev to main (#437)

This commit is contained in:
oSumAtrIX 2023-07-20 02:02:44 +02:00 committed by GitHub
commit 59f7733f99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 220 additions and 100 deletions

View File

@ -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)

View File

@ -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;

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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"
);

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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.

View File

@ -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.

View File

@ -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),

View File

@ -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

View File

@ -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,

View File

@ -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)) {

View File

@ -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");

View File

@ -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