1
mirror of https://github.com/revanced/revanced-integrations synced 2025-11-21 18:35:37 +01:00

Compare commits

..

39 Commits

Author SHA1 Message Date
semantic-release-bot
24a609288f chore(release): 0.106.0-dev.2 [skip ci]
# [0.106.0-dev.2](https://github.com/revanced/revanced-integrations/compare/v0.106.0-dev.1...v0.106.0-dev.2) (2023-04-30)

### Features

* add appreciation message for new contributors ([78d56d4](78d56d4fe1))
2023-04-30 01:17:18 +00:00
oSumAtrIX
78d56d4fe1 feat: add appreciation message for new contributors 2023-04-30 03:15:36 +02:00
semantic-release-bot
27fdcfff08 chore(release): 0.106.0-dev.1 [skip ci]
# [0.106.0-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.105.1-dev.2...v0.106.0-dev.1) (2023-04-28)

### Features

* **youtube/spoof-app-version:** user selectable version to spoof ([#375](https://github.com/revanced/revanced-integrations/issues/375)) ([f6f6c93](f6f6c93c57))
2023-04-28 17:53:58 +00:00
LisoUseInAIKyrios
f6f6c93c57 feat(youtube/spoof-app-version): user selectable version to spoof (#375) 2023-04-28 21:52:09 +04:00
semantic-release-bot
a661dac623 chore(release): 0.105.1-dev.2 [skip ci]
## [0.105.1-dev.2](https://github.com/revanced/revanced-integrations/compare/v0.105.1-dev.1...v0.105.1-dev.2) (2023-04-28)

### Bug Fixes

* **youtube/spoof-signature-verification:** more fixes for subtitle window positions  ([#374](https://github.com/revanced/revanced-integrations/issues/374)) ([8cc1b6e](8cc1b6ea4a))
2023-04-28 08:51:38 +00:00
LisoUseInAIKyrios
8cc1b6ea4a fix(youtube/spoof-signature-verification): more fixes for subtitle window positions (#374) 2023-04-28 12:49:41 +04:00
semantic-release-bot
829895874b chore(release): 0.105.1-dev.1 [skip ci]
## [0.105.1-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.105.0...v0.105.1-dev.1) (2023-04-28)

### Bug Fixes

* **youtube:** no longer need to restart the app after changing `copy-video-url` or `downloads` patch ([#372](https://github.com/revanced/revanced-integrations/issues/372)) ([6b15514](6b15514885))
2023-04-28 06:18:05 +00:00
LisoUseInAIKyrios
6b15514885 fix(youtube): no longer need to restart the app after changing copy-video-url or downloads patch (#372)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-04-28 10:16:08 +04:00
semantic-release-bot
5b53e02613 chore(release): 0.105.0 [skip ci]
# [0.105.0](https://github.com/revanced/revanced-integrations/compare/v0.104.0...v0.105.0) (2023-04-27)

### Bug Fixes

* **youtube/minimized-playback:** disable minimized playback for shorts ([#371](https://github.com/revanced/revanced-integrations/issues/371)) ([df4b03f](df4b03fed5))
* **youtube/return-youtube-dislike:** fix dislikes using wrong font if dark mode is enabled during video playback ([#368](https://github.com/revanced/revanced-integrations/issues/368)) ([3b37a3b](3b37a3b41f))
* **youtube/spoof-signature-verification:** additional fixes for subtitle window positions ([#369](https://github.com/revanced/revanced-integrations/issues/369)) ([6f2ae31](6f2ae313cf))

### Features

* **youtube/sponsorblock:** automatically hide skip button ([#365](https://github.com/revanced/revanced-integrations/issues/365)) ([75dad2f](75dad2f307))
2023-04-27 21:37:45 +00:00
oSumAtrIX
2deacc5035 chore: merge branch dev to main (#370) 2023-04-27 23:35:22 +02:00
oSumAtrIX
46d70a3e00 refactor: use better method name 2023-04-27 21:08:32 +02:00
semantic-release-bot
91ce39378a chore(release): 0.105.0-dev.2 [skip ci]
# [0.105.0-dev.2](https://github.com/revanced/revanced-integrations/compare/v0.105.0-dev.1...v0.105.0-dev.2) (2023-04-27)

### Bug Fixes

* **youtube/minimized-playback:** disable minimized playback for shorts ([#371](https://github.com/revanced/revanced-integrations/issues/371)) ([df4b03f](df4b03fed5))
2023-04-27 13:40:41 +00:00
LisoUseInAIKyrios
df4b03fed5 fix(youtube/minimized-playback): disable minimized playback for shorts (#371) 2023-04-27 17:38:52 +04:00
semantic-release-bot
9f8063880c chore(release): 0.105.0-dev.1 [skip ci]
# [0.105.0-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.104.1-dev.2...v0.105.0-dev.1) (2023-04-26)

### Features

* **youtube/sponsorblock:** automatically hide skip button ([#365](https://github.com/revanced/revanced-integrations/issues/365)) ([75dad2f](75dad2f307))
2023-04-26 08:33:11 +00:00
LisoUseInAIKyrios
75dad2f307 feat(youtube/sponsorblock): automatically hide skip button (#365)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-04-26 12:31:27 +04:00
semantic-release-bot
80dc8f0421 chore(release): 0.104.1-dev.2 [skip ci]
## [0.104.1-dev.2](https://github.com/revanced/revanced-integrations/compare/v0.104.1-dev.1...v0.104.1-dev.2) (2023-04-25)

### Bug Fixes

* **youtube/spoof-signature-verification:** additional fixes for subtitle window positions ([#369](https://github.com/revanced/revanced-integrations/issues/369)) ([6f2ae31](6f2ae313cf))
2023-04-25 13:24:36 +00:00
LisoUseInAIKyrios
6f2ae313cf fix(youtube/spoof-signature-verification): additional fixes for subtitle window positions (#369) 2023-04-25 17:22:52 +04:00
semantic-release-bot
cb7063b2b3 chore(release): 0.104.1-dev.1 [skip ci]
## [0.104.1-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.104.0...v0.104.1-dev.1) (2023-04-25)

### Bug Fixes

* **youtube/return-youtube-dislike:** fix dislikes using wrong font if dark mode is enabled during video playback ([#368](https://github.com/revanced/revanced-integrations/issues/368)) ([3b37a3b](3b37a3b41f))
2023-04-25 12:50:21 +00:00
LisoUseInAIKyrios
3b37a3b41f fix(youtube/return-youtube-dislike): fix dislikes using wrong font if dark mode is enabled during video playback (#368) 2023-04-25 16:48:01 +04:00
semantic-release-bot
13e4be8567 chore(release): 0.104.0 [skip ci]
# [0.104.0](https://github.com/revanced/revanced-integrations/compare/v0.103.0...v0.104.0) (2023-04-24)

### Bug Fixes

* **spoof-wifi-connection:** fixed crash when wifi is disabled ([#363](https://github.com/revanced/revanced-integrations/issues/363)) ([7fc8e88](7fc8e882d8))
* **youtube/hide-video-action-buttons:** fix hide action buttons not working for some users ([#366](https://github.com/revanced/revanced-integrations/issues/366)) ([246deb1](246deb1602))
* **youtube/sponsorblock:** Include milliseconds in the voting menu ([#362](https://github.com/revanced/revanced-integrations/issues/362)) ([6952c50](6952c50595))

### Features

* **youtube/wide-searchbar:** rename patch ([8493f57](8493f57879))
* **youtube:** remove non working patch `hide-my-mix` ([436a84e](436a84ee07))
2023-04-24 15:37:05 +00:00
oSumAtrIX
be7b6f2a20 chore: merge branch dev to main (#364) 2023-04-24 17:35:18 +02:00
semantic-release-bot
b9f6c62060 chore(release): 0.104.0-dev.1 [skip ci]
# [0.104.0-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.103.1-dev.2...v0.104.0-dev.1) (2023-04-24)

### Features

* **youtube/wide-searchbar:** rename patch ([2320880](2320880a42))
* **youtube:** bump compatibility to `18.15.40` ([#367](https://github.com/revanced/revanced-integrations/issues/367)) ([52a3193](52a3193087))
* **youtube:** remove non working patch `hide-my-mix` ([98edcdd](98edcdd589))
2023-04-24 17:33:46 +02:00
oSumAtrIX
8493f57879 feat(youtube/wide-searchbar): rename patch 2023-04-24 17:33:45 +02:00
oSumAtrIX
436a84ee07 feat(youtube): remove non working patch hide-my-mix 2023-04-24 17:33:45 +02:00
semantic-release-bot
f2603d3d79 chore(release): 0.103.1-dev.2 [skip ci]
## [0.103.1-dev.2](https://github.com/revanced/revanced-integrations/compare/v0.103.1-dev.1...v0.103.1-dev.2) (2023-04-23)

### Bug Fixes

* **youtube/hide-video-action-buttons:** fix hide action buttons not working for some users ([#366](https://github.com/revanced/revanced-integrations/issues/366)) ([afd9b6e](afd9b6e305))
2023-04-24 17:33:45 +02:00
LisoUseInAIKyrios
246deb1602 fix(youtube/hide-video-action-buttons): fix hide action buttons not working for some users (#366) 2023-04-24 17:33:45 +02:00
semantic-release-bot
050766de1d chore(release): 0.103.1-dev.1 [skip ci]
## [0.103.1-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.103.0...v0.103.1-dev.1) (2023-04-22)

### Bug Fixes

* **youtube/sponsorblock:** Include milliseconds in the voting menu ([#362](https://github.com/revanced/revanced-integrations/issues/362)) ([1ada30d](1ada30d5c9))
2023-04-24 17:33:44 +02:00
cane
6952c50595 fix(youtube/sponsorblock): Include milliseconds in the voting menu (#362) 2023-04-24 17:33:44 +02:00
LisoUseInAIKyrios
7fc8e882d8 fix(spoof-wifi-connection): fixed crash when wifi is disabled (#363) 2023-04-24 17:33:43 +02:00
semantic-release-bot
a61148cac2 chore(release): 0.103.0 [skip ci]
# [0.103.0](https://github.com/revanced/revanced-integrations/compare/v0.102.0...v0.103.0) (2023-04-21)

### Bug Fixes

* minor syntax error ([8797765](8797765efa))
* **youtube/general-ads:** hide new types of ads ([#339](https://github.com/revanced/revanced-integrations/issues/339)) ([6528d44](6528d444b4))
* **youtube/hide-video-action-buttons:** fix 'hide share button' ([#360](https://github.com/revanced/revanced-integrations/issues/360)) ([a2af2c0](a2af2c0c9f))
* **youtube/return-youtube-dislike:** fix error toast when voting ([#349](https://github.com/revanced/revanced-integrations/issues/349)) ([e3d923d](e3d923d564))
* **youtube/return-youtube-dislike:** render dislikes when scrolling into the screen ([#350](https://github.com/revanced/revanced-integrations/issues/350)) ([41c07f7](41c07f77f4))
* **youtube/return-youtube-dislike:** stale dislike data shown after opening / closing the app during shorts playback ([#356](https://github.com/revanced/revanced-integrations/issues/356)) ([212e4f2](212e4f2ce4))
* **youtube/settings:** fix dialog not shown if dismissed with back button ([584de16](584de16236))
* **youtube/sponsorblock:** always show the video time without segments using left to right layout ([#359](https://github.com/revanced/revanced-integrations/issues/359)) ([86c2789](86c27890ad))
* **youtube/sponsorblock:** change default behavior to better match the browser ([#353](https://github.com/revanced/revanced-integrations/issues/353)) ([b959c8e](b959c8ef98))
* **youtube/sponsorblock:** settings do not show default behavior ([#351](https://github.com/revanced/revanced-integrations/issues/351)) ([6dbccfd](6dbccfd472))
* **youtube/sponsorblock:** update HTTP user agent ([#344](https://github.com/revanced/revanced-integrations/issues/344)) ([3025103](3025103014))

### Features

* **youtube/general-ads:** block new type of ad ([6265a91](6265a91841))
* **youtube/general-ads:** hide new type of ad ([5ba4cbd](5ba4cbd4e0))
* **youtube/general-ads:** hide new type of ad ([f818490](f8184905bd))
* **youtube/general-ads:** hide new type of movie offer ad ([da7b669](da7b669c97))
* **youtube/settings:** disable preference control if the feature is turned off.  show a dialog explaining side effects of some patches ([#328](https://github.com/revanced/revanced-integrations/issues/328)) ([a0ad968](a0ad968aaa))
* **youtube/sponsorblock:** skip to video highlight ([#352](https://github.com/revanced/revanced-integrations/issues/352)) ([03f09cf](03f09cf7bc))
* **youtube:** user selectable default video speed and quality ([#354](https://github.com/revanced/revanced-integrations/issues/354)) ([14223f4](14223f40b5))
2023-04-21 13:49:05 +00:00
oSumAtrIX
c2ff0c45ab chore: merge branch dev to main (#361) 2023-04-21 15:47:23 +02:00
semantic-release-bot
587689ed7b chore(release): 0.103.0-dev.7 [skip ci]
# [0.103.0-dev.7](https://github.com/revanced/revanced-integrations/compare/v0.103.0-dev.6...v0.103.0-dev.7) (2023-04-20)

### Bug Fixes

* **youtube/hide-video-action-buttons:** fix 'hide share button' ([#360](https://github.com/revanced/revanced-integrations/issues/360)) ([a2af2c0](a2af2c0c9f))
2023-04-20 06:43:27 +00:00
LisoUseInAIKyrios
a2af2c0c9f fix(youtube/hide-video-action-buttons): fix 'hide share button' (#360) 2023-04-20 10:41:36 +04:00
semantic-release-bot
f7c3543d4f chore(release): 0.103.0-dev.6 [skip ci]
# [0.103.0-dev.6](https://github.com/revanced/revanced-integrations/compare/v0.103.0-dev.5...v0.103.0-dev.6) (2023-04-19)

### Bug Fixes

* **youtube/sponsorblock:** always show the video time without segments using left to right layout ([#359](https://github.com/revanced/revanced-integrations/issues/359)) ([86c2789](86c27890ad))
2023-04-19 09:32:27 +00:00
LisoUseInAIKyrios
86c27890ad fix(youtube/sponsorblock): always show the video time without segments using left to right layout (#359) 2023-04-19 13:30:46 +04:00
semantic-release-bot
2ea55af9ce chore(release): 0.103.0-dev.5 [skip ci]
# [0.103.0-dev.5](https://github.com/revanced/revanced-integrations/compare/v0.103.0-dev.4...v0.103.0-dev.5) (2023-04-19)

### Bug Fixes

* **youtube/return-youtube-dislike:** render dislikes when scrolling into the screen ([#350](https://github.com/revanced/revanced-integrations/issues/350)) ([41c07f7](41c07f77f4))
2023-04-19 06:37:56 +00:00
LisoUseInAIKyrios
41c07f77f4 fix(youtube/return-youtube-dislike): render dislikes when scrolling into the screen (#350)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-04-19 10:36:10 +04:00
semantic-release-bot
48050c1c50 chore(release): 0.103.0-dev.4 [skip ci]
# [0.103.0-dev.4](https://github.com/revanced/revanced-integrations/compare/v0.103.0-dev.3...v0.103.0-dev.4) (2023-04-18)

### Bug Fixes

* minor syntax error ([8797765](8797765efa))
2023-04-18 00:01:33 +00:00
oSumAtrIX
8797765efa fix: minor syntax error 2023-04-18 01:59:32 +02:00
33 changed files with 1076 additions and 683 deletions

2
.github/config.yml vendored Normal file
View File

@@ -0,0 +1,2 @@
firstPRMergeComment: >
Thank you for contributing to ReVanced. Join us on [Discord](https://revanced.app/discord) if you want to receive a contributor role.

View File

@@ -1,3 +1,167 @@
# [0.106.0-dev.2](https://github.com/revanced/revanced-integrations/compare/v0.106.0-dev.1...v0.106.0-dev.2) (2023-04-30)
### Features
* add appreciation message for new contributors ([78d56d4](https://github.com/revanced/revanced-integrations/commit/78d56d4fe182999555ddf5881a10880e3726782e))
# [0.106.0-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.105.1-dev.2...v0.106.0-dev.1) (2023-04-28)
### Features
* **youtube/spoof-app-version:** user selectable version to spoof ([#375](https://github.com/revanced/revanced-integrations/issues/375)) ([f6f6c93](https://github.com/revanced/revanced-integrations/commit/f6f6c93c57bdbec13f09acd802f58554cb981f3a))
## [0.105.1-dev.2](https://github.com/revanced/revanced-integrations/compare/v0.105.1-dev.1...v0.105.1-dev.2) (2023-04-28)
### Bug Fixes
* **youtube/spoof-signature-verification:** more fixes for subtitle window positions ([#374](https://github.com/revanced/revanced-integrations/issues/374)) ([8cc1b6e](https://github.com/revanced/revanced-integrations/commit/8cc1b6ea4af4e642fb2d97233d50f34b0113f2c0))
## [0.105.1-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.105.0...v0.105.1-dev.1) (2023-04-28)
### Bug Fixes
* **youtube:** no longer need to restart the app after changing `copy-video-url` or `downloads` patch ([#372](https://github.com/revanced/revanced-integrations/issues/372)) ([6b15514](https://github.com/revanced/revanced-integrations/commit/6b155148854fbfe155c9384ba8976b5ddf3d5992))
# [0.105.0](https://github.com/revanced/revanced-integrations/compare/v0.104.0...v0.105.0) (2023-04-27)
### Bug Fixes
* **youtube/minimized-playback:** disable minimized playback for shorts ([#371](https://github.com/revanced/revanced-integrations/issues/371)) ([df4b03f](https://github.com/revanced/revanced-integrations/commit/df4b03fed5a0622b18bf4a8dca1940d26a590d8f))
* **youtube/return-youtube-dislike:** fix dislikes using wrong font if dark mode is enabled during video playback ([#368](https://github.com/revanced/revanced-integrations/issues/368)) ([3b37a3b](https://github.com/revanced/revanced-integrations/commit/3b37a3b41f7bfbc4a6d6d12e2deb2acd9bb2ccc8))
* **youtube/spoof-signature-verification:** additional fixes for subtitle window positions ([#369](https://github.com/revanced/revanced-integrations/issues/369)) ([6f2ae31](https://github.com/revanced/revanced-integrations/commit/6f2ae313cf492166d64e5e33e759f2b234191b64))
### Features
* **youtube/sponsorblock:** automatically hide skip button ([#365](https://github.com/revanced/revanced-integrations/issues/365)) ([75dad2f](https://github.com/revanced/revanced-integrations/commit/75dad2f3071c19aa097ebdc7bd83d1ce9afb78ea))
# [0.105.0-dev.2](https://github.com/revanced/revanced-integrations/compare/v0.105.0-dev.1...v0.105.0-dev.2) (2023-04-27)
### Bug Fixes
* **youtube/minimized-playback:** disable minimized playback for shorts ([#371](https://github.com/revanced/revanced-integrations/issues/371)) ([df4b03f](https://github.com/revanced/revanced-integrations/commit/df4b03fed5a0622b18bf4a8dca1940d26a590d8f))
# [0.105.0-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.104.1-dev.2...v0.105.0-dev.1) (2023-04-26)
### Features
* **youtube/sponsorblock:** automatically hide skip button ([#365](https://github.com/revanced/revanced-integrations/issues/365)) ([75dad2f](https://github.com/revanced/revanced-integrations/commit/75dad2f3071c19aa097ebdc7bd83d1ce9afb78ea))
## [0.104.1-dev.2](https://github.com/revanced/revanced-integrations/compare/v0.104.1-dev.1...v0.104.1-dev.2) (2023-04-25)
### Bug Fixes
* **youtube/spoof-signature-verification:** additional fixes for subtitle window positions ([#369](https://github.com/revanced/revanced-integrations/issues/369)) ([6f2ae31](https://github.com/revanced/revanced-integrations/commit/6f2ae313cf492166d64e5e33e759f2b234191b64))
## [0.104.1-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.104.0...v0.104.1-dev.1) (2023-04-25)
### Bug Fixes
* **youtube/return-youtube-dislike:** fix dislikes using wrong font if dark mode is enabled during video playback ([#368](https://github.com/revanced/revanced-integrations/issues/368)) ([3b37a3b](https://github.com/revanced/revanced-integrations/commit/3b37a3b41f7bfbc4a6d6d12e2deb2acd9bb2ccc8))
# [0.104.0](https://github.com/revanced/revanced-integrations/compare/v0.103.0...v0.104.0) (2023-04-24)
### Bug Fixes
* **spoof-wifi-connection:** fixed crash when wifi is disabled ([#363](https://github.com/revanced/revanced-integrations/issues/363)) ([7fc8e88](https://github.com/revanced/revanced-integrations/commit/7fc8e882d8d268484b6e273fdb0371db2feef1d3))
* **youtube/hide-video-action-buttons:** fix hide action buttons not working for some users ([#366](https://github.com/revanced/revanced-integrations/issues/366)) ([246deb1](https://github.com/revanced/revanced-integrations/commit/246deb16020adda26d9d0a0449157f4855678d18))
* **youtube/sponsorblock:** Include milliseconds in the voting menu ([#362](https://github.com/revanced/revanced-integrations/issues/362)) ([6952c50](https://github.com/revanced/revanced-integrations/commit/6952c505957153d7fdeb7ee42b3f824c155993f5))
### Features
* **youtube/wide-searchbar:** rename patch ([8493f57](https://github.com/revanced/revanced-integrations/commit/8493f57879f0075c73932240b61bf0c52efda0ed))
* **youtube:** remove non working patch `hide-my-mix` ([436a84e](https://github.com/revanced/revanced-integrations/commit/436a84ee0785e5b0bed1b9a4a02b5be86eff4a4a))
# [0.104.0-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.103.1-dev.2...v0.104.0-dev.1) (2023-04-24)
### Features
* **youtube/wide-searchbar:** rename patch ([2320880](https://github.com/revanced/revanced-integrations/commit/2320880a42bf37335ececf1f8e6cb83bd57f347d))
* **youtube:** bump compatibility to `18.15.40` ([#367](https://github.com/revanced/revanced-integrations/issues/367)) ([52a3193](https://github.com/revanced/revanced-integrations/commit/52a31930870b838e766d08c3203bd8cd7ae443ba))
* **youtube:** remove non working patch `hide-my-mix` ([98edcdd](https://github.com/revanced/revanced-integrations/commit/98edcdd589c0d3615530b44c8bbaeb94ae599afb))
## [0.103.1-dev.2](https://github.com/revanced/revanced-integrations/compare/v0.103.1-dev.1...v0.103.1-dev.2) (2023-04-23)
### Bug Fixes
* **youtube/hide-video-action-buttons:** fix hide action buttons not working for some users ([#366](https://github.com/revanced/revanced-integrations/issues/366)) ([afd9b6e](https://github.com/revanced/revanced-integrations/commit/afd9b6e30566d735075c16d3f5173e406c965a8c))
## [0.103.1-dev.1](https://github.com/revanced/revanced-integrations/compare/v0.103.0...v0.103.1-dev.1) (2023-04-22)
### Bug Fixes
* **youtube/sponsorblock:** Include milliseconds in the voting menu ([#362](https://github.com/revanced/revanced-integrations/issues/362)) ([1ada30d](https://github.com/revanced/revanced-integrations/commit/1ada30d5c925f1b0f21d45865240780e4ecd84d7))
# [0.103.0](https://github.com/revanced/revanced-integrations/compare/v0.102.0...v0.103.0) (2023-04-21)
### Bug Fixes
* minor syntax error ([8797765](https://github.com/revanced/revanced-integrations/commit/8797765efa0fb98b6e11a7198ecce3943df3daf5))
* **youtube/general-ads:** hide new types of ads ([#339](https://github.com/revanced/revanced-integrations/issues/339)) ([6528d44](https://github.com/revanced/revanced-integrations/commit/6528d444b49759ee1137c9b0eb8e1079fb4cc97c))
* **youtube/hide-video-action-buttons:** fix 'hide share button' ([#360](https://github.com/revanced/revanced-integrations/issues/360)) ([a2af2c0](https://github.com/revanced/revanced-integrations/commit/a2af2c0c9ffc2f961773bfb8d546aff68c2d1c27))
* **youtube/return-youtube-dislike:** fix error toast when voting ([#349](https://github.com/revanced/revanced-integrations/issues/349)) ([e3d923d](https://github.com/revanced/revanced-integrations/commit/e3d923d564ae572c5e0e10a86ce17b8009ec8c42))
* **youtube/return-youtube-dislike:** render dislikes when scrolling into the screen ([#350](https://github.com/revanced/revanced-integrations/issues/350)) ([41c07f7](https://github.com/revanced/revanced-integrations/commit/41c07f77f47d726fdc16120bb5695407a7dec1fc))
* **youtube/return-youtube-dislike:** stale dislike data shown after opening / closing the app during shorts playback ([#356](https://github.com/revanced/revanced-integrations/issues/356)) ([212e4f2](https://github.com/revanced/revanced-integrations/commit/212e4f2ce43360776fe20467c4142c9936b22d42))
* **youtube/settings:** fix dialog not shown if dismissed with back button ([584de16](https://github.com/revanced/revanced-integrations/commit/584de16236ff758c2067ee84ba4cc04d765d49ba))
* **youtube/sponsorblock:** always show the video time without segments using left to right layout ([#359](https://github.com/revanced/revanced-integrations/issues/359)) ([86c2789](https://github.com/revanced/revanced-integrations/commit/86c27890ada8739ea272f8783eb4ef526b808a27))
* **youtube/sponsorblock:** change default behavior to better match the browser ([#353](https://github.com/revanced/revanced-integrations/issues/353)) ([b959c8e](https://github.com/revanced/revanced-integrations/commit/b959c8ef98e869201c8bc2609943108283fea453))
* **youtube/sponsorblock:** settings do not show default behavior ([#351](https://github.com/revanced/revanced-integrations/issues/351)) ([6dbccfd](https://github.com/revanced/revanced-integrations/commit/6dbccfd472d843b5c3f0efed39b575d3ea7ac04f))
* **youtube/sponsorblock:** update HTTP user agent ([#344](https://github.com/revanced/revanced-integrations/issues/344)) ([3025103](https://github.com/revanced/revanced-integrations/commit/3025103014a4521a437cfde0a417535e7751b517))
### Features
* **youtube/general-ads:** block new type of ad ([6265a91](https://github.com/revanced/revanced-integrations/commit/6265a91841f8b037be22dd5fd5399dbeeb666745))
* **youtube/general-ads:** hide new type of ad ([5ba4cbd](https://github.com/revanced/revanced-integrations/commit/5ba4cbd4e097d863924731d363dd5bb8849e1394))
* **youtube/general-ads:** hide new type of ad ([f818490](https://github.com/revanced/revanced-integrations/commit/f8184905bd9601bf63e30963ff337d24f2599794))
* **youtube/general-ads:** hide new type of movie offer ad ([da7b669](https://github.com/revanced/revanced-integrations/commit/da7b669c97d18bef51de98ddfde8a514ebb61ecf))
* **youtube/settings:** disable preference control if the feature is turned off. show a dialog explaining side effects of some patches ([#328](https://github.com/revanced/revanced-integrations/issues/328)) ([a0ad968](https://github.com/revanced/revanced-integrations/commit/a0ad968aaa66422e67de2a61d76bc7aa88f08bf6))
* **youtube/sponsorblock:** skip to video highlight ([#352](https://github.com/revanced/revanced-integrations/issues/352)) ([03f09cf](https://github.com/revanced/revanced-integrations/commit/03f09cf7bce1747b1d402f3a3e16dd69c364dfce))
* **youtube:** user selectable default video speed and quality ([#354](https://github.com/revanced/revanced-integrations/issues/354)) ([14223f4](https://github.com/revanced/revanced-integrations/commit/14223f40b5ca48f35bbecfd849dff20dfd309d92))
# [0.103.0-dev.7](https://github.com/revanced/revanced-integrations/compare/v0.103.0-dev.6...v0.103.0-dev.7) (2023-04-20)
### Bug Fixes
* **youtube/hide-video-action-buttons:** fix 'hide share button' ([#360](https://github.com/revanced/revanced-integrations/issues/360)) ([a2af2c0](https://github.com/revanced/revanced-integrations/commit/a2af2c0c9ffc2f961773bfb8d546aff68c2d1c27))
# [0.103.0-dev.6](https://github.com/revanced/revanced-integrations/compare/v0.103.0-dev.5...v0.103.0-dev.6) (2023-04-19)
### Bug Fixes
* **youtube/sponsorblock:** always show the video time without segments using left to right layout ([#359](https://github.com/revanced/revanced-integrations/issues/359)) ([86c2789](https://github.com/revanced/revanced-integrations/commit/86c27890ada8739ea272f8783eb4ef526b808a27))
# [0.103.0-dev.5](https://github.com/revanced/revanced-integrations/compare/v0.103.0-dev.4...v0.103.0-dev.5) (2023-04-19)
### Bug Fixes
* **youtube/return-youtube-dislike:** render dislikes when scrolling into the screen ([#350](https://github.com/revanced/revanced-integrations/issues/350)) ([41c07f7](https://github.com/revanced/revanced-integrations/commit/41c07f77f47d726fdc16120bb5695407a7dec1fc))
# [0.103.0-dev.4](https://github.com/revanced/revanced-integrations/compare/v0.103.0-dev.3...v0.103.0-dev.4) (2023-04-18)
### Bug Fixes
* minor syntax error ([8797765](https://github.com/revanced/revanced-integrations/commit/8797765efa0fb98b6e11a7198ecce3943df3daf5))
# [0.103.0-dev.3](https://github.com/revanced/revanced-integrations/compare/v0.103.0-dev.2...v0.103.0-dev.3) (2023-04-17)

View File

@@ -20,6 +20,8 @@
# hide the original source file name.
#-renamesourcefileattribute SourceFile
-dontobfuscate
-dontoptimize
-keepattributes * # https://www.guardsquare.com/manual/configuration/attributes
-keep class app.revanced.** {
*;
}

View File

@@ -1,60 +1,31 @@
package app.revanced.integrations.patches;
import app.revanced.integrations.settings.SettingsEnum;
import app.revanced.integrations.utils.LogHelper;
final class ButtonsPatch extends Filter {
private final BlockRule actionButtonsRule;
private final BlockRule dislikeRule;
private final BlockRule actionBarRule;
private final BlockRule[] rules;
public ButtonsPatch() {
BlockRule like = new BlockRule(SettingsEnum.HIDE_LIKE_BUTTON, "|like_button");
dislikeRule = new BlockRule(SettingsEnum.HIDE_DISLIKE_BUTTON, "dislike_button");
BlockRule download = new BlockRule(SettingsEnum.HIDE_DOWNLOAD_BUTTON, "download_button");
actionButtonsRule = new BlockRule(SettingsEnum.HIDE_ACTION_BUTTON, "ContainerType|video_action_button");
BlockRule playlist = new BlockRule(SettingsEnum.HIDE_PLAYLIST_BUTTON, "save_to_playlist_button");
rules = new BlockRule[]{like, dislikeRule, download, actionButtonsRule, playlist};
actionBarRule = new BlockRule(null, "video_action_bar");
this.pathRegister.registerAll(
like,
dislikeRule,
download,
playlist
pathRegister.registerAll(
new BlockRule(SettingsEnum.HIDE_LIKE_DISLIKE_BUTTON, "|like_button", "dislike_button"),
new BlockRule(SettingsEnum.HIDE_DOWNLOAD_BUTTON, "download_button"),
new BlockRule(SettingsEnum.HIDE_PLAYLIST_BUTTON, "save_to_playlist_button"),
new BlockRule(SettingsEnum.HIDE_CLIP_BUTTON, "|clip_button.eml|"),
new BlockRule(SettingsEnum.HIDE_ACTION_BUTTONS, "ContainerType|video_action_button", "|CellType|CollectionType|CellType|ContainerType|button.eml|")
);
}
private boolean hideActionBar() {
for (BlockRule rule : rules) if (!rule.isEnabled()) return false;
private boolean canHideActionBar() {
for (BlockRule rule : pathRegister) if (!rule.isEnabled()) return false;
return true;
}
@Override
public boolean filter(final String path, final String identifier) {
if (hideActionBar() && actionBarRule.check(identifier).isBlocked()) return true;
// If everything is hidden, then also hide the video bar itself.
if (canHideActionBar() && actionBarRule.check(identifier).isBlocked()) return true;
var currentIsActionButton = actionButtonsRule.check(path).isBlocked();
if (dislikeRule.check(path).isBlocked()) ActionButton.doNotBlockCounter = 4;
if (currentIsActionButton && ActionButton.doNotBlockCounter-- > 0) {
if (SettingsEnum.HIDE_SHARE_BUTTON.getBoolean()) {
LogHelper.printDebug(() -> "Hiding share button");
return true;
} else return false;
}
if ((currentIsActionButton && ActionButton.doNotBlockCounter <= 0 && actionButtonsRule.isEnabled()) || pathRegister.contains(path)) {
LogHelper.printDebug(() -> "Blocked: " + path);
return true;
} else return false;
}
static class ActionButton {
public static int doNotBlockCounter = 4;
return pathRegister.contains(path);
}
}

View File

@@ -8,7 +8,7 @@ import app.revanced.integrations.utils.ReVancedUtils;
public class CopyVideoUrlPatch {
public static void copyUrl(Boolean withTimestamp) {
try {
String url = String.format("https://youtu.be/%s", VideoInformation.getCurrentVideoId());
String url = String.format("https://youtu.be/%s", VideoInformation.getVideoId());
if (withTimestamp) {
long seconds = VideoInformation.getVideoTime() / 1000;
url += String.format("?t=%s", seconds);

View File

@@ -75,7 +75,7 @@ public final class GeneralAdsPatch extends Filter {
"horizontal_movie_shelf",
"movie_and_show_upsell_card",
"compact_tvfilm_item",
"offer_module_root
"offer_module_root"
);
this.pathRegister.registerAll(

View File

@@ -1,14 +0,0 @@
package app.revanced.integrations.patches;
import android.view.View;
import app.revanced.integrations.adremover.AdRemoverAPI;
import app.revanced.integrations.settings.SettingsEnum;
public class HideMixPlaylistsPatch {
public static void hideMixPlaylists(View view) {
if (!SettingsEnum.HIDE_MIX_PLAYLISTS.getBoolean()) return;
AdRemoverAPI.HideViewWithLayout1dp(view);
}
}

View File

@@ -1,16 +1,17 @@
package app.revanced.integrations.patches;
import app.revanced.integrations.settings.SettingsEnum;
import app.revanced.integrations.shared.PlayerType;
public class MinimizedPlaybackPatch {
public static boolean isNotPlayingShorts(boolean isPipEnabled) {
return !PlayerType.getCurrent().isNoneOrHidden() && isPipEnabled;
public static boolean isPlaybackNotShort() {
return !PlayerType.getCurrent().isNoneOrHidden();
}
public static boolean isMinimizedPlaybackEnabled() {
return SettingsEnum.ENABLE_MINIMIZED_PLAYBACK.getBoolean();
public static boolean overrideMinimizedPlaybackAvailable() {
// This could be done entirely in the patch,
// but having a unique method to search for makes manually inspecting the patched apk much easier.
return true;
}
}

View File

@@ -1,12 +0,0 @@
package app.revanced.integrations.patches;
import app.revanced.integrations.settings.SettingsEnum;
public class NewActionbarPatch {
//Used by app.revanced.patches.youtube.layout.widesearchbar.patch.WideSearchbarPatch
public static boolean getNewActionBar() {
return SettingsEnum.WIDE_SEARCHBAR.getBoolean(); // TODO: maybe this has to be inverted
}
}

View File

@@ -1,48 +1,108 @@
package app.revanced.integrations.patches;
import static app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike.Vote;
import android.text.SpannableString;
import android.text.Spanned;
import app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike;
import androidx.annotation.NonNull;
import java.util.concurrent.atomic.AtomicReference;
/**
* TODO: delete this empty class, and point the patch to {@link ReturnYouTubeDislike}
*/
import app.revanced.integrations.returnyoutubedislike.ReturnYouTubeDislike;
import app.revanced.integrations.settings.SettingsEnum;
import app.revanced.integrations.utils.LogHelper;
public class ReturnYouTubeDislikePatch {
/**
* Injection point
* Injection point.
*/
public static void newVideoLoaded(String videoId) {
ReturnYouTubeDislike.newVideoLoaded(videoId);
try {
if (!SettingsEnum.RYD_ENABLED.getBoolean()) return;
ReturnYouTubeDislike.newVideoLoaded(videoId);
} catch (Exception ex) {
LogHelper.printException(() -> "newVideoLoaded failure", ex);
}
}
/**
* Injection point
* Injection point.
*
* Called when a litho text component is created
* Called when a litho text component is initially created,
* and also when a Span is later reused again (such as scrolling off/on screen).
*
* This method is sometimes called on the main thread, but it usually is called _off_ the main thread.
* This method can be called multiple times for the same UI element (including after dislikes was added).
*
* @param textRef Cache reference to the like/dislike char sequence,
* which may or may not be the same as the original span parameter.
* If dislikes are added, the atomic reference must be set to the replacement span.
* @param original Original span that was created or reused by Litho.
* @return The original span (if nothing should change), or a replacement span that contains dislikes.
*/
public static void onComponentCreated(Object conversionContext, AtomicReference<Object> textRef) {
ReturnYouTubeDislike.onComponentCreated(conversionContext, textRef);
@NonNull
public static CharSequence onLithoTextLoaded(@NonNull Object conversionContext,
@NonNull AtomicReference<CharSequence> textRef,
@NonNull CharSequence original) {
try {
if (!SettingsEnum.RYD_ENABLED.getBoolean()) {
return original;
}
SpannableString replacement = ReturnYouTubeDislike.getDislikeSpanForContext(conversionContext, original);
if (replacement != null) {
textRef.set(replacement);
return replacement;
}
} catch (Exception ex) {
LogHelper.printException(() -> "onLithoTextLoaded failure", ex);
}
return original;
}
/**
* Injection point
* Injection point.
*
* Called when a Shorts dislike Spannable is created
* Called when a Shorts dislike Spanned is created.
*/
public static Spanned onShortsComponentCreated(Spanned dislike) {
return ReturnYouTubeDislike.onShortsComponentCreated(dislike);
public static Spanned onShortsComponentCreated(Spanned original) {
try {
if (!SettingsEnum.RYD_ENABLED.getBoolean()) {
return original;
}
SpannableString replacement = ReturnYouTubeDislike.getDislikeSpanForShort(original);
if (replacement != null) {
return replacement;
}
} catch (Exception ex) {
LogHelper.printException(() -> "onShortsComponentCreated failure", ex);
}
return original;
}
/**
* Injection point
* Injection point.
*
* Called when the like/dislike button is clicked
* Called when the user likes or dislikes.
*
* @param vote -1 (dislike), 0 (none) or 1 (like)
* @param vote int that matches {@link ReturnYouTubeDislike.Vote#value}
*/
public static void sendVote(int vote) {
ReturnYouTubeDislike.sendVote(vote);
try {
if (!SettingsEnum.RYD_ENABLED.getBoolean()) {
return;
}
for (Vote v : Vote.values()) {
if (v.value == vote) {
ReturnYouTubeDislike.sendVote(v);
return;
}
}
LogHelper.printException(() -> "Unknown vote type: " + vote);
} catch (Exception ex) {
LogHelper.printException(() -> "sendVote failure", ex);
}
}
}

View File

@@ -5,10 +5,8 @@ import app.revanced.integrations.settings.SettingsEnum;
public class SpoofAppVersionPatch {
public static String getYouTubeVersionOverride(String version) {
if (SettingsEnum.SPOOF_APP_VERSION.getBoolean()){
// Override with the most recent version that does not show the new UI player layout.
// If the new UI shows up for some users, then change this to an older version (such as 17.29.34).
return "17.30.34";
if (SettingsEnum.SPOOF_APP_VERSION.getBoolean()) {
return SettingsEnum.SPOOF_APP_VERSION_TARGET.getString();
}
return version;
}

View File

@@ -1,12 +1,15 @@
package app.revanced.integrations.patches;
import static app.revanced.integrations.utils.ReVancedUtils.containsAny;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import app.revanced.integrations.settings.SettingsEnum;
import app.revanced.integrations.shared.PlayerType;
import app.revanced.integrations.utils.LogHelper;
import app.revanced.integrations.utils.ReVancedUtils;
import static app.revanced.integrations.utils.ReVancedUtils.containsAny;
public class SpoofSignatureVerificationPatch {
/**
* Protobuf parameters used for autoplay in scrim.
@@ -28,6 +31,28 @@ public class SpoofSignatureVerificationPatch {
"SAFg" // Autoplay in scrim
};
/**
* On app first start, the first video played usually contains a single non-default window setting value
* and all other subtitle settings for the video are (incorrect) default shorts window settings.
* For this situation, the shorts settings must be replaced.
*
* But some videos use multiple text positions on screen (such as https://youtu.be/3hW1rMNC89o),
* and by chance many of the subtitles uses window positions that match a default shorts position.
* To handle these videos, selectively allowing the shorts specific window settings to 'pass thru' unchanged,
* but only if the video contains multiple non-default subtitle window positions.
*
* Do not enable 'pass thru mode' until this many non default subtitle settings are observed for a single video.
*/
private static final int NUMBER_OF_NON_DEFAULT_SUBTITLES_BEFORE_ENABLING_PASSTHRU = 2;
/**
* The number of non default subtitle settings encountered for the current video.
*/
private static int numberOfNonDefaultSettingsObserved;
@Nullable
private static String currentVideoId;
/**
* Injection point.
*
@@ -49,7 +74,7 @@ public class SpoofSignatureVerificationPatch {
if (isPlayingFeed) {
// Videos in feed won't autoplay with sound.
return PROTOBUF_PARAMETER_SCRIM + PROTOBUF_PARAMETER_SHORTS;
} else{
} else {
// Spoof the parameter to prevent playback issues.
return PROTOBUF_PARAMETER_SHORTS;
}
@@ -108,7 +133,7 @@ public class SpoofSignatureVerificationPatch {
final boolean signatureSpoofing = SettingsEnum.SIGNATURE_SPOOFING.getBoolean();
if (SettingsEnum.DEBUG.getBoolean()) {
if (ap != lastAp || ah != lastAh || av != lastAv || vs != lastVs || sd != lastSd) {
LogHelper.printDebug(() -> "video: " + VideoInformation.getCurrentVideoId() + " spoof: " + signatureSpoofing
LogHelper.printDebug(() -> "video: " + VideoInformation.getVideoId() + " spoof: " + signatureSpoofing
+ " ap:" + ap + " ah:" + ah + " av:" + av + " vs:" + vs + " sd:" + sd);
lastAp = ap;
lastAh = ah;
@@ -121,21 +146,44 @@ public class SpoofSignatureVerificationPatch {
// Videos with custom captions that specify screen positions appear to always have correct screen positions (even with spoofing).
// But for auto generated and most other captions, the spoof incorrectly gives various default Shorts caption settings.
// Check for these known default shorts captions parameters, and replace with the known correct values.
if (signatureSpoofing && !PlayerType.getCurrent().isNoneOrHidden()) { // video is not a Short or Story
//
// If a regular video uses a custom subtitle setting that match a default short setting,
// then this will incorrectly replace the setting.
// But, if the video uses multiple subtitles in different screen locations, then detect the non-default values
// and do not replace any window settings for the video (regardless if they match a shorts default).
if (signatureSpoofing && !PlayerType.getCurrent().isNoneOrHidden()
&& numberOfNonDefaultSettingsObserved < NUMBER_OF_NON_DEFAULT_SUBTITLES_BEFORE_ENABLING_PASSTHRU) {
for (SubtitleWindowReplacementSettings setting : SubtitleWindowReplacementSettings.values()) {
if (setting.match(ap, ah, av, vs, sd)) {
return setting.replacementSetting();
}
}
// Parameters are either subtitles with custom positions, or a set of unidentified (and incorrect) default parameters.
// The subtitles could be forced to the bottom no matter what, but that would override custom screen positions.
// For now, just return the original parameters.
numberOfNonDefaultSettingsObserved++;
LogHelper.printDebug(() ->
numberOfNonDefaultSettingsObserved < NUMBER_OF_NON_DEFAULT_SUBTITLES_BEFORE_ENABLING_PASSTHRU
? "Non default subtitle found."
: "Multiple non default subtitles found. Allowing all subtitles for this video to pass thru unchanged.");
}
// No matches, pass back the original values
return new int[]{ap, ah, av};
}
/**
* Injection point.
*/
public static void setCurrentVideoId(@NonNull String videoId) {
try {
if (videoId.equals(currentVideoId)) {
return;
}
currentVideoId = videoId;
numberOfNonDefaultSettingsObserved = 0;
} catch (Exception ex) {
LogHelper.printException(() -> "setCurrentVideoId failure", ex);
}
}
/**
* Known incorrect default Shorts subtitle parameters, and the corresponding correct (non-Shorts) values.
@@ -152,8 +200,8 @@ public class SpoofSignatureVerificationPatch {
final int ap, ah, av;
final boolean vs, sd;
// replacement values
final int replacementAp, replacementAh, replacementAv;
// replacement int values
final int[] replacement;
SubtitleWindowReplacementSettings(int ap, int ah, int av, boolean vs, boolean sd,
int replacementAp, int replacementAh, int replacementAv) {
@@ -162,9 +210,7 @@ public class SpoofSignatureVerificationPatch {
this.av = av;
this.vs = vs;
this.sd = sd;
this.replacementAp = replacementAp;
this.replacementAh = replacementAh;
this.replacementAv = replacementAv;
this.replacement = new int[]{replacementAp, replacementAh, replacementAv};
}
boolean match(int ap, int ah, int av, boolean vs, boolean sd) {
@@ -172,7 +218,7 @@ public class SpoofSignatureVerificationPatch {
}
int[] replacementSetting() {
return new int[]{replacementAp, replacementAh, replacementAv};
return replacement;
}
}
}

View File

@@ -42,7 +42,7 @@ public final class VideoInformation {
try {
seekMethod = thisRef.getClass().getMethod(SEEK_METHOD_NAME, Long.TYPE);
seekMethod.setAccessible(true);
} catch (NoSuchMethodException ex) {
} catch (Exception ex) {
LogHelper.printException(() -> "Failed to initialize", ex);
}
}
@@ -141,26 +141,25 @@ public final class VideoInformation {
* @return The id of the video. Empty string if not set yet.
*/
@NonNull
public static String getCurrentVideoId() {
public static String getVideoId() {
return videoId;
}
/**
* @return The current playback speed.
*/
public static float getCurrentPlaybackSpeed() {
public static float getPlaybackSpeed() {
return playbackSpeed;
}
/**
* Length of the current video playing.
* Includes Shorts playback.
* Length of the current video playing. Includes Shorts and YouTube Stories.
*
* @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,
* then this returns zero.
*/
public static long getCurrentVideoLength() {
public static long getVideoLength() {
return videoLength;
}
@@ -172,7 +171,7 @@ public final class VideoInformation {
* should use the callback video time and avoid using this method
* (in situations of recursive hook callbacks, the value returned here may be outdated).
*
* Includes Shorts playback.
* Includes Shorts and YouTube Stories.
*
* @return The time of the video in milliseconds. -1 if not set yet.
*/

View File

@@ -0,0 +1,9 @@
package app.revanced.integrations.patches;
import app.revanced.integrations.settings.SettingsEnum;
public final class WideSearchbarPatch {
public static boolean enableWideSearchbar() {
return SettingsEnum.WIDE_SEARCHBAR.getBoolean();
}
}

View File

@@ -49,7 +49,7 @@ public final class RememberPlaybackSpeedPatch {
* Overrides the video speed. Called after video loads, and immediately after user selects a different playback speed
*/
public static float getPlaybackSpeedOverride() {
return VideoInformation.getCurrentPlaybackSpeed();
return VideoInformation.getPlaybackSpeed();
}
/**

View File

@@ -203,7 +203,7 @@ public class ReturnYouTubeDislikeApi {
@SuppressWarnings("NonAtomicOperationOnVolatileField") // do not want to pay performance cost of full synchronization for debug fields that are only estimates anyways
private static void updateStatistics(long timeNetworkCallStarted, long timeNetworkCallEnded, boolean connectionError, boolean rateLimitHit) {
if (connectionError && rateLimitHit) {
throw new IllegalArgumentException("both connection error and rate limit parameter were true");
throw new IllegalArgumentException();
}
final long responseTimeOfFetchCall = timeNetworkCallEnded - timeNetworkCallStarted;
fetchCallResponseTimeTotal += responseTimeOfFetchCall;
@@ -320,7 +320,7 @@ public class ReturnYouTubeDislikeApi {
return confirmRegistration(userId, solution);
}
LogHelper.printException(() -> "Failed to register new user: " + userId
+ " response code was: " + responseCode);
+ " response code was: " + responseCode); // failed attempt, and ok to log userId
connection.disconnect();
} catch (Exception ex) {
LogHelper.printException(() -> "Failed to register user", ex);
@@ -337,7 +337,7 @@ public class ReturnYouTubeDislikeApi {
if (checkIfRateLimitInEffect("confirmRegistration")) {
return null;
}
LogHelper.printDebug(() -> "Trying to confirm registration for user: " + userId + " with solution: " + solution);
LogHelper.printDebug(() -> "Trying to confirm registration with solution: " + solution);
HttpURLConnection connection = getRYDConnectionFromRoute(ReturnYouTubeDislikeRoutes.CONFIRM_REGISTRATION, userId);
applyCommonPostRequestSettings(connection);
@@ -355,7 +355,7 @@ public class ReturnYouTubeDislikeApi {
if (responseCode == HTTP_STATUS_CODE_SUCCESS) {
String result = Requester.parseJson(connection);
if (result.equalsIgnoreCase("true")) {
LogHelper.printDebug(() -> "Registration confirmation successful for user: " + userId);
LogHelper.printDebug(() -> "Registration confirmation successful");
return userId;
}
LogHelper.printException(() -> "Failed to confirm registration for user: " + userId
@@ -382,8 +382,7 @@ public class ReturnYouTubeDislikeApi {
if (checkIfRateLimitInEffect("sendVote")) {
return false;
}
LogHelper.printDebug(() -> "Trying to vote for video: "
+ videoId + " with vote: " + vote + " user: " + userId);
LogHelper.printDebug(() -> "Trying to vote for video: " + videoId + " with vote: " + vote);
HttpURLConnection connection = getRYDConnectionFromRoute(ReturnYouTubeDislikeRoutes.SEND_VOTE);
applyCommonPostRequestSettings(connection);
@@ -408,11 +407,10 @@ public class ReturnYouTubeDislikeApi {
return confirmVote(videoId, userId, solution);
}
LogHelper.printException(() -> "Failed to send vote for video: " + videoId
+ " userId: " + userId + " vote: " + vote + " response code was: " + responseCode);
+ " vote: " + vote + " response code was: " + responseCode);
connection.disconnect(); // something went wrong, might as well disconnect
} catch (Exception ex) {
LogHelper.printException(() -> "Failed to send vote for video: " + videoId
+ " user: " + userId + " vote: " + vote, ex);
LogHelper.printException(() -> "Failed to send vote for video: " + videoId + " vote: " + vote, ex);
}
return false;
}
@@ -427,8 +425,7 @@ public class ReturnYouTubeDislikeApi {
if (checkIfRateLimitInEffect("confirmVote")) {
return false;
}
LogHelper.printDebug(() -> "Trying to confirm vote for video: "
+ videoId + " user: " + userId + " solution: " + solution);
LogHelper.printDebug(() -> "Trying to confirm vote for video: " + videoId + " solution: " + solution);
HttpURLConnection connection = getRYDConnectionFromRoute(ReturnYouTubeDislikeRoutes.CONFIRM_VOTE);
applyCommonPostRequestSettings(connection);
@@ -450,15 +447,15 @@ public class ReturnYouTubeDislikeApi {
return true;
}
LogHelper.printException(() -> "Failed to confirm vote for video: " + videoId
+ " user: " + userId + " solution: " + solution + " response string was: " + result);
+ " solution: " + solution + " response string was: " + result);
} else {
LogHelper.printException(() -> "Failed to confirm vote for video: " + videoId
+ " user: " + userId + " solution: " + solution + " response code was: " + responseCode);
+ " solution: " + solution + " response code was: " + responseCode);
}
connection.disconnect(); // something went wrong, might as well disconnect
} catch (Exception ex) {
LogHelper.printException(() -> "Failed to confirm vote for video: " + videoId
+ " user: " + userId + " solution: " + solution, ex);
+ " solution: " + solution, ex);
}
return false;
}

View File

@@ -19,13 +19,12 @@ import app.revanced.integrations.utils.StringRef;
public enum SettingsEnum {
//Download Settings
// TODO: DOWNLOAD_PATH("revanced_download_path", STRING, Environment.getExternalStorageDirectory().getPath() + "/Download"),
DOWNLOADS_BUTTON_SHOWN("revanced_downloads_enabled", BOOLEAN, TRUE, true),
DOWNLOADS_BUTTON_SHOWN("revanced_downloads_enabled", BOOLEAN, TRUE),
DOWNLOADS_PACKAGE_NAME("revanced_downloads_package_name", STRING, "org.schabi.newpipe" /* NewPipe */, parents(DOWNLOADS_BUTTON_SHOWN)),
// Copy video URL settings
COPY_VIDEO_URL_BUTTON_SHOWN("revanced_copy_video_url_enabled", BOOLEAN, TRUE, true),
COPY_VIDEO_URL_TIMESTAMP_BUTTON_SHOWN("revanced_copy_video_url_timestamp_enabled", BOOLEAN, TRUE, true),
COPY_VIDEO_URL_BUTTON_SHOWN("revanced_copy_video_url_enabled", BOOLEAN, TRUE),
COPY_VIDEO_URL_TIMESTAMP_BUTTON_SHOWN("revanced_copy_video_url_timestamp_enabled", BOOLEAN, TRUE),
// Video settings
OLD_STYLE_VIDEO_QUALITY_PLAYER_SETTINGS("revanced_use_old_style_quality_settings", BOOLEAN, TRUE),
@@ -71,12 +70,11 @@ public enum SettingsEnum {
VIDEO_ADS_REMOVAL("revanced_video_ads_removal", BOOLEAN, TRUE, true),
// Action buttons
HIDE_ACTION_BUTTON("revanced_hide_action_button", BOOLEAN, FALSE),
HIDE_DISLIKE_BUTTON("revanced_hide_dislike_button", BOOLEAN, FALSE),
HIDE_LIKE_DISLIKE_BUTTON("revanced_hide_like_dislike_button", BOOLEAN, FALSE),
HIDE_DOWNLOAD_BUTTON("revanced_hide_download_button", BOOLEAN, FALSE),
HIDE_LIKE_BUTTON("revanced_hide_like_button", BOOLEAN, FALSE),
HIDE_PLAYLIST_BUTTON("revanced_hide_playlist_button", BOOLEAN, FALSE),
HIDE_SHARE_BUTTON("revanced_hide_share_button", BOOLEAN, FALSE),
HIDE_CLIP_BUTTON("revanced_hide_clip_button", BOOLEAN, FALSE, "revanced_hide_clip_button_user_dialog_message"),
HIDE_ACTION_BUTTONS("revanced_hide_action_buttons", BOOLEAN, FALSE),
// Layout settings
DISABLE_STARTUP_SHORTS_PLAYER("revanced_startup_shorts_player_enabled", BOOLEAN, FALSE),
@@ -94,7 +92,6 @@ public enum SettingsEnum {
HIDE_FLOATING_MICROPHONE_BUTTON("revanced_hide_floating_microphone_button", BOOLEAN, TRUE, true),
HIDE_FULLSCREEN_PANELS("revanced_hide_fullscreen_panels", BOOLEAN, TRUE),
HIDE_INFO_CARDS("revanced_hide_infocards", BOOLEAN, TRUE),
HIDE_MIX_PLAYLISTS("revanced_hide_mix_playlists", BOOLEAN, FALSE, true),
HIDE_PLAYER_BUTTONS("revanced_hide_player_buttons", BOOLEAN, FALSE),
HIDE_PREVIEW_COMMENT("revanced_hide_preview_comment", BOOLEAN, FALSE, true),
HIDE_SEEKBAR("revanced_hide_seekbar", BOOLEAN, FALSE),
@@ -105,6 +102,7 @@ public enum SettingsEnum {
HIDE_WATCH_IN_VR("revanced_hide_watch_in_vr", BOOLEAN, FALSE, true),
PLAYER_POPUP_PANELS("revanced_player_popup_panels_enabled", BOOLEAN, FALSE),
SPOOF_APP_VERSION("revanced_spoof_app_version", BOOLEAN, FALSE, true, "revanced_spoof_app_version_user_dialog_message"),
SPOOF_APP_VERSION_TARGET("revanced_spoof_app_version_target", STRING, "17.30.35", true, parents(SPOOF_APP_VERSION)),
USE_TABLET_MINIPLAYER("revanced_tablet_miniplayer", BOOLEAN, FALSE, true),
WIDE_SEARCHBAR("revanced_wide_searchbar", BOOLEAN, FALSE, true),
@@ -113,7 +111,6 @@ public enum SettingsEnum {
CAPTIONS_ENABLED("revanced_autocaptions_enabled", BOOLEAN, FALSE),
DISABLE_ZOOM_HAPTICS("revanced_disable_zoom_haptics", BOOLEAN, TRUE),
ENABLE_EXTERNAL_BROWSER("revanced_enable_external_browser", BOOLEAN, TRUE, true),
ENABLE_MINIMIZED_PLAYBACK("revanced_enable_minimized_playback", BOOLEAN, TRUE),
PREFERRED_AUTO_REPEAT("revanced_pref_auto_repeat", BOOLEAN, FALSE),
TAP_SEEKING_ENABLED("revanced_enable_tap_seeking", BOOLEAN, TRUE),
USE_HDR_AUTO_BRIGHTNESS("revanced_pref_hdr_autobrightness", BOOLEAN, TRUE),
@@ -149,7 +146,8 @@ public enum SettingsEnum {
SB_ENABLED("sb-enabled", BOOLEAN, TRUE, SPONSOR_BLOCK),
SB_VOTING_ENABLED("sb-voting-enabled", BOOLEAN, FALSE, SPONSOR_BLOCK, parents(SB_ENABLED)),
SB_CREATE_NEW_SEGMENT_ENABLED("sb-new-segment-enabled", BOOLEAN, FALSE, SPONSOR_BLOCK, parents(SB_ENABLED)),
SB_USE_COMPACT_SKIPBUTTON("sb-use-compact-skip-button", BOOLEAN, FALSE, SPONSOR_BLOCK, parents(SB_ENABLED)),
SB_USE_COMPACT_SKIP_BUTTON("sb-use-compact-skip-button", BOOLEAN, FALSE, SPONSOR_BLOCK, parents(SB_ENABLED)),
SB_AUTO_HIDE_SKIP_BUTTON("sb-auto-hide-skip-segment-button", BOOLEAN, TRUE, SPONSOR_BLOCK, parents(SB_ENABLED)),
SB_SHOW_TOAST_ON_SKIP("show-toast", BOOLEAN, TRUE, SPONSOR_BLOCK, parents(SB_ENABLED)),
SB_TRACK_SKIP_COUNT("count-skips", BOOLEAN, TRUE, SPONSOR_BLOCK, parents(SB_ENABLED)),
SB_UUID("uuid", STRING, "", SPONSOR_BLOCK),

View File

@@ -15,7 +15,6 @@ import java.lang.ref.WeakReference;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.Arrays;
import java.util.Date;
import java.util.Objects;
import java.util.TimeZone;
@@ -157,13 +156,13 @@ public class SponsorBlockUtils {
private static final DialogInterface.OnClickListener segmentVoteClickListener = (dialog, which) -> {
try {
final Context context = ((AlertDialog) dialog).getContext();
SponsorSegment[] currentSegments = SegmentPlaybackController.getSegmentsOfCurrentVideo();
if (currentSegments == null || currentSegments.length == 0) {
SponsorSegment[] segments = SegmentPlaybackController.getSegments();
if (segments == null || segments.length == 0) {
// should never be reached
LogHelper.printException(() -> "Segment is no longer available on the client");
return;
}
SponsorSegment segment = currentSegments[which];
SponsorSegment segment = segments[which];
SegmentVote[] voteOptions = (segment.category == SegmentCategory.HIGHLIGHT)
? SegmentVote.voteTypesWithoutCategoryChange // highlight segments cannot change category
@@ -218,8 +217,8 @@ public class SponsorBlockUtils {
final String uuid = SettingsEnum.SB_UUID.getString();
final long start = newSponsorSegmentStartMillis;
final long end = newSponsorSegmentEndMillis;
final String videoId = VideoInformation.getCurrentVideoId();
final long videoLength = VideoInformation.getCurrentVideoLength();
final String videoId = VideoInformation.getVideoId();
final long videoLength = VideoInformation.getVideoLength();
final SegmentCategory segmentCategory = newUserCreatedSegmentCategory;
if (start < 0 || end < 0 || start >= end || videoLength <= 0 || videoId.isEmpty()
|| segmentCategory == null || uuid.isEmpty()) {
@@ -287,33 +286,33 @@ public class SponsorBlockUtils {
public static void onVotingClicked(@NonNull Context context) {
try {
ReVancedUtils.verifyOnMainThread();
SponsorSegment[] currentSegments = SegmentPlaybackController.getSegmentsOfCurrentVideo();
if (currentSegments == null || currentSegments.length == 0) {
// button is hidden if no segments exist.
SponsorSegment[] segments = SegmentPlaybackController.getSegments();
if (segments == null || segments.length == 0) {
// Button is hidden if no segments exist.
// But if prior video had segments, and current video does not,
// then the button persists until the overlay fades out (this is intentional, as abruptly hiding the button is jarring)
// then the button persists until the overlay fades out (this is intentional, as abruptly hiding the button is jarring).
ReVancedUtils.showToastShort(str("sb_vote_no_segments"));
return;
}
// use same time formatting as shown in the video player
final long currentVideoLength = VideoInformation.getCurrentVideoLength();
final long videoLength = VideoInformation.getVideoLength();
final String formatPattern;
if (currentVideoLength < (10 * 60 * 1000)) {
formatPattern = "m:ss"; // less than 10 minutes
} else if (currentVideoLength < (60 * 60 * 1000)) {
formatPattern = "mm:ss"; // less than 1 hour
} else if (currentVideoLength < (10 * 60 * 60 * 1000)) {
formatPattern = "H:mm:ss"; // less than 10 hours
if (videoLength < (10 * 60 * 1000)) {
formatPattern = "m:ss.SSS"; // less than 10 minutes
} else if (videoLength < (60 * 60 * 1000)) {
formatPattern = "mm:ss.SSS"; // less than 1 hour
} else if (videoLength < (10 * 60 * 60 * 1000)) {
formatPattern = "H:mm:ss.SSS"; // less than 10 hours
} else {
formatPattern = "HH:mm:ss"; // why is this on YouTube
formatPattern = "HH:mm:ss.SSS"; // why is this on YouTube
}
voteSegmentTimeFormatter.applyPattern(formatPattern);
final int numberOfSegments = currentSegments.length;
final int numberOfSegments = segments.length;
CharSequence[] titles = new CharSequence[numberOfSegments];
for (int i = 0; i < numberOfSegments; i++) {
SponsorSegment segment = currentSegments[i];
SponsorSegment segment = segments[i];
if (segment.category == SegmentCategory.UNSUBMITTED) {
continue;
}
@@ -364,14 +363,11 @@ public class SponsorBlockUtils {
} else if (newSponsorSegmentStartMillis >= newSponsorSegmentEndMillis) {
ReVancedUtils.showToastShort(str("sb_new_segment_start_is_before_end"));
} else {
SegmentPlaybackController.removeUnsubmittedSegments(); // If user hits preview more than once before playing.
SegmentPlaybackController.addUnsubmittedSegment(
new SponsorSegment(SegmentCategory.UNSUBMITTED, null,
newSponsorSegmentStartMillis, newSponsorSegmentEndMillis, false));
VideoInformation.seekTo(newSponsorSegmentStartMillis - 2500);
final SponsorSegment[] original = SegmentPlaybackController.getSegmentsOfCurrentVideo();
final SponsorSegment[] segments = original == null ? new SponsorSegment[1] : Arrays.copyOf(original, original.length + 1);
segments[segments.length - 1] = new SponsorSegment(SegmentCategory.UNSUBMITTED, null,
newSponsorSegmentStartMillis, newSponsorSegmentEndMillis, false);
SegmentPlaybackController.setSegmentsOfCurrentVideo(segments);
}
} catch (Exception ex) {
LogHelper.printException(() -> "onPreviewClicked failure", ex);

View File

@@ -300,7 +300,7 @@ public enum SegmentCategory {
*/
@NonNull
StringRef getSkipButtonText(long segmentStartTime, long videoLength) {
if (SettingsEnum.SB_USE_COMPACT_SKIPBUTTON.getBoolean()) {
if (SettingsEnum.SB_USE_COMPACT_SKIP_BUTTON.getBoolean()) {
return (this == SegmentCategory.HIGHLIGHT)
? skipSponsorTextCompactHighlight
: skipSponsorTextCompact;

View File

@@ -1,13 +1,14 @@
package app.revanced.integrations.sponsorblock.objects;
import static app.revanced.integrations.utils.StringRef.sf;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import app.revanced.integrations.patches.VideoInformation;
import app.revanced.integrations.utils.StringRef;
import java.util.Objects;
import static app.revanced.integrations.utils.StringRef.sf;
public class SponsorSegment implements Comparable<SponsorSegment> {
public enum SegmentVote {
UPVOTE(sf("sb_vote_upvote"), 1,false),
@@ -99,7 +100,7 @@ public class SponsorSegment implements Comparable<SponsorSegment> {
*/
@NonNull
public String getSkipButtonText() {
return category.getSkipButtonText(start, VideoInformation.getCurrentVideoLength()).toString();
return category.getSkipButtonText(start, VideoInformation.getVideoLength()).toString();
}
/**
@@ -107,12 +108,30 @@ public class SponsorSegment implements Comparable<SponsorSegment> {
*/
@NonNull
public String getSkippedToastText() {
return category.getSkippedToastText(start, VideoInformation.getCurrentVideoLength()).toString();
return category.getSkippedToastText(start, VideoInformation.getVideoLength()).toString();
}
@Override
public int compareTo(SponsorSegment o) {
return (int) (this.start - o.start);
// If both segments start at the same time, then sort with the longer segment first.
// This keeps the seekbar drawing correct since it draws the segments using the sorted order.
return start == o.start ? Long.compare(o.length(), length()) : Long.compare(start, o.start);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof SponsorSegment)) return false;
SponsorSegment other = (SponsorSegment) o;
return Objects.equals(UUID, other.UUID)
&& category == other.category
&& start == other.start
&& end == other.end;
}
@Override
public int hashCode() {
return Objects.hashCode(UUID);
}
@NonNull

View File

@@ -97,6 +97,33 @@ public class SBRequester {
} catch (Exception ex) {
LogHelper.printException(() -> "Failed to get segments", ex, str("sb_sponsorblock_connection_failure_generic"));
}
// Crude debug tests to verify random features
// Could benefit from:
// 1) collection of YouTube videos with test segment times (verify client skip timing matches the video, verify seekbar draws correctly)
// 2) unit tests (verify everything else)
if (false) {
segments.clear();
// Test auto-hide skip button:
// Button should appear only once
segments.add(new SponsorSegment(SegmentCategory.INTRO, "debug", 5000, 120000, false));
// Button should appear only once
segments.add(new SponsorSegment(SegmentCategory.SELF_PROMO, "debug", 10000, 60000, false));
// Button should appear only once
segments.add(new SponsorSegment(SegmentCategory.INTERACTION, "debug", 15000, 20000, false));
// Button should appear _twice_ (at 21s and 27s)
segments.add(new SponsorSegment(SegmentCategory.SPONSOR, "debug", 21000, 30000, false));
// Button should appear only once
segments.add(new SponsorSegment(SegmentCategory.OUTRO, "debug", 24000, 27000, false));
// Test seekbar visibility:
// All three segments should be viewable on the seekbar
segments.add(new SponsorSegment(SegmentCategory.MUSIC_OFFTOPIC, "debug", 200000, 300000, false));
segments.add(new SponsorSegment(SegmentCategory.SPONSOR, "debug", 200000, 250000, false));
segments.add(new SponsorSegment(SegmentCategory.SELF_PROMO, "debug", 200000, 330000, false));
}
return segments.toArray(new SponsorSegment[0]);
}

View File

@@ -1,8 +1,5 @@
package app.revanced.integrations.sponsorblock.ui;
import static app.revanced.integrations.utils.ReVancedUtils.getResourceDimensionPixelSize;
import static app.revanced.integrations.utils.ReVancedUtils.getResourceIdentifier;
import android.content.Context;
import android.content.res.ColorStateList;
import android.graphics.drawable.RippleDrawable;
@@ -11,114 +8,119 @@ import android.util.TypedValue;
import android.view.LayoutInflater;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import app.revanced.integrations.patches.VideoInformation;
import app.revanced.integrations.settings.SettingsEnum;
import app.revanced.integrations.sponsorblock.SponsorBlockUtils;
import app.revanced.integrations.utils.LogHelper;
public class NewSegmentLayout extends FrameLayout {
import static app.revanced.integrations.utils.ReVancedUtils.getResourceDimensionPixelSize;
import static app.revanced.integrations.utils.ReVancedUtils.getResourceIdentifier;
public final class NewSegmentLayout extends FrameLayout {
private static final ColorStateList rippleColorStateList = new ColorStateList(
new int[][]{new int[]{android.R.attr.state_enabled}},
new int[]{0x33ffffff} // sets the ripple color to white
);
private final int rippleEffectId;
final int defaultBottomMargin;
final int ctaBottomMargin;
public NewSegmentLayout(Context context) {
public NewSegmentLayout(final Context context) {
this(context, null);
}
public NewSegmentLayout(Context context, AttributeSet attributeSet) {
public NewSegmentLayout(final Context context, final AttributeSet attributeSet) {
this(context, attributeSet, 0);
}
public NewSegmentLayout(Context context, AttributeSet attributeSet, int defStyleAttr) {
public NewSegmentLayout(final Context context, final AttributeSet attributeSet, final int defStyleAttr) {
this(context, attributeSet, defStyleAttr, 0);
}
public NewSegmentLayout(Context context, AttributeSet attributeSet, int defStyleAttr, int defStyleRes) {
public NewSegmentLayout(final Context context, final AttributeSet attributeSet,
final int defStyleAttr, final int defStyleRes) {
super(context, attributeSet, defStyleAttr, defStyleRes);
LayoutInflater.from(context).inflate(getResourceIdentifier(context, "new_segment", "layout"), this, true);
LayoutInflater.from(context).inflate(
getResourceIdentifier(context, "new_segment", "layout"), this, true
);
TypedValue rippleEffect = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.selectableItemBackground, rippleEffect, true);
rippleEffectId = rippleEffect.resourceId;
// LinearLayout newSegmentContainer = findViewById(getResourceIdentifier(context, "sb_new_segment_container", "id"));
initializeButton(
context,
"sb_new_segment_rewind",
() -> VideoInformation.seekToRelative(-SettingsEnum.SB_ADJUST_NEW_SEGMENT_STEP.getInt()),
"Rewind button clicked"
);
ImageButton rewindButton = findViewById(getResourceIdentifier(context, "sb_new_segment_rewind", "id"));
if (rewindButton == null) {
LogHelper.printException(() -> "Could not find rewindButton");
} else {
setClickEffect(rewindButton);
rewindButton.setOnClickListener(v -> {
LogHelper.printDebug(() -> "Rewind button clicked");
VideoInformation.seekToRelative(-SettingsEnum.SB_ADJUST_NEW_SEGMENT_STEP.getInt());
});
}
ImageButton forwardButton = findViewById(getResourceIdentifier(context, "sb_new_segment_forward", "id"));
if (forwardButton == null) {
LogHelper.printException(() -> "Could not find forwardButton");
} else {
setClickEffect(forwardButton);
forwardButton.setOnClickListener(v -> {
LogHelper.printDebug(() -> "Forward button clicked");
VideoInformation.seekToRelative(SettingsEnum.SB_ADJUST_NEW_SEGMENT_STEP.getInt());
});
}
ImageButton adjustButton = findViewById(getResourceIdentifier(context, "sb_new_segment_adjust", "id"));
if (adjustButton == null) {
LogHelper.printException(() -> "Could not find adjustButton");
} else {
setClickEffect(adjustButton);
adjustButton.setOnClickListener(v -> {
LogHelper.printDebug(() -> "Adjust button clicked");
SponsorBlockUtils.onMarkLocationClicked();
});
}
ImageButton compareButton = findViewById(getResourceIdentifier(context, "sb_new_segment_compare", "id"));
if (compareButton == null) {
LogHelper.printException(() -> "Could not find compareButton");
} else {
setClickEffect(compareButton);
compareButton.setOnClickListener(v -> {
LogHelper.printDebug(() -> "Compare button clicked");
SponsorBlockUtils.onPreviewClicked();
});
}
ImageButton editButton = findViewById(getResourceIdentifier(context, "sb_new_segment_edit", "id"));
if (editButton == null) {
LogHelper.printException(() -> "Could not find editButton");
} else {
setClickEffect(editButton);
editButton.setOnClickListener(v -> {
LogHelper.printDebug(() -> "Edit button clicked");
SponsorBlockUtils.onEditByHandClicked();
});
}
ImageButton publishButton = findViewById(getResourceIdentifier(context, "sb_new_segment_publish", "id"));
if (publishButton == null) {
LogHelper.printException(() -> "Could not find publishButton");
} else {
setClickEffect(publishButton);
publishButton.setOnClickListener(v -> {
LogHelper.printDebug(() -> "Publish button clicked");
SponsorBlockUtils.onPublishClicked();
});
}
initializeButton(
context,
"sb_new_segment_forward",
() -> VideoInformation.seekToRelative(SettingsEnum.SB_ADJUST_NEW_SEGMENT_STEP.getInt()),
"Forward button clicked"
);
initializeButton(
context,
"sb_new_segment_adjust",
SponsorBlockUtils::onMarkLocationClicked,
"Adjust button clicked"
);
initializeButton(
context,
"sb_new_segment_compare",
SponsorBlockUtils::onPreviewClicked,
"Compare button clicked"
);
initializeButton(
context,
"sb_new_segment_edit",
SponsorBlockUtils::onEditByHandClicked,
"Edit button clicked"
);
initializeButton(
context,
"sb_new_segment_publish",
SponsorBlockUtils::onPublishClicked,
"Publish button clicked"
);
defaultBottomMargin = getResourceDimensionPixelSize("brand_interaction_default_bottom_margin");
ctaBottomMargin = getResourceDimensionPixelSize("brand_interaction_cta_bottom_margin");
}
private void setClickEffect(ImageButton btn) {
btn.setBackgroundResource(rippleEffectId);
/**
* Initializes a segment button with the given resource identifier name with the given handler and a ripple effect.
*
* @param context The context.
* @param resourceIdentifierName The resource identifier name for the button.
* @param handler The handler for the button's click event.
* @param debugMessage The debug message to print when the button is clicked.
*/
private void initializeButton(final Context context, final String resourceIdentifierName,
final ButtonOnClickHandlerFunction handler, final String debugMessage) {
final ImageButton button = findViewById(getResourceIdentifier(context, resourceIdentifierName, "id"));
RippleDrawable rippleDrawable = (RippleDrawable) btn.getBackground();
// Add ripple effect
button.setBackgroundResource(rippleEffectId);
RippleDrawable rippleDrawable = (RippleDrawable) button.getBackground();
rippleDrawable.setColor(rippleColorStateList);
int[][] states = new int[][]{new int[]{android.R.attr.state_enabled}};
int[] colors = new int[]{0x33ffffff}; // sets the ripple color to white
button.setOnClickListener((v) -> {
handler.apply();
LogHelper.printDebug(() -> debugMessage);
});
}
ColorStateList colorStateList = new ColorStateList(states, colors);
rippleDrawable.setColor(colorStateList);
@FunctionalInterface
public interface ButtonOnClickHandlerFunction {
void apply();
}
}

View File

@@ -10,6 +10,7 @@ import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -20,7 +21,6 @@ import java.util.Objects;
import app.revanced.integrations.sponsorblock.SegmentPlaybackController;
import app.revanced.integrations.sponsorblock.objects.SponsorSegment;
import app.revanced.integrations.utils.LogHelper;
public class SkipSponsorButton extends FrameLayout {
private static final boolean highContrast = true;
@@ -62,6 +62,8 @@ public class SkipSponsorButton extends FrameLayout {
ctaBottomMargin = getResourceDimensionPixelSize("skip_button_cta_bottom_margin"); // dimen:skip_button_cta_bottom_margin
skipSponsorBtnContainer.setOnClickListener(v -> {
// The view controller handles hiding this button, but hide it here as well just in case something goofs.
setVisibility(View.GONE);
SegmentPlaybackController.onSkipSegmentClicked(segment);
});
}

View File

@@ -55,6 +55,9 @@ public class SponsorBlockViewController {
try {
LogHelper.printDebug(() -> "initializing");
// hide any old components, just in case they somehow are still hanging around
hideAll();
Context context = ReVancedUtils.getContext();
RelativeLayout layout = new RelativeLayout(context);
layout.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,RelativeLayout.LayoutParams.MATCH_PARENT));
@@ -103,7 +106,7 @@ public class SponsorBlockViewController {
skipHighlight = Objects.requireNonNull(segment);
NewSegmentLayout newSegmentLayout = newSegmentLayoutRef.get();
// don't show highlight button if create new segment is visible
final boolean buttonVisibility = newSegmentLayout != null && newSegmentLayout.getVisibility() != View.VISIBLE;
final boolean buttonVisibility = newSegmentLayout == null || newSegmentLayout.getVisibility() != View.VISIBLE;
updateSkipButton(skipHighlightButtonRef.get(), segment, buttonVisibility);
}
public static void showSkipSegmentButton(@NonNull SponsorSegment segment) {
@@ -146,11 +149,7 @@ public class SponsorBlockViewController {
public static void hideNewSegmentLayout() {
newSegmentLayoutVisible = false;
NewSegmentLayout newSegmentLayout = newSegmentLayoutRef.get();
if (newSegmentLayout == null) {
return;
}
setViewVisibility(newSegmentLayout, false);
setViewVisibility(newSegmentLayoutRef.get(), false);
}
private static void setViewVisibility(@Nullable View view, boolean visible) {

View File

@@ -106,7 +106,7 @@ public class VotingButtonController {
private static boolean shouldBeShown() {
return SettingsEnum.SB_ENABLED.getBoolean() && SettingsEnum.SB_VOTING_ENABLED.getBoolean()
&& SegmentPlaybackController.currentVideoHasSegments() && !VideoInformation.isAtEndOfVideo();
&& SegmentPlaybackController.videoHasSegments() && !VideoInformation.isAtEndOfVideo();
}
public static void hide() {

View File

@@ -1,66 +1,64 @@
package app.revanced.integrations.videoplayer;
import android.support.constraint.ConstraintLayout;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.widget.ImageView;
import java.lang.ref.WeakReference;
import androidx.annotation.NonNull;
import app.revanced.integrations.settings.SettingsEnum;
import app.revanced.integrations.utils.LogHelper;
import app.revanced.integrations.utils.ReVancedUtils;
import java.lang.ref.WeakReference;
import java.util.Objects;
public abstract class BottomControlButton {
WeakReference<ImageView> button = new WeakReference<>(null);
ConstraintLayout constraintLayout;
Boolean isButtonEnabled;
Boolean isShowing;
private static final Animation fadeIn = ReVancedUtils.getResourceAnimation("fade_in");
private static final Animation fadeOut = ReVancedUtils.getResourceAnimation("fade_out");
private final WeakReference<ImageView> buttonRef;
private final SettingsEnum setting;
protected boolean isVisible;
private Animation fadeIn;
private Animation fadeOut;
public BottomControlButton(Object obj, String viewId, Boolean isEnabled, View.OnClickListener onClickListener) {
try {
LogHelper.printDebug(() -> "Initializing button with id: " + viewId);
constraintLayout = (ConstraintLayout) obj;
isButtonEnabled = isEnabled;
ImageView imageView = constraintLayout.findViewById(ReVancedUtils.getResourceIdentifier(viewId, "id"));
if (imageView == null) {
LogHelper.printException(() -> "Couldn't find ImageView with id: " + viewId);
return;
}
imageView.setOnClickListener(onClickListener);
button = new WeakReference<>(imageView);
fadeIn = ReVancedUtils.getResourceAnimation("fade_in");
fadeOut = ReVancedUtils.getResourceAnimation("fade_out");
fadeIn.setDuration(ReVancedUtils.getResourceInteger("fade_duration_fast"));
fadeOut.setDuration(ReVancedUtils.getResourceInteger("fade_duration_scheduled"));
isShowing = true;
setVisibility(false);
} catch (Exception e) {
LogHelper.printException(() -> "Failed to initialize button with id: " + viewId, e);
}
static {
// TODO: check if these durations are correct.
fadeIn.setDuration(ReVancedUtils.getResourceInteger("fade_duration_fast"));
fadeOut.setDuration(ReVancedUtils.getResourceInteger("fade_duration_scheduled"));
}
public void setVisibility(boolean showing) {
if (isShowing == showing) return;
public BottomControlButton(@NonNull ViewGroup bottomControlsViewGroup, @NonNull String imageViewButtonId,
@NonNull SettingsEnum booleanSetting, @NonNull View.OnClickListener onClickListener) {
LogHelper.printDebug(() -> "Initializing button: " + imageViewButtonId);
isShowing = showing;
ImageView imageView = button.get();
if (constraintLayout == null || imageView == null)
return;
if (showing && isButtonEnabled) {
LogHelper.printDebug(() -> "Fading in");
imageView.setVisibility(View.VISIBLE);
imageView.startAnimation(fadeIn);
if (booleanSetting.returnType != SettingsEnum.ReturnType.BOOLEAN) {
throw new IllegalArgumentException();
}
else if (imageView.getVisibility() == View.VISIBLE) {
LogHelper.printDebug(() -> "Fading out");
setting = booleanSetting;
// Create the button.
ImageView imageView = Objects.requireNonNull(bottomControlsViewGroup.findViewById(
ReVancedUtils.getResourceIdentifier(imageViewButtonId, "id")
));
imageView.setOnClickListener(onClickListener);
imageView.setVisibility(View.GONE);
buttonRef = new WeakReference<>(imageView);
}
public void setVisibility(boolean visible) {
if (isVisible == visible) return;
isVisible = visible;
ImageView imageView = buttonRef.get();
if (imageView == null) {
return;
}
imageView.clearAnimation();
if (visible && setting.getBoolean()) {
imageView.startAnimation(fadeIn);
imageView.setVisibility(View.VISIBLE);
} else if (imageView.getVisibility() == View.VISIBLE) {
imageView.startAnimation(fadeOut);
imageView.setVisibility(View.GONE);
}

View File

@@ -1,25 +1,40 @@
package app.revanced.integrations.videoplayer;
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import app.revanced.integrations.patches.CopyVideoUrlPatch;
import app.revanced.integrations.settings.SettingsEnum;
import app.revanced.integrations.utils.LogHelper;
public class CopyVideoUrlButton extends BottomControlButton {
public static CopyVideoUrlButton instance;
@Nullable
private static CopyVideoUrlButton instance;
public CopyVideoUrlButton(Object obj) {
public CopyVideoUrlButton(ViewGroup viewGroup) {
super(
obj,
viewGroup,
"copy_video_url_button",
SettingsEnum.COPY_VIDEO_URL_BUTTON_SHOWN.getBoolean(),
SettingsEnum.COPY_VIDEO_URL_BUTTON_SHOWN,
view -> CopyVideoUrlPatch.copyUrl(false)
);
}
/**
* Injection point.
*/
public static void initializeButton(Object obj) {
instance = new CopyVideoUrlButton(obj);
try {
instance = new CopyVideoUrlButton((ViewGroup) obj);
} catch (Exception ex) {
LogHelper.printException(() -> "initializeButton failure", ex);
}
}
/**
* Injection point.
*/
public static void changeVisibility(boolean showing) {
if (instance != null) instance.setVisibility(showing);
}

View File

@@ -1,24 +1,40 @@
package app.revanced.integrations.videoplayer;
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import app.revanced.integrations.patches.CopyVideoUrlPatch;
import app.revanced.integrations.settings.SettingsEnum;
import app.revanced.integrations.utils.LogHelper;
public class CopyVideoUrlTimestampButton extends BottomControlButton {
public static CopyVideoUrlTimestampButton instance;
@Nullable
private static CopyVideoUrlTimestampButton instance;
public CopyVideoUrlTimestampButton(Object obj) {
public CopyVideoUrlTimestampButton(ViewGroup bottomControlsViewGroup) {
super(
obj,
bottomControlsViewGroup,
"copy_video_url_timestamp_button",
SettingsEnum.COPY_VIDEO_URL_TIMESTAMP_BUTTON_SHOWN.getBoolean(),
SettingsEnum.COPY_VIDEO_URL_TIMESTAMP_BUTTON_SHOWN,
view -> CopyVideoUrlPatch.copyUrl(true)
);
}
public static void initializeButton(Object obj) {
instance = new CopyVideoUrlTimestampButton(obj);
/**
* Injection point.
*/
public static void initializeButton(Object bottomControlsViewGroup) {
try {
instance = new CopyVideoUrlTimestampButton((ViewGroup) bottomControlsViewGroup);
} catch (Exception ex) {
LogHelper.printException(() -> "initializeButton failure", ex);
}
}
/**
* Injection point.
*/
public static void changeVisibility(boolean showing) {
if (instance != null) instance.setVisibility(showing);
}

View File

@@ -3,6 +3,9 @@ package app.revanced.integrations.videoplayer;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import app.revanced.integrations.patches.VideoInformation;
import app.revanced.integrations.settings.SettingsEnum;
@@ -11,21 +14,32 @@ import app.revanced.integrations.utils.ReVancedUtils;
import app.revanced.integrations.utils.StringRef;
public class DownloadButton extends BottomControlButton {
public static DownloadButton instance;
@Nullable
private static DownloadButton instance;
public DownloadButton(Object obj) {
public DownloadButton(ViewGroup viewGroup) {
super(
obj,
viewGroup,
"download_button",
SettingsEnum.DOWNLOADS_BUTTON_SHOWN.getBoolean(),
SettingsEnum.DOWNLOADS_BUTTON_SHOWN,
DownloadButton::onDownloadClick
);
}
/**
* Injection point.
*/
public static void initializeButton(Object obj) {
instance = new DownloadButton(obj);
try {
instance = new DownloadButton((ViewGroup) obj);
} catch (Exception ex) {
LogHelper.printException(() -> "initializeButton failure", ex);
}
}
/**
* Injection point.
*/
public static void changeVisibility(boolean showing) {
if (instance != null) instance.setVisibility(showing);
}
@@ -38,7 +52,6 @@ public class DownloadButton extends BottomControlButton {
boolean packageEnabled = false;
try {
assert context != null;
packageEnabled = context.getPackageManager().getApplicationInfo(downloaderPackageName, 0).enabled;
} catch (PackageManager.NameNotFoundException error) {
LogHelper.printDebug(() -> "Downloader could not be found: " + error);
@@ -52,7 +65,7 @@ public class DownloadButton extends BottomControlButton {
// Launch PowerTube intent
try {
String content = String.format("https://youtu.be/%s", VideoInformation.getCurrentVideoId());
String content = String.format("https://youtu.be/%s", VideoInformation.getVideoId());
Intent intent = new Intent("android.intent.action.SEND");
intent.setType("text/plain");

Some files were not shown because too many files have changed in this diff Show More