Skip to content

Releases: Sv443/BetterYTM

[PREVIEW] 3.1.0 - Release Candidate 1

14 Mar 18:54

Choose a tag to compare

Pre-release

Important

This version is almost finished but may still contain a few bugs and inconsistencies.
It is highly recommended you fully remove the script and reinstall it once the update is released, as data integrity can't be guaranteed for preview versions.

Click to expand the changelog at the time of 0de089e
  • New features:
    • Add hotkeys to focus and clear the search bar on both pages (closes #145)
    • Improve config menu
      • Add a sidenav to toggle off all but one feature category (closes #140)
      • Add feature groups with headers to logically group features together
      • Add generic markdown sections to render the changelog and an about section
      • Remove advanced mode flag from a lot of features since there's much more space now
    • 🎵 Show the track number in playlists (by @indierodo) (closes #117)
    • 🎵 Use an exponential scale for the volume slider (by @cryeprecision) (closes #157)
    • Require double-pressing the number keys within a configurable time frame to skip to the associated timestamp (closes #152)
    • 🎵 Automatically close the activity check dialog
    • 🎵 Swap like and dislike buttons to match YT's layout
    • 🎵 In fullscreen, also hide the player bar on idle
  • Changes and improvements:
    • 🎵 Overhaul thumbnail overlay to fix massive inconsistencies (closes #143)
      • Fix album artwork being fetched with wrong parameters (closes #149)
      • Allow manually toggling between thumbnail providers
      • Cache resolved AM album artwork URLs similar to how lyrics URLs are currently cached
    • 🎵 Decouple volume slider step and scroll step (closes #102)
    • 🎵 Make the "improve links" feature also apply to all types of song list items
    • Change some default feature values (if left unchanged):
      • initTimeout: from 8 to 5 seconds (because of the now faster init time)
      • rememberSongTimeDuration: from 60 to 180 sec
      • 🎵 thumbnailOverlayITunesImgRes: from 1500 to 2000 px
      • frameSkipAmount: from 0.0417 to 0.0166 seconds (tbr idk how this happened)
    • Migrate to CoreUtils v3.0.0 DataStores
    • Overhaul contributing.md (part 1)
    • Overhaul translations
    • Add typedoc documentation for interface.ts and common dependencies
  • Fixes:
    • Fix share tracking parameter not being removed on YT
    • Fix inconsistent auto-like button rendering (closes #120)
    • Fix DataStores going out of sync across sessions (closes #162)
    • Fix auto-like feature not resolving channel names properly (closes #156)
    • 🎵 Fix SyntaxError when no AM album artwork found (closes #146)
    • Fix Error when clicking on a BytmDialog's exit button (closes #147)
    • Fix config menu not closing on Esc press when other dialog over top was closed with Esc
    • 🎵 Fix list buttons not disappearing with the native buttons in song lists (closes #86)
    • 🎵 Fix anchor improvements feature on the search page (closes #99)
    • 🎵 Fix rounded border in fullscreen mode when using the ThemeSong extension
    • Fix page scroll bar reappearing after BytmDialog opened over top of the config menu is closed
    • Fix inline SVG logo not being swapped in when watermarkEnabled is off (closes #161)
    • Fix number input constraints not being respected (closes #56)
Click to expand plugin and internal changes (I did my best to order these by relevance for each section)
  • Plugin Changes:
    (also refer to version 3.1.0's API docs)
    • Migration guide:
      • ⚠️ The plugin sublicense agreement was updated to version 2 to clarify points which were worded poorly. Read the latest version here.
      • ⚠️ POT. BREAKING: Since BYTM now requires plugin intents to be set, make sure to add all intents required by the authenticated functions your plugin calls to the PluginDef object's intents property (which can now also be an array instead of just a bitwise-or'ed number). Read below for a list of functions and their required intents.
      • If you use the BytmDialog, ExImDialog or MarkdownDialog classes directly, switch to the new authenticated functions getBytmDialog(), getExImDialog() and getMarkdownDialog(). Direct access will continue to work until version 4.0.0, but to future-proof your plugin, switch to the new functions as soon as possible, and make sure to add the CreateModalDialogs (32) intent to your plugin definition's intents property.
      • If you were using bytm:ready to reliably wait until all features are initialized, switch to bytm:allReady instead.
        The bytm:ready event is still emitted, but it is now only guaranteed to be emitted when the DOM is loaded and all features have started to initialize.
      • All NanoEmitter subclasses and the interface-exposed NanoEmitter class reference now use CoreUtils' new NanoEmitter class, which grants you access to the powerful onMulti() method to listen to multiple events at once, with configurable behavior.
      • The intents prop can now be an array of PluginIntent enum members.
    • API Changes:
      • ⚠️ POT. BREAKING: Plugins will no longer be able to call authenticated functions without the required intents.
        Intents are now required to be set in the plugin definition object, though for now they will still all be granted and don't need to be explicitly allowed by the user once after installing yet.
        The new intent FullAccess (512) grants all other intents, though you should only use it if your plugin truly requires all intents.
        These are the intents that are now required for the respective functions:
        • getFeatures() - ReadFeatureConfig (1) and optionally SeeHiddenConfigValues (4)
        • saveFeatures() - WriteFeatureConfig (2)
        • setLocale() - WriteTranslations (16)
        • getBytmDialog() - CreateModalDialogs (32)
        • getExImDialog() - CreateModalDialogs (32)
        • getMarkdownDialog() - CreateModalDialogs (32)
        • getAutoLikeData() - ReadAutoLikeData (64)
        • saveAutoLikeData() - WriteAutoLikeData (128)
        • getInternals() - InternalAccess (256)
      • The dialog classes BytmDialog, ExImDialog and MarkdownDialog should now be gotten using the new authenticated getBytmDialog(), getExImDialog() and getMarkdownDialog() functions, respectively.
        Using the direct access will work until version 4.0.0, but it is recommended you switch to the new functions as soon as possible.
      • The PluginDef object's intents property can now be either an array of PluginIntent values or a single number that is the bitwise OR of the intents.
      • Added a new broadcast system based on the BroadcastChannel API (name: bytm-broadcast), used for inter-tab communication. Events are relayed via the site event bytm:siteEvent:broadcast - see src/utils/broadcast.ts for a list of events.
      • Auth tokens are now in the format of a UUIDv4 instead of a 16-character, 36-radix string.
      • registerPlugin() now also returns a permissions object with the int and array properties, which contain all of the bitwise OR of the plugin's intents and an array of the intents that were actually granted to the plugin. The int property can be used with CoreUtils' bitSetHas() function to check if specific intents were granted.
      • A URL to the plugin's changelog file can now be specified in the PluginDef object's homepage.changelog property.
    • API Additions:
      • Added new intents InternalAccess (256) (currently only used by getInternals()) and FullAccess (512) (grants all intents).
      • Added new functions to the interface that allow for better interaction with the siteEvents system:
        • resourceAsString() - Returns a BYTM resource as a string, some of which are cached cross-session in GM storage for better performance.
        • onSiteEvent() - Adds a site event listener.
        • onceSiteEvent() - Adds a site event listener that is only called once and also returns a Promise for use with the async/await pattern.
        • onMultiSiteEvents() - Adds a listener that triggers after one of, or all of the given site events are dispatched, either continuously or just once, with configurable behavior.
        • 🔒 getBytmDialog() (requires intent CreateModalDialogs (32)) - Returns a reference to the BytmDialog class, which can be used to create new generic dialog instances.
        • 🔒 getExImDialog() (requires intent CreateModalDialogs (32)) - Returns a reference to the ExImDialog class, to export and import serializable data.
        • 🔒 getMarkdownDialog() (requires intent CreateModalDialogs (32)) - Returns a reference to the MarkdownDialog class, to render a markdown string in a modal dialog.
        • 🔒 getInternals() (requires intent InternalAccess (256)) - returns some internal function and object references that can be used by core libraries and deeper reaching plugins.
      • Added new events:
        • bytm:preInitPlugin (no arguments) - emitted at the earliest possible point i...
Read more

[PREVIEW] 3.1.0 - Prerelease 4

11 Mar 21:25

Choose a tag to compare

Pre-release

Important

This is an experimental version!

Features might still be unstable or unfinished, so please check back later for the finished release.
Since data integrity isn't ensured in experimental versions, I highly recommend you fully remove the script and reinstall it manually before installing the full release when it's out.
To keep your data, use the config and auto-liked channels menu's export and import functions to create a backup before installing the preview version.
After installing the full release and importing your old data, it will automatically be corrected to the latest format.

Click to expand the changelog at the time of 1681618
  • New features:
    • Add hotkeys to focus and clear the search bar on both pages (#145)
    • Improve config menu
      • Add a sidenav to toggle off all but one feature category (#140)
      • Add feature groups with headers to logically group features together
      • Add generic markdown sections to render the changelog and an about section
      • Remove advanced mode flag from a lot of features since there's much more space now
    • 🎵 Show the track number in playlists (by @indierodo) (#117)
    • 🎵 Use an exponential scale for the volume slider (by @cryeprecision) (#157)
    • Require double-pressing the number keys within a configurable time frame to skip to the associated timestamp (#152)
    • 🎵 Automatically close the activity check dialog
    • 🎵 Swap like and dislike buttons to match YT's layout
    • 🎵 In fullscreen, also hide the player bar on idle
  • Changes and improvements:
    • 🎵 Overhaul thumbnail overlay to fix massive inconsistencies (#143)
      • Fix album artwork being fetched with wrong parameters (#149)
      • Allow manually toggling between thumbnail providers
      • Cache resolved AM album artwork URLs similar to how lyrics URLs are currently cached
    • 🎵 Decouple volume slider step and scroll step (#102)
    • 🎵 Make the "improve links" feature also apply to all types of song list items
    • Change some default feature values (if left unchanged):
      • initTimeout: from 8 to 5 seconds (because of the now faster init time)
      • rememberSongTimeDuration: from 60 to 180 sec
      • 🎵 thumbnailOverlayITunesImgRes: from 1500 to 2000 px
      • frameSkipAmount: from 0.0417 to 0.0166 seconds (tbr idk how this happened)
    • Migrate to CoreUtils v3.0.0 DataStores
    • Overhaul contributing.md (part 1)
    • Overhaul translations
    • Add typedoc documentation for interface.ts and common dependencies
  • Fixes:
    • Fix inconsistent auto-like button rendering (#120)
    • Fix DataStores going out of sync across sessions (#162)
    • Fix auto-like feature not resolving channel names properly (#156)
    • 🎵 Fix SyntaxError when no AM album artwork found (#146)
    • Fix Error when clicking on a BytmDialog's exit button (#147)
    • Fix config menu not closing on Esc press when other dialog over top was closed with Esc
    • 🎵 Fix list buttons not disappearing with the native buttons in song lists (#86)
    • 🎵 Fix anchor improvements feature on the search page (#99)
    • 🎵 Fix rounded border in fullscreen mode when using the ThemeSong extension
    • Fix page scroll bar reappearing after BytmDialog opened over top of the config menu is closed
    • Fix inline SVG logo not being swapped in when watermarkEnabled is off (#161)
Click to expand plugin and internal changes (I did my best to order these by relevance for each section)
  • Plugin Changes:
    (also refer to version 3.1.0's API docs)
    • Migration guide:
      • ⚠️ The plugin sublicense agreement was updated to version 2 to clarify points which were worded poorly. Read the latest version here.
      • ⚠️ POT. BREAKING: Since BYTM now requires plugin intents to be set, make sure to add all intents required by the authenticated functions your plugin calls to the PluginDef object's intents property (which can now also be an array instead of just a bitwise-or'ed number). Read below for a list of functions and their required intents.
      • If you use the BytmDialog, ExImDialog or MarkdownDialog classes directly, switch to the new authenticated functions getBytmDialog(), getExImDialog() and getMarkdownDialog(). Direct access will continue to work until version 4.0.0, but to future-proof your plugin, switch to the new functions as soon as possible, and make sure to add the CreateModalDialogs (32) intent to your plugin definition's intents property.
      • If you were using bytm:ready to reliably wait until all features are initialized, switch to bytm:allReady instead.
        The bytm:ready event is still emitted, but it is now only guaranteed to be emitted when the DOM is loaded and all features have started to initialize.
      • All NanoEmitter subclasses and the interface-exposed NanoEmitter class reference now use CoreUtils' new NanoEmitter class, which grants you access to the powerful onMulti() method to listen to multiple events at once, with configurable behavior.
      • The intents prop can now be an array of PluginIntent enum members.
    • API Changes:
      • ⚠️ POT. BREAKING: Plugins will no longer be able to call authenticated functions without the required intents.
        Intents are now required to be set in the plugin definition object, though for now they will still all be granted and don't need to be explicitly allowed by the user once after installing yet.
        The new intent FullAccess (512) grants all other intents, though you should only use it if your plugin truly requires all intents.
        These are the intents that are now required for the respective functions:
        • getFeatures() - ReadFeatureConfig (1) and optionally SeeHiddenConfigValues (4)
        • saveFeatures() - WriteFeatureConfig (2)
        • setLocale() - WriteTranslations (16)
        • getBytmDialog() - CreateModalDialogs (32)
        • getExImDialog() - CreateModalDialogs (32)
        • getMarkdownDialog() - CreateModalDialogs (32)
        • getAutoLikeData() - ReadAutoLikeData (64)
        • saveAutoLikeData() - WriteAutoLikeData (128)
        • getInternals() - InternalAccess (256)
      • The dialog classes BytmDialog, ExImDialog and MarkdownDialog should now be gotten using the new authenticated getBytmDialog(), getExImDialog() and getMarkdownDialog() functions, respectively.
        Using the direct access will work until version 4.0.0, but it is recommended you switch to the new functions as soon as possible.
      • The PluginDef object's intents property can now be either an array of PluginIntent values or a single number that is the bitwise OR of the intents.
      • Added a new broadcast system using GM.addValueChangeListener for inter-tab communication. Events are relayed via the site event bytm:siteEvent:broadcast - see src/utils/broadcast.ts for a list of events.
      • Auth tokens are now in the format of a UUIDv4 instead of a 16-character, 36-radix string.
      • registerPlugin() now also returns a permissions object with the int and array properties, which contain all of the bitwise OR of the plugin's intents and an array of the intents that were actually granted to the plugin. The int property can be used with CoreUtils' bitSetHas() function to check if specific intents were granted.
      • A URL to the plugin's changelog file can now be specified in the PluginDef object's homepage.changelog property.
    • API Additions:
      • Added new intents InternalAccess (256) (currently only used by getInternals()) and FullAccess (512) (grants all intents).
      • Added new functions to the interface that allow for better interaction with the siteEvents system:
        • resourceAsString() - Returns a BYTM resource as a string, some of which are cached cross-session in GM storage for better performance.
        • onSiteEvent() - Adds a site event listener.
        • onceSiteEvent() - Adds a site event listener that is only called once and also returns a Promise for use with the async/await pattern.
        • onMultiSiteEvents() - Adds a listener that triggers after one of, or all of the given site events are dispatched, either continuously or just once, with configurable behavior.
        • 🔒 getBytmDialog() (requires intent CreateModalDialogs (32)) - Returns a reference to the BytmDialog class, which can be used to create new generic dialog instances.
        • 🔒 getExImDialog() (requires intent CreateModalDialogs (32)) - Returns a reference to the ExImDialog class, to export and import serializable data.
        • 🔒 getMarkdownDialog() ...
Read more

[PREVIEW] 3.1.0 - Prerelease 3

06 Mar 21:59

Choose a tag to compare

Pre-release

Important

This is an experimental version!

Features might still be unstable or unfinished, so please check back later for the finished release.
Since data integrity isn't ensured in experimental versions, I highly recommend you fully remove the script and reinstall it manually before installing the full release when it's out.
To keep your data, use the config and auto-liked channels menu's export and import functions to create a backup before installing the preview version.
After installing the full release and importing your old data, it will automatically be updated to the correct format.

Click to expand the changelog at the time of d1ab7b1
  • New features:
    • Add hotkeys to focus and clear the search bar on both pages (#145)
    • Improve config menu
      • Add a sidenav to toggle off all but one feature category (#140)
      • Add feature groups with headers to logically group features together
      • Add generic markdown sections to render the changelog and an about section
      • Remove advanced mode flag from a lot of features since there's much more space now
    • 🎵 Show the track number in playlists (by @indierodo) (#117)
    • 🎵 Use an exponential scale for the volume slider (by @cryeprecision) (#157)
    • Require double-pressing the number keys within a configurable time frame to skip to the associated timestamp (#152)
    • 🎵 Automatically close the activity check dialog
    • 🎵 Swap like and dislike buttons to match YT's layout
    • 🎵 In fullscreen, also hide the player bar on idle
  • Changes and improvements:
    • 🎵 Overhaul thumbnail overlay to fix massive inconsistencies (#143)
      • Fix album artwork being fetched with wrong parameters (#149)
      • Allow manually toggling between thumbnail providers
      • Cache resolved AM album artwork URLs similar to how lyrics URLs are currently cached
    • 🎵 Decouple volume slider step and scroll step (#102)
    • 🎵 Make the "improve links" feature also apply to all types of song list items
    • Change some default feature values (if left unchanged):
      • initTimeout: from 8 to 5 seconds (because of the now faster init time)
      • rememberSongTimeDuration: from 60 to 180 sec
      • 🎵 thumbnailOverlayITunesImgRes: from 1500 to 2000 px
      • frameSkipAmount: from 0.0417 to 0.0166 seconds (tbr idk how this happened)
    • Migrate to CoreUtils v3.0.0 DataStores
    • Overhaul contributing.md (part 1)
  • Fixes:
    • Fix inconsistent auto-like button rendering (#120)
    • Fix DataStores going out of sync across sessions (#162)
    • Fix auto-like feature not resolving channel names properly (#156)
    • 🎵 Fix SyntaxError when no AM album artwork found (#146)
    • Fix Error when clicking on a BytmDialog's exit button (#147)
    • Fix config menu not closing on Esc press when other dialog over top was closed with Esc
    • 🎵 Fix list buttons not disappearing with the native buttons in song lists (#86)
    • 🎵 Fix anchor improvements feature on the search page (#99)
    • 🎵 Fix rounded border in fullscreen mode when using the ThemeSong extension
    • Fix page scroll bar reappearing after BytmDialog opened over top of the config menu is closed
Click to expand plugin and internal changes (I did my best to order these by relevance for each section)
  • Plugin Changes:
    (also refer to version 3.1.0's API docs)
    • Migration guide:
      • ⚠️ The plugin sublicense agreement was updated to version 2 to clarify points which were worded poorly. Read the latest version here.
      • ⚠️ POT. BREAKING: Since BYTM now requires plugin intents to be set, make sure to add all intents required by the authenticated functions your plugin calls to the PluginDef object's intents property (which can now also be an array instead of just a bitwise-or'ed number). Read below for a list of functions and their required intents.
      • If you use the BytmDialog, ExImDialog or MarkdownDialog classes directly, switch to the new authenticated functions getBytmDialog(), getExImDialog() and getMarkdownDialog(). Direct access will continue to work until version 4.0.0, but to future-proof your plugin, switch to the new functions as soon as possible, and make sure to add the CreateModalDialogs (32) intent to your plugin definition's intents property.
      • If you were using bytm:ready to reliably wait until all features are initialized, switch to bytm:allReady instead.
        The bytm:ready event is still emitted, but it is now only guaranteed to be emitted when the DOM is loaded and all features have started to initialize.
      • All NanoEmitter subclasses and the interface-exposed NanoEmitter class reference now use CoreUtils' new NanoEmitter class, which grants you access to the powerful onMulti() method to listen to multiple events at once, with configurable behavior.
      • The intents prop can now be an array of PluginIntent enum members.
    • API Changes:
      • ⚠️ POT. BREAKING: Plugins will no longer be able to call authenticated functions without the required intents.
        Intents are now required to be set in the plugin definition object, though for now they will still all be granted and don't need to be explicitly allowed by the user once after installing yet.
        The new intent FullAccess (512) grants all other intents, though you should only use it if your plugin truly requires all intents.
        These are the intents that are now required for the respective functions:
        • getFeatures() - ReadFeatureConfig (1) and optionally SeeHiddenConfigValues (4)
        • saveFeatures() - WriteFeatureConfig (2)
        • setLocale() - WriteTranslations (16)
        • getBytmDialog() - CreateModalDialogs (32)
        • getExImDialog() - CreateModalDialogs (32)
        • getMarkdownDialog() - CreateModalDialogs (32)
        • getAutoLikeData() - ReadAutoLikeData (64)
        • saveAutoLikeData() - WriteAutoLikeData (128)
        • getInternals() - InternalAccess (256)
      • The dialog classes BytmDialog, ExImDialog and MarkdownDialog should now be gotten using the new authenticated getBytmDialog(), getExImDialog() and getMarkdownDialog() functions, respectively.
        Using the direct access will work until version 4.0.0, but it is recommended you switch to the new functions as soon as possible.
      • The PluginDef object's intents property can now be either an array of PluginIntent values or a single number that is the bitwise OR of the intents.
      • Added a new broadcast system based on the BroadcastChannel API (name: bytm-broadcast), used for inter-tab communication. Events are relayed via the site event bytm:siteEvent:broadcast - see src/utils/broadcast.ts for a list of events.
      • Auth tokens are now in the format of a UUIDv4 instead of a 16-character, 36-radix string.
      • registerPlugin() now also returns a permissions object with the int and array properties, which contain all of the bitwise OR of the plugin's intents and an array of the intents that were actually granted to the plugin. The int property can be used with CoreUtils' bitSetHas() function to check if specific intents were granted.
      • A URL to the plugin's changelog file can now be specified in the PluginDef object's homepage.changelog property.
    • API Additions:
      • Added new intents InternalAccess (256) (currently only used by getInternals()) and FullAccess (512) (grants all intents).
      • Added new functions to the interface that allow for better interaction with the siteEvents system:
        • resourceAsString() - Returns a BYTM resource as a string, some of which are cached cross-session in GM storage for better performance.
        • onSiteEvent() - Adds a site event listener.
        • onceSiteEvent() - Adds a site event listener that is only called once and also returns a Promise for use with the async/await pattern.
        • onMultiSiteEvents() - Adds a listener that triggers after one of, or all of the given site events are dispatched, either continuously or just once, with configurable behavior.
        • 🔒 getBytmDialog() (requires intent CreateModalDialogs (32)) - Returns a reference to the BytmDialog class, which can be used to create new generic dialog instances.
        • 🔒 getExImDialog() (requires intent CreateModalDialogs (32)) - Returns...
Read more

[PREVIEW] 3.1.0 - Prerelease 2

27 Sep 22:43

Choose a tag to compare

Pre-release

Important

This is an experimental version!

Features might still be unstable or unfinished, so please check back later for the finished release.
Since data integrity isn't ensured in experimental versions, I highly recommend you fully remove the script and reinstall it manually before installing the full release when it's out.
To keep your data, use the config and auto-liked channels menu's export and import functions to create a backup before installing the preview version.
After installing the full release and importing your old data, it will automatically be updated to the correct format.

Click to expand the changelog at the time of 4501b5f
  • New Features:
    • Improved config menu UX:
      • Added a sidenav that displays one group at a time, for a much less overwhelming experience.
      • Added feature groups, which further divide each group's features into logical sections.
      • Removed advanced mode flag from a lot of features since there's much more breathing room now.
      • Removed the dialog title subtexts. Instead, icons will be rendered in the footer, below the sidenav.
      • Reordered categories and features to be grouped more logically.
    • New configurable hotkeys:
      • Focus on the search bar (ShiftF).
      • Clear the search bar (ShiftDelete).
    • 🎵 Show a track number in the currently playing queue and playlists.
    • 🎵 Swap like- and dislike buttons to match the layout on YT.
    • Require double-pressing the number keys within a configurable time frame to skip to a specific point in the song.
    • 🎵 Automatically close the activity check dialog. Note: Might only work if the browser isn't minimized.
  • Improvements and Changes:
    • Improved script initialization performance.
    • 🎵 Overhauled thumbnail overlay to fix inconsistencies.
      • Fixed album artwork being fetched with wrong parameters.
      • Allow manually toggling between thumbnail providers.
      • Cache resolved AM album artwork URLs similar to how lyrics URLs are currently cached.
    • 🎵 Decoupled volume slider step and scroll step, allowing for both to work and be configured independently.
    • 🎵 The "improve links" feature now also applies to all types of song list items.
      Clicking a list item anywhere will now start playing that song. This doesn't affect clicking and dragging them.
    • The values of some features (if left unchanged), will be updated to the new defaults:
      • initTimeout will be changed from 8 to 5 seconds amid initialization performance improvements.
      • rememberSongTimeDuration will be changed from 60 to 180 seconds.
      • thumbnailOverlayITunesImgRes will be changed from 1500 to 2000 pixels.
    • Made some menu commands usable by default without requiring to be compiled in dev mode, and there's even more when the advanced mode is enabled. See internal changes for a full list.
    • Increased the amount of times per second the video/song time is remembered from 2 to 4.
  • Fixes:
    • Fixed inconsistent auto-like button rendering and channel name resolution on both pages.
    • 🎵 Fixed SyntaxError when no AM album artwork found.
    • Fixed Error when clicking on a BytmDialog's exit button.
    • Fixed interactivity problems with config menu and stacked BytmDialogs when other dialog was opened over top and then closed.
    • 🎵 Fixed list buttons not disappearing with the native buttons in song lists.
    • 🎵 Fixed anchor improvements feature on the search page.
    • 🎵 Fixed rounded border in fullscreen mode when using the ThemeSong extension.
    • Fixed changelog URL pointing to the script's build commit version instead of the latest version (this is like the 5th time I fixed this).
    • Fixed hotkey inputs not deactivating when the config menu is closed.
Click to expand plugin and internal changes (I did my best to order these by importance, but it's still a lot, sorry about that.)
  • Plugin Changes:
    (also refer to version 3.1.0's API docs)
    • Migration guide:
      • ⚠️ POT. BREAKING: Since BYTM now requires plugin intents to be set, make sure to add all intents required by the authenticated functions your plugin calls to the PluginDef object's intents property (which can now also be an array instead of just a bitwise-or'ed number). Read below for a list of functions and their required intents.
      • If you use the BytmDialog, ExImDialog or MarkdownDialog classes directly, switch to the new authenticated functions getBytmDialog(), getExImDialog() and getMarkdownDialog(). Direct access will continue to work until version 4.0.0, but to future-proof your plugin, switch to the new functions as soon as possible, and make sure to add the CreateModalDialogs (32) intent to your plugin definition's intents property.
      • If you were using bytm:ready to reliably wait until all features are initialized, switch to bytm:allReady instead.
        The bytm:ready event is still emitted, but it is now only guaranteed to be emitted when the DOM is loaded and all features have started to initialize.
      • All NanoEmitter subclasses and the interface-exposed NanoEmitter class reference now use CoreUtils' new NanoEmitter class, which grants you access to the powerful onMulti() method to listen to multiple events at once, with configurable behavior.
      • The intents prop can now be an array of PluginIntent enum members.
    • API Changes:
      • ⚠️ POT. BREAKING: Plugins will no longer be able to call authenticated functions without the required intents.
        Intents are now required to be set in the plugin definition object, though for now they will still all be granted and don't need to be explicitly allowed by the user once after installing yet.
        The new intent FullAccess (512) grants all other intents, though you should only use it if your plugin truly requires all intents.
        These are the intents that are now required for the respective functions:
        • getFeatures() - ReadFeatureConfig (1) and optionally SeeHiddenConfigValues (4)
        • saveFeatures() - WriteFeatureConfig (2)
        • setLocale() - WriteTranslations (16)
        • getBytmDialog() - CreateModalDialogs (32)
        • getExImDialog() - CreateModalDialogs (32)
        • getMarkdownDialog() - CreateModalDialogs (32)
        • getAutoLikeData() - ReadAutoLikeData (64)
        • saveAutoLikeData() - WriteAutoLikeData (128)
        • getInternals() - InternalAccess (256)
      • The dialog classes BytmDialog, ExImDialog and MarkdownDialog should now be gotten using the new authenticated getBytmDialog(), getExImDialog() and getMarkdownDialog() functions, respectively.
        Using the direct access will work until version 4.0.0, but it is recommended you switch to the new functions as soon as possible.
      • The PluginDef object's intents property can now be either an array of PluginIntent values or a single number that is the bitwise OR of the intents.
      • Auth tokens are now in the format of a UUIDv4 instead of a 16-character, 36-radix string.
      • registerPlugin() now also returns a permissions object with the int and array properties, which contain all of the bitwise OR of the plugin's intents and an array of the intents that were actually granted to the plugin. The int property can be used with CoreUtils' bitSetHas() function to check if specific intents were granted.
    • API Additions:
      • Added new intents InternalAccess (256) (currently only used by getInternals()) and FullAccess (512) (grants all intents).
      • Added new functions to the interface that allow for better interaction with the siteEvents system:
        • resourceAsString() - Returns a BYTM resource as a string, some of which are cached cross-session in GM storage for better performance.
        • onSiteEvent() - Adds a site event listener.
        • onceSiteEvent() - Adds a site event listener that is only called once and also returns a Promise for use with the async/await pattern.
        • onMultiSiteEvents() - Adds a listener that triggers after one of, or all of the given site events are dispatched, either continuously or just once, with configurable behavior.
        • 🔒 getBytmDialog() (requires intent CreateModalDialogs (32)) - Returns a reference to the BytmDialog class, which can be used to create new generic dialog instances.
        • 🔒 getExImDialog() (requires intent CreateModalDialogs (32)) - Returns a reference to the ExImDialog class, to export and import serializable data.
        • 🔒 getMarkdownDialog() (requires intent CreateModalDialogs (32)) - Returns a reference to the MarkdownDialog class, to render a markdown string in a modal dialog.
        • 🔒 getInternals() (requires intent InternalAccess (256)) - returns some internal function and object references that can be used by core libraries and deeper reaching plugins.
      • Added new events:
        • bytm:preInitPlugin (no arguments) - emitted at the earlie...
Read more

[PREVIEW] 3.1.0 - Prerelease 1

30 Jun 02:06

Choose a tag to compare

Pre-release

Important

This is an experimental version!

Features might still be unstable or unfinished, so please check back later for the finished release.
Since data integrity isn't ensured in experimental versions, I highly recommend you fully remove the script and reinstall it manually before installing the full release when it's out.
To keep your data, use the config and auto-liked channels menu's export and import functions to create a backup before installing the preview version. After updating to the full release and importing it, the data will automatically be migrated to the latest format.

Click to expand the changelog at the time of aee3859

New features:

  • Improved config menu UX with a sidenav:
    • Removed advanced mode flag from a lot of features since there's much more space now.
    • Removed the subtitle elements. Instead, icons will be rendered in the footer, below the sidenav.
    • Reordered categories and features to be grouped more logically.
    • Added extra info categories to render "About" and "Changelog" sections.
  • New configurable hotkeys:
    • Focus on the search bar (ShiftF).
    • Clear the search bar (ShiftDelete).
  • 🎵 Show a track number in the currently playing queue and playlists.

Changes and Improvements:

  • 🎵 [🚧 WIP] Overhauled thumbnail overlay to fix massive inconsistencies
    • Fixed album artwork being fetched with wrong parameters
    • Allow manually toggling between thumbnail providers
    • Cache resolved AM album artwork URLs similar to how lyrics URLs are currently cached
  • 🎵 Decoupled volume slider step and scroll step

Fixes:

  • 🎵 Fixed SyntaxError when no AM album artwork found
  • Fixed Error when clicking on a BytmDialog's exit button
  • 🎵 Fixed rounded border in fullscreen mode when using the ThemeSong extension
  • Fixed changelog URL pointing to the script's build commit version instead of the latest version (this is like the 5th time I fixed this)

Click to expand plugin and internal changes
  • Plugin Changes:
    • See contributing guide for full documentation
    • Added new events:
      • bytm:siteEvent:cfgMenuMounted (no arguments) - emitted when the config menu is invisibly mounted to the DOM (not opened yet, but modifiable).
      • bytm:siteEvent:configHeaderSelected: (name: LooseUnion<FeatureCategory>) - emitted when a config header is selected in the config menu, with the name of the selected header. This is usually the feature category name, but can also be an info category name (currently just "about" and "changelog").
      • bytm:siteEvent:voteLabelsAdded (no arguments) - emitted after the Return YouTube Dislike vote labels were added to the DOM.
      • bytm:siteEvent:updateVolumeSliderLabel (no arguments) - emitted to make the volume slider label update its text content.
    • Added new functions to the interface with the siteEvents system:
      • onSiteEvent() - Adds a site event listener.
      • onceSiteEvent() - Adds a site event listener that is only called once and also returns a Promise for use with the async/await pattern.
      • onMultiSiteEvents() - Adds a listener for multiple site events at once, with configurable behavior and with a shared callback function.
      • onceMultiSiteEvents() - Adds a listener for multiple site events at once, with configurable behavior and with a shared callback function that is only called once.
    • Auth token is now in the format of a UUID instead of a 16-character, 36-radix string.
  • Internal Changes:
    • Added NanoEmitter wrapper class MultiNanoEmitter that allows listening to when one, all, or a given subset of events have been emitted before executing a callback. It shares the same methods as the base NanoEmitter, but has the new methods onMulti() and onceMulti() for listening to multiple events. This new class is exposed on the plugin interface next to the NanoEmitter class.
    • Made siteEvents system use a MultiNanoEmitter instance instead of a NanoEmitter instance, so it can now also be used to listen to multiple events at once.
    • Made plugin-specific events (returned by registerPlugin()) use a MultiNanoEmitter instance too.
    • Removed GM.getResourceUrl() entirely in favor of fetching resources from a CDN.
    • Arguments to the translation functions can now also be an object that map a placeholder key to a string value, e.g. { name: "John" } for a translation using the new placeholder syntax, e.g. "Hello, ${name}!".
    • Moved the general feature category to the top of the config menu.
    • Wrapped feature config elements in a new container element with the ID bytm-ftconf-category-${categoryName} to allow for the sidenav to disable all but one at a time.
    • Updated UserUtils to v9.4.3 to fix two bugs related to the template literal placeholder format. This now allows specifying a single placeholder multiple times per translation string.
    • Added ability to render custom info categories in the config menu. Their navigation headers will be aligned to the bottom, and they render arbitrary elements. They use the same general formatting as the new feature category containers, just with their own categoryName (currently just "about" and "changelog").
    • Added CSS var --bytm-menu-bg-highlight-2 (hex, opacity 1) as a secondary level of highlight to --bytm-menu-bg-highlight.
    • Renamed CSS var --bytm-dialog-height-max to --bytm-dialog-target-height, but only for the config menu. All BytmDialogs will still use --bytm-dialog-height-max.
    • Improved number argument resolution of the functions in src/utils/logging.ts (if the last argument is a number and exceeds the range of the enum LogLevel, it will not be interpreted as a log level anymore, but as a number to be logged).

  • The music note emoji (🎵) tells you that the associated item only applies to YTM and not YT.
  • The warning emoji (⚠️) means there was a breaking change in the plugin API.

Release 3.0.0

21 May 16:12

Choose a tag to compare

  • Added features:
    • 🎵 Automatically scroll to the active song in the queue on page load or video change
    • 🎵 Make the player container use all available space on /watch
    • New configurable hotkeys:
      • 🎵 Skip forwards/backwards by a frame (. / ,)
      • Like/dislike video/song (ShiftL / ShiftD)
      • 🎵 Open lyrics of current song (O)
      • Skip to last remembered video/song time (AltR)
      • Reconfigurable skip to beginning & previous/next video/song (ShiftN / ShiftP, disabled by default)
      • Reconfigurable play/pause (Pause, disabled by default)
  • Changes and improvements:
    • Song/video volume will now be restored after BYTM reloads the tab by using the new common reloadTab() function
    • Added an adornment icon to identify which features work only on YTM, versus on both sites
    • 🎵 Thumbnail overlay improvements:
      • Overlay now prefers to use a high res album artwork from Apple Music if the current song is in an album
      • Fixed image not being updated while in fullscreen
    • 🎵 Made above-queue button container's sticky positioning toggleable with a feature
    • Made the resolution of the browser-preferred locale more reliable
    • Implemented a more powerful translation system
    • Removed the thumbnail overlay fitting option in favor of automatically switching based on the media type
  • Fixes:
    • Sped up installation time by loading all resources except stylesheets via regular fetch() and the external CDN instead of using @resource directives
    • Bumped z-index of dialog elements to display them correctly after a recent page update
    • Fixed white font color for BYTM config option on YT in light theme
    • 🎵 Fixed volume label not being fully hidden along with the slider
    • Config menu will now be correctly set as inert when a BytmDialog is opened over top
    • 🎵 Fixed "remove from queue" button sometimes deleting playlist entries instead of queue items
Click to expand internal and plugin changes
  • Plugin Changes:
    • See contributing guide for full documentation
    • API changes:
      • ⚠️ BREAKING: Renamed createRipple()'s speed prop values:
        • From faster to fastest
        • From slower to slowest
      • ⚠️ BREAKING: Made hasKey() and hasKeyFor() return a Promise to load the given locale if it's not found
      • ⚠️ 🎵 BREAKING: Removed sideBarMini observer instance
      • Made getCurrentMediaType() return "video" on YT instead of throwing an error
      • Added property additionalProps to the RippleProps argument in createRipple(), to assign extra props to the created or passed ripple element
    • New API functions:
      • Added reloadTab() as a better way to reload the page by keeping the same video time and volume and disabling BYTM features like initial tab volume
      • Added getVideoElement() to get the video element (if available) on the current page, on both YT and YTM
      • Added getVideoSelector() to get the CSS selector for the video element on the current page, on both YT and YTM
      • Added getDefaultFeatures() (callable without registering the plugin) to return the default / fallback feature configuration object
      • Added getLikeDislikeBtns() to return the like and dislike buttons on both domains, including the like/dislike state
      • Added isIgnoredInputElement() to check if the given or currently focused element is an input element, upon which all other keypress event listeners should be ignored
      • Added fetchITunesAlbumInfo() to fetch album info objects from the Apple Music / iTunes API, given an artist and album name
    • New API constants:
      • Added initialParams (URLSearchParams), the search params at the initial point of loading BYTM
      • Added sessionStorageAvailable (boolean), whether the browser supports sessionStorage
  • Internal Changes:
    • Improved asset caching by using JSDelivr instead of GitHub as a CDN
    • Fixed problems with the translation system by implementing UserUtils v9's new system
    • Added JSON schemas for all JSON files in assets

See pull request for more info

Release 2.2.0

11 Nov 18:53

Choose a tag to compare

  • Changes:
    • Replaced the monospace font Cascadia Code with Cousine
    • Due to massive incompatibilities on FireMonkey, the script will show an error and not execute under the extension anymore
    • Resources now have their integrity checked to make BYTM more resilient against XSS- and MITM-type attacks
  • Fixes:
    • Fixed errors in TamperMonkey because of missing @connect directives
    • Fixed locale codes not using the correct format (en_US instead of the correct format en-US)
    • Fixed changelog not updating on new releases and thus the update notification dialog would also show an outdated changelog
    • Fixed auto-like channel toggle button disappearing after changing channel page tabs on both pages
    • Fixed duplicate logo if the ThemeSong extension is installed
    • Fixed tab opening with the resolved lyrics URL when ctrl-clicking the lyrics button
Click to expand internal and plugin changes
  • Internal Changes:
    • Breaking: Changed the locale code format to match the BCP 47 standard.
      As part of this, all _ underscores were replaced with - hyphens and the following locales had their country codes corrected:
      • en-UK -> en-GB
      • ja-JA -> ja-JP
    • Enabled Subresource Integrity (SRI) hashes for all resources in the metadata block
    • Updated UserUtils library to v8.3.1
  • Plugin Changes:
    • Migration guide:
      • Since locale codes now have the format xx-YY and two were renamed, all plugins must implement those changes

See pull request for more info

Release 2.1.0

11 Nov 18:50

Choose a tag to compare

  • Added features:
    • Added a feature to like songs and videos of certain channels (on both sites) automatically.
      The button to toggle auto-liking will only show up on channel pages until the next update. Please report any issues you encounter.
    • Added the ability to show the approximate amount of likes and dislikes on the currently playing song (powered by ReturnYoutubeDislike)
    • Added support for themes set by the ThemeSong extension
    • Added a dialog for listing the currently installed and active plugins including some metadata
  • Changes:
    • Made song/video time remembering enabled by default on YT too
    • Made reset button in config menu a feature of type button
    • Welcome menu is now shown on YT too
    • Added Ctrl modifier key to every lyrics button to open a lyrics search prompt
    • Added Shift and Ctrl modifier keys to the above-queue buttons that will skip prompts or customize their behavior in other ways
    • Arrow key and number key skipping works more reliably and now also in the config menu
    • Changed default settings for some features.
      After updating, if the values were unchanged from their previous default, they will automatically have the new default value:
      • Remember Song Time Sites: if set to YTM only, it changes to both sites
      • Volume Slider Scroll Sensitivity: if set to 10%, it changes to 4%
    • Made some settings require advanced mode that didn't before:
      • Fix spacing/layout issues
      • Fix HDR issues
      • Disable Dark Reader sites
      • Remove share tracking parameter sites
      • Placement of list/queue buttons
    • Removed broken feature "remove upgrade tab"
    • Removed unnecessary experimental feature "advancedLyricsFilter" as the API's native search improved a lot
    • Made all integration features configurable and gave them their own config category
    • Created a prompt dialog to replace the browser's native dialogs, which could accidentally be turned off by the user and would softlock the script
  • Fixes:
    • Fixed major bug that threw "This document requires 'TrustedHTML' assignment" errors on Chromium browsers
    • Adjusted script to UI redesign of playlists
    • Fixed song list buttons disappearing when dragging the row around
    • Fixed song list buttons not always appearing immediately
    • Fixed escape closing all open dialogs instead of one at a time
    • Fixed "added to liked songs" toast not being consistently closed
    • Fixed messed up time restoration feature on YT because of the &t param
    • Fixed broken autoplay queue delete button after a redesign
    • Fixed transparent player bar background in fullscreen being barely readable with thumbnail overlay active
    • Fixed thumbnail overlay not updating in fullscreen mode and in the mini player
    • Fixed video time restoring breaking after pausing for a longer time
    • Fixed toasts being shown with a 1000x higher duration than intended
    • Fixed volume slider features not working anymore when display width shrinks to below 1150px
Click to expand internal and plugin changes
  • Internal Changes:
    • Updated the UserUtils library to v8.0.2
    • Removed compareVersions() and compareVersionArrays() in favor of including the compare-versions library
    • Now using a single query parameter for lyrics lookup
    • Added license for plugin-related source code, see license-for-plugins.txt
    • Added advanced feature to change the startup timeout (only impacts plugin initialization for now)
    • Now using a blue logo is instead of the red BetterYTM logo when the script was compiled in development (preview) mode
    • Added Storybook for easier and faster development of components
    • Removed the @updateURL and @downloadURL directives because their use is controversial and the script has a built-in update check now
    • Migrated to pnpm for faster compilation times
    • Moved NanoEmitter class over to the UserUtils library (it is still re-exported by the plugin interface as before)
    • Made getThumbnailUrl() and getBestThumbnailUrl() use the domain youtube.com to prevent cross-origin issues
    • Added custom error instances LyricsError and PluginError for better error handling using instanceof
    • Changed the feature identifier key for showVotesFormat to numbersFormat as it is now generic and available to plugins through the formatNumber() function
    • Feature config keys will now be corrected on each page load (meaning missing keys will be set to their default and extra keys will be removed)
  • Plugin Changes:
    See the contributing guide for the latest documentation of the plugin interface
    • Changed the way plugins are registered by making the registerPlugin() function the sole argument passed by the bytm:registerPlugin event. Call this function synchronously to register your plugin.
    • Plugins will now load at an earlier point in BetterYTM's startup sequence. This means that plugins can now be initialized before the script's features are fully initialized and the DOM is ready. Use site events to wait for the right moment to interact with the page.
    • Added new components:
      • createLongBtn() to create a button with an icon and text (works either as normal or as a toggle button)
        The design follows that of the subscribe button on YTM's channel pages, but the consistent class names make it easy to style it differently.
      • createRipple() to create a click ripple animation effect on a given element
      • showToast() to show a custom toast notification with a message string or element and duration
      • showIconToast() to show a custom toast notification with a message string or element, icon and duration
      • showPrompt() to show a styled dialog that replaces the confirm(), alert() and prompt() functions
      • ExImDialog class for creating a BytmDialog instance that is designed for exporting and importing generic data as a string
    • Changed components:
      • BytmDialog now has the option removeListenersOnDestroy (true by default) to configure removing all event listeners when the dialog is destroyed
      • BytmDialog's private members and methods have been changed to protected for easier extension (when using TypeScript)
    • Plugin definition changes:
      • Some intents were added or moved around in their order. See the new values in src/types.ts -> enum PluginIntent
    • Added interface functions:
      • setInnerHtml() to set the innerHTML property of an element to a sanitized string using the Trusted Types API and the library DOMPurify
      • getAutoLikeData() to return the current auto-like data (authenticated function)
      • saveAutoLikeData() to overwrite the auto-like data (authenticated function)
      • fetchVideoVotes() to fetch the approximate like and dislike count of a video from Return Youtube Dislike
      • getDomain() returns the current domain ("yt" or "ytm")
      • waitVideoElementReady() returns a promise that resolves when the video element is ready
      • getCurrentMediaType() (on YTM only) returns the current media type ("video" or "song")
      • tl() returns the translation for the provided translation key and provided locale
      • tlp() returns the translation for the provided translation key, including pluralization identifier and provided locale
      • formatNumber() formats a number according to the configured locale and configured or provided format ("short" or "long")
    • SelectorObserver / addSelectorListener() changes:
      • Added ytMasthead instance for the title bar on YT
      • Renamed all YT-specific instances to have the yt prefix
        • watchFlexy renamed to ytWatchFlexy
        • watchMetadata renamed to ytWatchMetadata
      • Added new SelectorObserver instance browseResponse for pages like /channel/{id}
    • Event changes:
      • Added events
        • bytm:featureInitStarted - emitted when the feature initialization process starts
        • bytm:featureInitialized - emitted every time a feature has been initialized and is passed the feature's identifier string
        • bytm:dialogClosed - emitted when a BytmDialog is closed and gets passed the instance
        • bytm:dialogClosed:id - emitted only when the dialog with the given ID is closed and gets passed the instance
        • bytm:siteEvent:pathChanged - emitted whenever the URL path (location.pathname) changes
      • Now the event bytm:siteEvent:fullscreenToggled is only emitted once per fullscreen change
      • Renamed event bytm:initPlugins to bytm:registerPlugin to be more consistent
      • Changed event property returned by registerPlugin() from nanoevents Emitter to NanoEmitter instance (see the UserUtils docs)
        In practice this changes nothing, but it benefits from plugins having access to the additional methods once() for immediately unsubscribing from an event after it was emitted once and unsubscribeAll() to remove all event listeners.

See p...

Read more

[PREVIEW] 2.1.0 - Release Candidate 2

08 Sep 16:56

Choose a tag to compare

Pre-release
Click to expand the changes since rc1
  • Changes:
    • Created a prompt dialog to replace the browser's native dialogs, which could accidentally be turned off by the user and would softlock the script
  • Internal Changes:
    • Updated the UserUtils library to v7.2.1
    • Made getThumbnailUrl() and getBestThumbnailUrl() use the domain youtube.com to prevent cross-origin issues
    • Changed the way plugins are registered by making the registerPlugin() function the sole argument passed by the bytm:registerPlugin event. Call this function synchronously to register your plugin.
    • Plugins will now load at an earlier point in BetterYTM's startup sequence. This means that plugins can now be initialized before the script's features are fully initialized and the DOM is ready. Use site events to wait for the right moment to interact with the page.
    • Added new components:
      • showPrompt() to show a styled dialog that replaces the confirm(), alert() and prompt() functions
    • Plugin definition changes:
      • Some intents were added or moved around in their order. See the new values in src/types.ts -> enum PluginIntent
    • Added interface functions:
      • tl() returns the translation for the provided translation key and provided locale
      • tlp() returns the translation for the provided translation key, including pluralization identifier and provided locale
    • Renamed event bytm:initPlugins to bytm:registerPlugin to be more consistent


This version is almost finished but may still contain a few tiny bugs.
It is highly recommended you fully remove the script and reinstall it manually once the update is released.

See pull request for more info

[PREVIEW] 2.1.0 - Release Candidate 1

28 Aug 12:08

Choose a tag to compare

Pre-release
Click to expand the changelog at the time of 0635e65
  • Added features:
    • Added an experimental feature to like songs and videos of certain channels (on both sites) automatically.
      Since this feature is still experimental, to be able to turn it on, you first need to enable advanced mode in the settings.
      The button to toggle auto-liking will only show up on channel pages until the next update. Please report any issues you encounter.
    • Added the ability to show the approximate amount of likes and dislikes on the currently playing song (powered by ReturnYoutubeDislike)
    • Added support for themes set by the ThemeSong extension
  • Changes:
    • Made song/video time remembering enabled by default on YT too
    • Made reset button in config menu a feature of type button
    • Welcome menu is now shown on YT too
    • Added Ctrl modifier key to every lyrics button to open a lyrics search prompt
    • Added Shift and Ctrl modifier keys to the above-queue buttons that can skip prompts or customize the behavior
    • Arrow key and number key skipping works more reliably and now also in the config menu
    • Changed default settings for some features.
      After updating, if the values were unchanged from their previous default, they will automatically have the new default value:
      • Remember Song Time Sites: if set to YTM only, it changes to both sites
      • Volume Slider Scroll Sensitivity: if set to 10%, it changes to 4%
    • Made some settings require advanced mode that didn't before:
      • Fix spacing/layout issues
      • Fix HDR issues
      • Disable Dark Reader sites
      • Remove share tracking parameter sites
      • Placement of list/queue buttons
    • Removed broken feature "remove upgrade tab"
    • Removed unnecessary experimental feature "advancedLyricsFilter" as the API's native search improved a lot
    • Made all integration features configurable and gave them their own config category
  • Fixes:
    • Adjusted script to UI redesign of playlists
    • Fixed song list buttons disappearing when dragging the row around
    • Fixed song list buttons not always appearing immediately
    • Fixed escape closing all open dialogs instead of one at a time
    • Fixed "added to liked songs" toast not being consistently closed
    • Fixed messed up time restoration feature on YT because of the &t param
    • Fixed broken autoplay queue delete button after a redesign
    • Fixed transparent player bar background in fullscreen being barely readable with thumbnail overlay active
    • Fixed thumbnail overlay not updating in fullscreen mode and in the mini player
    • Fixed video time restoring breaking after pausing for a longer time
    • Fixed "This document requires 'TrustedHTML' assignment" error on Chromium browsers
    • Fixed toasts being shown with a 1000x higher duration than intended
Click to expand internal and plugin changes
  • Internal Changes:
    • Updated the UserUtils library to v7.2.1
    • Removed compareVersions() and compareVersionArrays() in favor of including the compare-versions library
    • Now using a single query parameter for lyrics lookup
    • Added license for plugin-related source code, see license-for-plugins.txt
    • Added advanced feature to change the startup timeout (only impacts plugin initialization for now)
    • Now using a blue logo is instead of the red BetterYTM logo when the script was compiled in development (preview) mode
    • Fixed missing configuration keys in development/preview mode instead of potentially breaking the script
    • Added Storybook for easier and faster development of components
    • Removed the @updateURL and @downloadURL directives because their use is controversial and the script has a built-in update check now
    • Migrated to pnpm for faster compilation times
    • Moved NanoEmitter class over to the UserUtils library (it is still re-exported by the plugin interface as before)
  • Plugin Changes:
    See the contributing guide for the latest documentation of the plugin interface
    • Added new components:
      • createLongBtn() to create a button with an icon and text (works either as normal or as a toggle button)
        The design follows that of the subscribe button on YTM's channel pages, but the consistent class names make it easy to style it differently.
      • showToast() to show a custom toast notification with a message string or element and duration
      • showIconToast() to show a custom toast notification with a message string or element, icon and duration
      • createRipple() to create a click ripple animation effect on a given element (experimental)
      • ExImDialog class for creating a BytmDialog instance that is designed for exporting and importing generic data as a string
    • Changed components:
      • BytmDialog now has the option removeListenersOnDestroy (true by default) to configure removing all event listeners when the dialog is destroyed
      • BytmDialog's private members and methods have been changed to protected for easier extension (when using TypeScript)
    • Added interface functions:
      • setInnerHtml() to set the innerHTML property of an element to a sanitized string using the Trusted Types API and the library DOMPurify
      • getAutoLikeData() to return the current auto-like data (authenticated function)
      • saveAutoLikeData() to overwrite the auto-like data (authenticated function)
      • fetchVideoVotes() to fetch the approximate like and dislike count of a video from Return Youtube Dislike
      • getDomain() returns the current domain ("yt" or "ytm")
      • waitVideoElementReady() returns a promise that resolves when the video element is ready
      • getCurrentMediaType() (on YTM only) returns the current media type ("video" or "song")
    • SelectorObserver / addSelectorListener() changes:
      • Added ytMasthead instance for the title bar on YT
      • Renamed all YT-specific instances to have the yt prefix
        • watchFlexy renamed to ytWatchFlexy
        • watchMetadata renamed to ytWatchMetadata
      • Added new SelectorObserver instance browseResponse for pages like /channel/{id}
    • Event changes:
      • Added events
        • bytm:featureInitStarted - emitted when the feature initialization process starts
        • bytm:featureInitialized - emitted every time a feature has been initialized and is passed the feature's identifier string
        • bytm:dialogClosed - emitted when a BytmDialog is closed and gets passed the instance
        • bytm:dialogClosed:id - emitted only when the dialog with the given ID is closed and gets passed the instance
        • bytm:siteEvent:pathChanged - emitted whenever the URL path (location.pathname) changes
      • Now the event bytm:siteEvent:fullscreenToggled is only emitted once per fullscreen change
      • Renamed event bytm:initPlugins to bytm:registerPlugins to be more consistent
      • Changed event property returned by registerPlugin() from nanoevents Emitter to NanoEmitter instance (see the UserUtils docs)
        In practice this changes nothing, but it benefits from plugins having access to the additional methods once() for immediately unsubscribing from an event after it was emitted once and unsubscribeAll() to remove all event listeners.


This version is almost finished but may still contain a few tiny bugs.
It is highly recommended you fully remove the script and reinstall it manually once the update is released.

See pull request for more info