From b5d712a3326d1e8cdb8d8642aa7bd1bee6e30ac1 Mon Sep 17 00:00:00 2001 From: LisoUseInAIKyrios <118716522+LisoUseInAIKyrios@users.noreply.github.com> Date: Sun, 2 Apr 2023 18:10:26 +0400 Subject: [PATCH] feat(youtube): sponsorblock improvements (#1557) Co-authored-by: oSumAtrIX --- .../NextGenWatchLayoutFingerprint.kt | 10 - .../patch/SponsorBlockBytecodePatch.kt | 74 +++-- .../patch/VideoInformationPatch.kt | 5 +- .../host/values/strings.xml | 1 + .../sponsorblock/drawable/ic_sb_voting.xml | 10 +- .../host/layout/youtube_controls_layout.xml | 30 +- .../sponsorblock/host/values/strings.xml | 291 ++++++++++-------- .../layout/inline_sponsor_overlay.xml | 22 +- .../sponsorblock/layout/new_segment.xml | 106 +++---- .../layout/skip_sponsor_button.xml | 37 ++- 10 files changed, 346 insertions(+), 240 deletions(-) delete mode 100644 src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/NextGenWatchLayoutFingerprint.kt diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/NextGenWatchLayoutFingerprint.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/NextGenWatchLayoutFingerprint.kt deleted file mode 100644 index d17333720..000000000 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/fingerprints/NextGenWatchLayoutFingerprint.kt +++ /dev/null @@ -1,10 +0,0 @@ -package app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints - - -import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint -import org.jf.dexlib2.util.MethodUtil - -object NextGenWatchLayoutFingerprint : MethodFingerprint( - "V", // constructors return void, in favour of speed of matching, this fingerprint has been added - customFingerprint = { methodDef -> MethodUtil.isConstructor(methodDef) && methodDef.parameterTypes.size == 3 && methodDef.definingClass.endsWith("NextGenWatchLayout;") } -) \ No newline at end of file diff --git a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/patch/SponsorBlockBytecodePatch.kt b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/patch/SponsorBlockBytecodePatch.kt index b7e775ca2..e147ce4d1 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/patch/SponsorBlockBytecodePatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/layout/sponsorblock/bytecode/patch/SponsorBlockBytecodePatch.kt @@ -1,5 +1,6 @@ package app.revanced.patches.youtube.layout.sponsorblock.bytecode.patch +import app.revanced.extensions.toErrorResult import app.revanced.patcher.annotation.Description import app.revanced.patcher.annotation.Name import app.revanced.patcher.annotation.Version @@ -22,10 +23,13 @@ import app.revanced.patches.shared.mapping.misc.patch.ResourceMappingPatch import app.revanced.patches.youtube.layout.sponsorblock.annotations.SponsorBlockCompatibility import app.revanced.patches.youtube.layout.sponsorblock.bytecode.fingerprints.* import app.revanced.patches.youtube.layout.sponsorblock.resource.patch.SponsorBlockResourcePatch +import app.revanced.patches.youtube.misc.autorepeat.fingerprints.AutoRepeatFingerprint +import app.revanced.patches.youtube.misc.autorepeat.fingerprints.AutoRepeatParentFingerprint import app.revanced.patches.youtube.misc.integrations.patch.IntegrationsPatch import app.revanced.patches.youtube.misc.playercontrols.bytecode.patch.PlayerControlsBytecodePatch import app.revanced.patches.youtube.misc.playertype.patch.PlayerTypeHookPatch import app.revanced.patches.youtube.misc.video.information.patch.VideoInformationPatch +import app.revanced.patches.youtube.misc.video.speed.remember.patch.RememberPlaybackSpeedPatch import app.revanced.patches.youtube.misc.video.videoid.patch.VideoIdPatch import org.jf.dexlib2.Opcode import org.jf.dexlib2.iface.instruction.* @@ -38,11 +42,12 @@ import org.jf.dexlib2.iface.reference.StringReference @DependsOn( dependencies = [ VideoInformationPatch::class, // updates video information and adds method to seek in video + VideoIdPatch::class, PlayerControlsBytecodePatch::class, PlayerTypeHookPatch::class, + RememberPlaybackSpeedPatch::class, IntegrationsPatch::class, SponsorBlockResourcePatch::class, - VideoIdPatch::class ] ) @Name("sponsorblock") @@ -52,15 +57,21 @@ import org.jf.dexlib2.iface.reference.StringReference class SponsorBlockBytecodePatch : BytecodePatch( listOf( SeekbarFingerprint, - NextGenWatchLayoutFingerprint, AppendTimeFingerprint, PlayerOverlaysLayoutInitFingerprint, + AutoRepeatParentFingerprint, ) ) { private companion object { - const val INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR = - "Lapp/revanced/integrations/sponsorblock/PlayerController;" + const val INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR = + "Lapp/revanced/integrations/sponsorblock/SegmentPlaybackController;" + const val INTEGRATIONS_CREATE_SEGMENT_BUTTON_CONTROLLER_CLASS_DESCRIPTOR = + "Lapp/revanced/integrations/sponsorblock/ui/CreateSegmentButtonController;" + const val INTEGRATIONS_VOTING_BUTTON_CONTROLLER_CLASS_DESCRIPTOR = + "Lapp/revanced/integrations/sponsorblock/ui/VotingButtonController;" + const val INTEGRATIONS_SPONSORBLOCK_VIEW_CONTROLLER_CLASS_DESCRIPTOR = + "Lapp/revanced/integrations/sponsorblock/ui/SponsorBlockViewController;" } override fun execute(context: BytecodeContext): PatchResult { @@ -69,19 +80,15 @@ class SponsorBlockBytecodePatch : BytecodePatch( */ with(VideoInformationPatch) { videoTimeHook( - INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR, + INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR, "setVideoTime" ) - highPrecisionTimeHook( - INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR, - "setHighPrecisionVideoTime" - ) } /* Set current video id */ - VideoIdPatch.injectCallBackgroundPlay("$INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->setCurrentVideoId(Ljava/lang/String;)V") + VideoIdPatch.injectCallBackgroundPlay("$INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setCurrentVideoId(Ljava/lang/String;)V") /* Seekbar drawing @@ -99,7 +106,7 @@ class SponsorBlockBytecodePatch : BytecodePatch( if (instruction.opcode != Opcode.MOVE_OBJECT_FROM16) continue seekbarMethod.addInstruction( index + 1, - "invoke-static/range {p0 .. p0}, $INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarRect(Ljava/lang/Object;)V" + "invoke-static/range {p0 .. p0}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarRect(Ljava/lang/Object;)V" ) break } @@ -115,7 +122,7 @@ class SponsorBlockBytecodePatch : BytecodePatch( // set the thickness of the segment seekbarMethod.addInstruction( insertIndex, - "invoke-static {v${invokeInstruction.registerC}}, $INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarThickness(I)V" + "invoke-static {v${invokeInstruction.registerC}}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarThickness(I)V" ) break } @@ -136,11 +143,11 @@ class SponsorBlockBytecodePatch : BytecodePatch( // the reason for that is that we get the index, add instructions and then the offset would be wrong seekbarMethod.addInstruction( indexLeft + 1, - "invoke-static {v$rectangleLeftRegister}, $INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarAbsoluteLeft(Landroid/graphics/Rect;)V" + "invoke-static {v$rectangleLeftRegister}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarAbsoluteLeft(Landroid/graphics/Rect;)V" ) seekbarMethod.addInstruction( indexRight + 1, - "invoke-static {v$rectangleRightRegister}, $INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarAbsoluteRight(Landroid/graphics/Rect;)V" + "invoke-static {v$rectangleRightRegister}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->setSponsorBarAbsoluteRight(Landroid/graphics/Rect;)V" ) /* @@ -152,7 +159,7 @@ class SponsorBlockBytecodePatch : BytecodePatch( } seekbarMethod.addInstruction( drawSegmentInstructionInsertIndex, - "invoke-static {v$canvasInstance, v$centerY}, $INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->drawSponsorTimeBars(Landroid/graphics/Canvas;F)V" + "invoke-static {v$canvasInstance, v$centerY}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->drawSponsorTimeBars(Landroid/graphics/Canvas;F)V" ) /* @@ -181,8 +188,8 @@ class SponsorBlockBytecodePatch : BytecodePatch( method.addInstructions( moveResultInstructionIndex + 1, // insert right after moving the view to the register and use that register """ - invoke-static {v$inflatedViewRegister}, Lapp/revanced/integrations/sponsorblock/ShieldButton;->initialize(Ljava/lang/Object;)V - invoke-static {v$inflatedViewRegister}, Lapp/revanced/integrations/sponsorblock/VotingButton;->initialize(Ljava/lang/Object;)V + invoke-static {v$inflatedViewRegister}, $INTEGRATIONS_CREATE_SEGMENT_BUTTON_CONTROLLER_CLASS_DESCRIPTOR->initialize(Ljava/lang/Object;)V + invoke-static {v$inflatedViewRegister}, $INTEGRATIONS_VOTING_BUTTON_CONTROLLER_CLASS_DESCRIPTOR->initialize(Ljava/lang/Object;)V """ ) } @@ -193,8 +200,8 @@ class SponsorBlockBytecodePatch : BytecodePatch( // change visibility of the buttons invertVisibilityMethod.addInstructions( 0, """ - invoke-static {p1}, Lapp/revanced/integrations/sponsorblock/ShieldButton;->changeVisibilityNegatedImmediate(Z)V - invoke-static {p1}, Lapp/revanced/integrations/sponsorblock/VotingButton;->changeVisibilityNegatedImmediate(Z)V + invoke-static {p1}, $INTEGRATIONS_CREATE_SEGMENT_BUTTON_CONTROLLER_CLASS_DESCRIPTOR->changeVisibilityNegatedImmediate(Z)V + invoke-static {p1}, $INTEGRATIONS_VOTING_BUTTON_CONTROLLER_CLASS_DESCRIPTOR->changeVisibilityNegatedImmediate(Z)V """.trimIndent() ) } @@ -203,15 +210,8 @@ class SponsorBlockBytecodePatch : BytecodePatch( } // change visibility of the buttons - PlayerControlsBytecodePatch.injectVisibilityCheckCall("Lapp/revanced/integrations/sponsorblock/ShieldButton;->changeVisibility(Z)V") - PlayerControlsBytecodePatch.injectVisibilityCheckCall("Lapp/revanced/integrations/sponsorblock/VotingButton;->changeVisibility(Z)V") - - // set SegmentHelperLayout.context to the player layout instance - val instanceRegister = 0 - NextGenWatchLayoutFingerprint.result!!.mutableMethod.addInstruction( - 3, // after super call - "invoke-static/range {p$instanceRegister}, $INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR->addSkipSponsorView15(Landroid/view/View;)V" - ) + PlayerControlsBytecodePatch.injectVisibilityCheckCall("$INTEGRATIONS_CREATE_SEGMENT_BUTTON_CONTROLLER_CLASS_DESCRIPTOR->changeVisibility(Z)V") + PlayerControlsBytecodePatch.injectVisibilityCheckCall("$INTEGRATIONS_VOTING_BUTTON_CONTROLLER_CLASS_DESCRIPTOR->changeVisibility(Z)V") // append the new time to the player layout val appendTimeFingerprintResult = AppendTimeFingerprint.result!! @@ -221,18 +221,18 @@ class SponsorBlockBytecodePatch : BytecodePatch( appendTimeFingerprintResult.mutableMethod.addInstructions( appendTimePatternScanStartIndex + 2, """ - invoke-static {v$targetRegister}, Lapp/revanced/integrations/sponsorblock/SponsorBlockUtils;->appendTimeWithoutSegments(Ljava/lang/String;)Ljava/lang/String; + invoke-static {v$targetRegister}, $INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR->appendTimeWithoutSegments(Ljava/lang/String;)Ljava/lang/String; move-result-object v$targetRegister """ ) // initialize the player controller - VideoInformationPatch.onCreateHook(INTEGRATIONS_PLAYER_CONTROLLER_CLASS_DESCRIPTOR, "initialize") + VideoInformationPatch.onCreateHook(INTEGRATIONS_SEGMENT_PLAYBACK_CONTROLLER_CLASS_DESCRIPTOR, "initialize") // initialize the sponsorblock view PlayerOverlaysLayoutInitFingerprint.result!!.mutableMethod.addInstruction( 6, // after inflating the view - "invoke-static {p0}, Lapp/revanced/integrations/sponsorblock/player/ui/SponsorBlockView;->initialize(Ljava/lang/Object;)V" + "invoke-static {p0}, $INTEGRATIONS_SPONSORBLOCK_VIEW_CONTROLLER_CLASS_DESCRIPTOR->initialize(Ljava/lang/Object;)V" ) // get rectangle field name @@ -244,7 +244,7 @@ class SponsorBlockBytecodePatch : BytecodePatch( // replace the "replaceMeWith*" strings context - .proxy(context.classes.first { it.type.endsWith("PlayerController;") }) + .proxy(context.classes.first { it.type.endsWith("SegmentPlaybackController;") }) .mutableClass .methods .find { it.name == "setSponsorBarRect" } @@ -268,6 +268,16 @@ class SponsorBlockBytecodePatch : BytecodePatch( } } ?: return PatchResultError("Could not find the method which contains the replaceMeWith* strings") + + // detect end of the video has been reached + AutoRepeatParentFingerprint.result ?: return AutoRepeatParentFingerprint.toErrorResult() + AutoRepeatFingerprint.also { + it.resolve(context, AutoRepeatParentFingerprint.result!!.classDef) + }.result?.mutableMethod?.addInstruction( + 0, + "invoke-static {}, $INTEGRATIONS_SPONSORBLOCK_VIEW_CONTROLLER_CLASS_DESCRIPTOR->endOfVideoReached()V" + ) ?: return AutoRepeatFingerprint.toErrorResult() + // TODO: isSBChannelWhitelisting implementation return PatchResultSuccess() diff --git a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/patch/VideoInformationPatch.kt b/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/patch/VideoInformationPatch.kt index 83a9333a0..7ae872218 100644 --- a/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/patch/VideoInformationPatch.kt +++ b/src/main/kotlin/app/revanced/patches/youtube/misc/video/information/patch/VideoInformationPatch.kt @@ -122,7 +122,7 @@ class VideoInformationPatch : BytecodePatch( /* Hook the methods which set the time */ - highPrecisionTimeHook(INTEGRATIONS_CLASS_DESCRIPTOR, "setVideoTime") + highPrecisionTimeHook(INTEGRATIONS_CLASS_DESCRIPTOR, "setVideoTimeHighPrecision") return PatchResultSuccess() } @@ -155,6 +155,7 @@ class VideoInformationPatch : BytecodePatch( /** * Hook the video time. + * The hook is usually called once per second. * * @param targetMethodClass The descriptor for the static method to invoke when the player controller is created. * @param targetMethodName The name of the static method to invoke when the player controller is created. @@ -167,6 +168,8 @@ class VideoInformationPatch : BytecodePatch( /** * Hook the high precision video time. + * The hooks is called extremely often (10 to 15 times a seconds), so use with caution. + * Note: the hook is usually called _off_ the main thread * * @param targetMethodClass The descriptor for the static method to invoke when the player controller is created. * @param targetMethodName The name of the static method to invoke when the player controller is created. diff --git a/src/main/resources/returnyoutubedislike/host/values/strings.xml b/src/main/resources/returnyoutubedislike/host/values/strings.xml index e97bbbc1f..31ca93597 100644 --- a/src/main/resources/returnyoutubedislike/host/values/strings.xml +++ b/src/main/resources/returnyoutubedislike/host/values/strings.xml @@ -21,6 +21,7 @@ Like button styled for minimum width Like button styled for best appearance + About ReturnYouTubeDislike.com Dislike data is provided by the Return YouTube Dislike API. Tap here to learn more. diff --git a/src/main/resources/sponsorblock/drawable/ic_sb_voting.xml b/src/main/resources/sponsorblock/drawable/ic_sb_voting.xml index 97db9c98d..30224f149 100644 --- a/src/main/resources/sponsorblock/drawable/ic_sb_voting.xml +++ b/src/main/resources/sponsorblock/drawable/ic_sb_voting.xml @@ -1,9 +1,9 @@ - + android:height="24dp" + android:tint="#FFFFFF" + android:viewportWidth="24" + android:viewportHeight="24"> diff --git a/src/main/resources/sponsorblock/host/layout/youtube_controls_layout.xml b/src/main/resources/sponsorblock/host/layout/youtube_controls_layout.xml index 97796266a..33a11b83b 100644 --- a/src/main/resources/sponsorblock/host/layout/youtube_controls_layout.xml +++ b/src/main/resources/sponsorblock/host/layout/youtube_controls_layout.xml @@ -1,4 +1,28 @@ - - - + + + + + diff --git a/src/main/resources/sponsorblock/host/values/strings.xml b/src/main/resources/sponsorblock/host/values/strings.xml index 2f4838352..3d6ef38c7 100644 --- a/src/main/resources/sponsorblock/host/values/strings.xml +++ b/src/main/resources/sponsorblock/host/values/strings.xml @@ -1,142 +1,173 @@ - Enable SponsorBlock - SponsorBlock is a crowd-sourced system for skipping annoying parts in YouTube videos - Enable new segment adding - Switch this on to enable experimental segment adding (has button visibility issues) - What to do with different segments - General - Show a toast when skipping segment automatically - Click to see an example toast - Skip count tracking - This lets SponsorBlock leaderboard system know how much time people have saved. The extension sends a message to the server each time you skip a segment - Adjusting new segment step - This is the number of milliseconds you can move when you use the time adjustment buttons while adding new segment - Minimum segment duration - Segments shorter than the set value (in seconds) will not be skipped or shown in the player - Your private user id - This should be kept private. This is like a password and should not be shared with anyone. If someone has this, they can impersonate you - Import/Export settings - This is your entire configuration that is applicable in the desktop extension in JSON. This includes your Private userID, so be sure to share this wisely. - Change API URL - The address SponsorBlock uses to make calls to the server. <b>Don\'t change this unless you know what you\'re doing.</b> - Settings were successfully imported - Failed to import settings - Failed to export settings - Cache segments locally - Frequently watched videos (eg. music videos) may store segments in app cache to make skipping segments faster - Clear SponsorBlock segments cache - Sponsor - Paid promotion, paid referrals and direct advertisements - Intermission/Intro Animation - An interval without actual content. Could be a pause, static frame, repeating animation - Endcards/Credits - Credits or when the YouTube endcards appear. Not for spoken conclusions - Interaction Reminder (Subscribe) - When there is a short reminder to like, subscribe, follow or interact with them on any free or paid platform - Unpaid/Self Promotion - When there is unpaid or self promotion. This includes specific sections about merchandise, donations, or information about who they collaborated with - Music: Non-Music Section - Only for use in music videos. Skips parts of the video not in official mixes - Filler Tangent/Jokes - Tangential scenes added only for filler or humor that are not required to understand the main content of the video. This should not include context or background details - Skipped a sponsor segment - Skipped sponsor - Skipped intro - Skipped outro - Skipped annoying reminder - Skipped self promotion - Skipped a non-music section - Skipped preview - Skipped filler - Skipped unsubmitted segment - Skip automatically - Skip automatically once - Show a skip button - Don\'t do anything - Skip segment - About - This app uses the API from SponsorBlock - Tap to learn more, and see downloads for other platforms at: sponsor.ajay.app - Integration made by JakubWeg, recoded by oSumAtrIX - Tap to skip + Enable SponsorBlock + SponsorBlock is a crowd-sourced system for skipping annoying parts of YouTube videos + Show voting button + Segment voting button is shown + Segment voting button is not shown + Show create new segment button + Create new segment button is shown + Create new segment button is not shown + Use compact skip button + Skip button styled for minimum width + Skip button styled for best appearance + What to do with different segments + General + Show a toast when skipping segment automatically + Toast shown when a segment is automatically skipped. Tap here to see an example + Toast not shown. Tap here to see an example + Enable skip count tracking + Lets the SponsorBlock leaderboard know how much time is saved. A message is sent to the leaderboard each time a segment is skipped + Skip count tracking is not enabled + Show video length without segments + Video length minus all segments, shown in parentheses next to the full video length + Full video length shown + Adjust new segment step + Number of milliseconds the time adjustment buttons move when creating new segments + Value must be a positive number + Minimum segment duration + Segments shorter than this value (in seconds) will not be shown or skipped + Your private user id + This should be kept private. This is like a password and should not be shared with anyone. If someone has this, they can impersonate you + User id cannot be blank + Import/Export settings + Your SponsorBlock JSON configuration that can be imported/exported to ReVanced and other SponsorBlock platforms. This includes your private user id. Be sure to share this wisely + Change API URL + The address SponsorBlock uses to make calls to the server. <b>Don\'t change this unless you know what you\'re doing</b> + Settings imported successfully + Failed to import: %s + Failed to export settings (try clearing app data) - Can\'t submit the segment: %s - Unable to submit segments: Status: %d %s - Can\'t submit the segment.\nRate Limited (Too many from the same user or IP) - Can\'t submit the segment.\n\n%s - Can\'t submit the segment.\nAlready exists - Segment submitted successfully - Submitting segment… + Sponsor + Paid promotion, paid referrals and direct advertisements. Not for self-promotion or free shout-outs to causes/creators/websites/products they like + Unpaid/Self Promotion + Similar to \'Sponsor\' except for unpaid or self promotion. Includes sections about merchandise, donations, or information about who they collaborated with + Interaction Reminder (Subscribe) + A short reminder to like, subscribe or follow them in the middle of content. If it is long or about something specific, it should instead be under self promotion + Intermission/Intro Animation + An interval without actual content. Could be a pause, static frame, or repeating animation. Does not include transitions containing information + Endcards/Credits + Credits or when the YouTube endcards appear. Not for conclusions with information + Preview/Recap + Collection of clips that show what is coming up or what happened in the video or in other videos of a series, where all information is repeated elsewhere + Filler Tangent/Jokes + Tangential scenes added only for filler or humor that are not required to understand the main content of the video. Does not include segments providing context or background details + Music: Non-Music Section + Only for use in music videos. Sections of music videos without music, that aren\'t already covered by another category - Unable to vote for segment: Status: %d %s - Can\'t vote for segment.\nRate Limited (Too many from the same user or IP) - Can\'t vote for segment.\n\n%s - Voted successfully - Voting for segment… - Upvote - Downvote - Change category - There are no segments to vote for - Enable voting - Switch this on to enable voting. + Skip + Skip sponsor + Skip promo + Skip interact + Skip intro + Skip intermission + Skip intermission + Skip outro + Skip preview + Skip preview + Skip recap + Skip filler + Skip non-music + Skip segment - Choose the segment category - You\'ve disabled this category in the settings, enable it to be able to submit - New SponsorBlock segment - Set %02d:%02d:%04d as the start or end of a new segment? - start - end - now - Time the segment begins at - Time the segment ends at - Beginning of segment set - End of segment set - Are the times correct? - The segment lasts from %02d:%02d to %02d:%02d (%d minutes %02d seconds)\nIs it ready to submit? - Mark two locations on the time bar first - Edit timing of segment manually - Do you want to edit the timing for the start or end of the segment? - Done - Invalid time given + Skipped sponsor + Skipped self promotion + Skipped annoying reminder + Skipped intro + Skipped intermission + Skipped intermission + Skipped outro + Skipped preview + Skipped preview + Skipped recap + Skipped filler + Skipped a non-music section + Skipped unsubmitted segment + Skipped multiple segments + + Skip automatically + Skip automatically once + Show a skip button + Show in seek bar + Disable + + About + Sponsor.Ajay.app + Data is provided by the SponsorBlock API. Tap here to learn more and see downloads for other platforms + ReVanced integration by JakubWeg,\nrecoded by oSumAtrIX + + Can\'t submit the segment: %s + Unable to submit segments (API timed out) + Unable to submit segments (status: %d %s) + Can\'t submit the segment.\nRate Limited (too many from the same user or IP) + Can\'t submit the segment: %s + Can\'t submit the segment.\nAlready exists + Segment submitted successfully + + SponsorBlock temporarily not available + SponsorBlock temporarily not available (status %d) + SponsorBlock temporarily not available (API timed out) + + Unable to vote for segment (API timed out) + Unable to vote for segment (status: %d %s) + Unable to vote for segment: %s + Upvote + Downvote + Change category + There are no segments to vote for + + Choose the segment category + Category is disabled in settings. Enable category to submit. + New SponsorBlock segment + Set %02d:%02d:%04d as the start or end of a new segment? + start + end + now + Time the segment begins at + Time the segment ends at + Are the times correct? + The segment lasts from %02d:%02d to %02d:%02d (%d minutes %02d seconds)\nIs it ready to submit? + Mark two locations on the time bar first + Preview the segment, and ensure it skips smoothly + Edit timing of segment manually + Do you want to edit the timing for the start or end of the segment? + Invalid time given View guidelines - Guidelines contain tips and rules about submitting segments - There are guidelines - It\'s recommended to read the SponsorBlock guidelines before submitting any segment + Guidelines contain rules and tips for creating new segments + Follow the guidelines + Read the SponsorBlock guidelines before creating new segments Already read Show me - Show time without segments - This time appears in brackets next to the current time. This shows the total video duration minus any segments. - Preview/Recap - Recap of previous episodes, or a preview of what\'s coming up later in the current video or future videos in the same series. Clips should not provide additional information. - Stats - Loading.. - SponsorBlock is disabled - Your username: <b>%s</b> - Click to change your username - Unable to change username: Status: %d %s - Username successfully changed - Submissions: <b>%s</b> - You\'ve saved people from <b>%s</b> segments. - That\'s <b>%s</b> of their lives. Click to see the leaderboard - You\'ve skipped <b>%s</b> segments. - That\'s <b>%s</b>. - minutes - Are you looking for changing colors? - You can now change a category\'s color by clicking on it above. - Choose the category - Color changed - Color reset - Invalid hex code - Change - Reset + Stats + Stats temporarily not available (API is down) + Loading... + SponsorBlock is disabled + Your username: <b>%s</b> + Tap here to change your username + Unable to change username: Status: %d %s + Username successfully changed + You\'re reputation is <b>%.2f</b> + You\'ve created <b>%s</b> segments + SponsorBlock leaderboard + You\'ve saved people from <b>%s</b> segments + Tap here to see the global stats and top contributors + That\'s <b>%s</b> of their lives.<br>Tap here to see the leaderboard + You\'ve skipped <b>%s</b> segments + That\'s <b>%s</b> + Reset skipped segments counter? + %d hours %d minutes + %d minutes %d seconds + %d seconds + Color: + Color changed + Color reset + Invalid color code + Reset color - Segments - SB Browser - - API URL changed - API URL reset - Provided API URL is invalid + Reset + API URL reset + API URL is invalid + API URL changed diff --git a/src/main/resources/sponsorblock/layout/inline_sponsor_overlay.xml b/src/main/resources/sponsorblock/layout/inline_sponsor_overlay.xml index 6bc670fb9..9f4221735 100644 --- a/src/main/resources/sponsorblock/layout/inline_sponsor_overlay.xml +++ b/src/main/resources/sponsorblock/layout/inline_sponsor_overlay.xml @@ -1,5 +1,23 @@ - - + + + + \ No newline at end of file diff --git a/src/main/resources/sponsorblock/layout/new_segment.xml b/src/main/resources/sponsorblock/layout/new_segment.xml index 155907c96..be5020be2 100644 --- a/src/main/resources/sponsorblock/layout/new_segment.xml +++ b/src/main/resources/sponsorblock/layout/new_segment.xml @@ -3,58 +3,58 @@ xmlns:yt="http://schemas.android.com/apk/res-auto"> + android:layout_height="wrap_content" + android:background="#66000000" + android:gravity="start|center" + android:orientation="vertical"> + android:paddingTop="3.0dip" + android:paddingEnd="5.0dip" + android:paddingBottom="3.0dip" + android:src="@drawable/player_fast_rewind" /> + android:paddingTop="3.0dip" + android:paddingEnd="5.0dip" + android:paddingBottom="3.0dip" + android:src="@drawable/player_fast_forward" /> + android:paddingTop="3.0dip" + android:paddingEnd="10.0dip" + android:paddingBottom="3.0dip" + android:src="@drawable/ic_sb_adjust" /> + android:paddingTop="3.0dip" + android:paddingEnd="5.0dip" + android:paddingBottom="3.0dip" + android:src="@drawable/ic_sb_compare" /> + android:paddingTop="3.0dip" + android:paddingEnd="5.0dip" + android:paddingBottom="3.0dip" + android:src="@drawable/ic_sb_edit" /> + android:paddingTop="3.0dip" + android:paddingEnd="10.0dip" + android:paddingBottom="3.0dip" + android:src="@drawable/ic_sb_publish" /> \ No newline at end of file diff --git a/src/main/resources/sponsorblock/layout/skip_sponsor_button.xml b/src/main/resources/sponsorblock/layout/skip_sponsor_button.xml index 3ceb8c362..3a3167bb8 100644 --- a/src/main/resources/sponsorblock/layout/skip_sponsor_button.xml +++ b/src/main/resources/sponsorblock/layout/skip_sponsor_button.xml @@ -1,7 +1,36 @@ - - - - + + + + + + + \ No newline at end of file