diff --git a/Resources/en.lproj/Localizable.strings b/Resources/en.lproj/Localizable.strings
index 05401c5a2c34678f8b0703922ee5c7c802ccdd63..dababc2b04e7cb8a9eb6a44d061eb48e1fd77e06 100644
--- a/Resources/en.lproj/Localizable.strings
+++ b/Resources/en.lproj/Localizable.strings
@@ -549,8 +549,6 @@
 "FEEDBACK_EMAIL_NOT_POSSIBLE_TITLE" = "Mail account not configured";
 "FEEDBACK_EMAIL_NOT_POSSIBLE_LONG" = "Contact us through %@ from another device.";
 
-"SETTINGS_THEME_BLACK" = "Use black background on dark mode";
-"SETTINGS_THEME_BLACK_SUBTITLE" = "Improves battery life on devices with an OLED screen";
 
 "SETTINGS_RESET_TITLE" = "Reset the settings";
 "SETTINGS_RESET_MESSAGE" = "Do you want to reset all the settings to their default values?";
diff --git a/Resources/iOS/Settings.bundle/Root.inApp.plist b/Resources/iOS/Settings.bundle/Root.inApp.plist
index 2172d720bdc9e792760ec9c5eef1515bdd12c97e..8ba36216e6d659228bd1f9425fa216a4edb55f9c 100644
--- a/Resources/iOS/Settings.bundle/Root.inApp.plist
+++ b/Resources/iOS/Settings.bundle/Root.inApp.plist
@@ -42,14 +42,12 @@
 				<string>SETTINGS_THEME_BRIGHT</string>
 				<string>SETTINGS_THEME_DARK</string>
 				<string>SETTINGS_THEME_SYSTEM</string>
-				<string>SETTINGS_THEME_BLACK</string>
 			</array>
 			<key>Values</key>
 			<array>
 				<integer>0</integer>
 				<integer>1</integer>
 				<integer>2</integer>
-				<string>3</string>
 			</array>
 		</dict>
 		<dict>
diff --git a/Sources/App/iOS/DefaultsChangeListener.swift b/Sources/App/iOS/DefaultsChangeListener.swift
new file mode 100644
index 0000000000000000000000000000000000000000..e4da299607e1064ce6e963748e72921714b8c6d6
--- /dev/null
+++ b/Sources/App/iOS/DefaultsChangeListener.swift
@@ -0,0 +1,106 @@
+/*****************************************************************************
+ * DefaultsChangeListener.swift
+ * VLC for iOS
+ *****************************************************************************
+ * Copyright (c) 2025 VideoLAN. All rights reserved.
+ * $Id$
+ *
+ * Authors: Craig Reyenga <craig.reyenga # gmail.com>
+ *
+ * Refer to the COPYING file of the official project for license.
+ *****************************************************************************/
+
+/// Emits notifications or performs other actions based on updates to user defaults.
+@objc(VLCDefaultsChangeListener)
+final class DefaultsChangeListener: NSObject {
+    private let appTheme: ChangeManager<Int>
+    private let appThemeBlack: ChangeManager<Int>
+    private let disableGrouping: ChangeManager<Bool>
+    private let hideMediaLibrary: ChangeManager<Bool>
+    private let excludeFromDeviceBackup: ChangeManager<Bool>
+
+    @objc var mediaLibraryService: MediaLibraryService?
+
+    override init() {
+        let notificationCenter = NotificationCenter.default
+
+        appTheme = ChangeManager(value: Self.readAppTheme(), action: { _ in
+            PresentationTheme.themeDidUpdate()
+        })
+
+        appThemeBlack = ChangeManager(value: Self.readAppThemeBlack(), action: { _ in
+            PresentationTheme.themeDidUpdate()
+        })
+
+        disableGrouping = ChangeManager(value: Self.readDisableGrouping(), action: { _ in
+            notificationCenter.post(name: .VLCDisableGroupingDidChangeNotification, object: nil)
+        })
+
+        hideMediaLibrary = ChangeManager(value: Self.readHideMediaLibrary())
+
+        excludeFromDeviceBackup = ChangeManager(value: Self.readExcludeFromDeviceBackup())
+
+        super.init()
+
+        notificationCenter.addObserver(self,
+                                       selector: #selector(userDefaultsUpdated),
+                                       name: UserDefaults.didChangeNotification,
+                                       object: nil)
+
+        hideMediaLibrary.action = { [weak self] hide in
+            self?.mediaLibraryService?.hideMediaLibrary(hide)
+        }
+
+        excludeFromDeviceBackup.action = { [weak self] exclude in
+            self?.mediaLibraryService?.excludeFromDeviceBackup(exclude)
+        }
+    }
+
+    @objc private func userDefaultsUpdated() {
+        appTheme.update(Self.readAppTheme())
+        appThemeBlack.update(Self.readAppThemeBlack())
+        disableGrouping.update(Self.readDisableGrouping())
+        hideMediaLibrary.update(Self.readHideMediaLibrary())
+        excludeFromDeviceBackup.update(Self.readExcludeFromDeviceBackup())
+    }
+
+    static func readAppTheme() -> Int {
+        return UserDefaults.standard.integer(forKey: kVLCSettingAppTheme)
+    }
+
+    static func readAppThemeBlack() -> Int {
+        return UserDefaults.standard.integer(forKey: kVLCSettingAppThemeBlack)
+    }
+
+    static func readDisableGrouping() -> Bool {
+        return UserDefaults.standard.bool(forKey: kVLCSettingsDisableGrouping)
+    }
+
+    static func readHideMediaLibrary() -> Bool {
+        return UserDefaults.standard.bool(forKey: kVLCSettingHideLibraryInFilesApp)
+    }
+
+    static func readExcludeFromDeviceBackup() -> Bool {
+        // The user interface setting is for *including* in a backup, but
+        // user defaults and the media library refer to *exclusion*. We perform
+        // the inversion right here to have everything match up.
+        return !UserDefaults.standard.bool(forKey: kVLCSettingBackupMediaLibrary)
+    }
+}
+
+/// Executes an action when the underlying value has changed.
+fileprivate final class ChangeManager<T: Equatable> {
+    var value: T
+    var action: ((T) -> Void)?
+
+    init(value: T, action: ((T) -> Void)? = nil) {
+        self.value = value
+        self.action = action
+    }
+
+    func update(_ newValue: T) {
+        guard value != newValue else { return }
+        value = newValue
+        action?(newValue)
+    }
+}
diff --git a/Sources/App/iOS/VLCAppCoordinator.m b/Sources/App/iOS/VLCAppCoordinator.m
index 0b0b8c2d8ff2a3336bebf8de010521c9e267fbe7..9a0f8906dfc7ca26a91b75148eae8ed9189658c6 100644
--- a/Sources/App/iOS/VLCAppCoordinator.m
+++ b/Sources/App/iOS/VLCAppCoordinator.m
@@ -28,6 +28,7 @@
     VLCRemoteControlService *_remoteControlService;
     UIWindow *_externalWindow;
     VLCStripeController *_stripeController;
+    VLCDefaultsChangeListener *_defaultsChangeListener;
 
 #if TARGET_OS_IOS
     VLCRendererDiscovererManager *_rendererDiscovererManager;
@@ -54,6 +55,8 @@
 {
     self = [super init];
     if (self) {
+        _defaultsChangeListener = [[VLCDefaultsChangeListener alloc] init];
+
         dispatch_async(dispatch_get_main_queue(), ^{
             [VLCLibrary setSharedEventsConfiguration:[VLCEventsLegacyConfiguration new]];
             [self initializeServices];
@@ -71,6 +74,8 @@
 
     // start the remote control service
     _remoteControlService = [[VLCRemoteControlService alloc] init];
+
+    _defaultsChangeListener.mediaLibraryService = self.mediaLibraryService;
 }
 
 - (MediaLibraryService *)mediaLibraryService
diff --git a/Sources/Playback/Player/VideoPlayer-iOS/MediaMoreOptionsActionSheet.swift b/Sources/Playback/Player/VideoPlayer-iOS/MediaMoreOptionsActionSheet.swift
index 0e587c057552d0f53bd163e6069453f39b12666d..9ab18d603bba5b622a2d49d614abeb9b4bd48f6c 100644
--- a/Sources/Playback/Player/VideoPlayer-iOS/MediaMoreOptionsActionSheet.swift
+++ b/Sources/Playback/Player/VideoPlayer-iOS/MediaMoreOptionsActionSheet.swift
@@ -486,8 +486,7 @@ extension MediaMoreOptionsActionSheet: MediaPlayerActionSheetDataSource {
             }
 
             // Do not display these options in the action sheet.
-            if $0 == .addBookmarks || $0 == .blackBackground ||
-                $0 == .playNextItem || $0 == .playlistPlayNextItem {
+            if [ .addBookmarks, .playNextItem, .playlistPlayNextItem ].contains($0) {
                 return
             }
 
diff --git a/Sources/Playback/Player/VideoPlayer-iOS/Subviews/MediaPlayerActionSheet.swift b/Sources/Playback/Player/VideoPlayer-iOS/Subviews/MediaPlayerActionSheet.swift
index 9783bb165732e21f69c53aa936c54d61a8cb8e7c..21d043f20292be941e09bf9d78d5791ad8163b0c 100644
--- a/Sources/Playback/Player/VideoPlayer-iOS/Subviews/MediaPlayerActionSheet.swift
+++ b/Sources/Playback/Player/VideoPlayer-iOS/Subviews/MediaPlayerActionSheet.swift
@@ -22,7 +22,6 @@ enum ActionSheetCellIdentifier: String, CustomStringConvertible, CaseIterable {
     case addBookmarks
     case abRepeat
     case interfaceLock
-    case blackBackground
     case playNextItem
     case playlistPlayNextItem
 
@@ -48,8 +47,6 @@ enum ActionSheetCellIdentifier: String, CustomStringConvertible, CaseIterable {
             return NSLocalizedString("REPEAT_MODE", comment: "")
         case .abRepeat:
             return NSLocalizedString("AB_LOOP", comment: "")
-        case .blackBackground:
-            return NSLocalizedString("SETTINGS_THEME_BLACK", comment: "")
         case .playNextItem:
             return NSLocalizedString("SETTINGS_PLAY_ALL", comment: "")
         case .playlistPlayNextItem:
@@ -73,8 +70,6 @@ enum ActionSheetCellIdentifier: String, CustomStringConvertible, CaseIterable {
             return NSLocalizedString("BOOKMARKS_HINT", comment: "")
         case .interfaceLock:
             return NSLocalizedString("INTERFACE_LOCK_HINT", comment: "")
-        case .blackBackground:
-            return NSLocalizedString("SETTINGS_THEME_BLACK_SUBTITLE", comment: "")
         case .playNextItem:
             return NSLocalizedString("SETTINGS_PLAY_ALL_HINT", comment: "")
         case .playlistPlayNextItem:
diff --git a/Sources/Settings/Controller/SettingsController.swift b/Sources/Settings/Controller/SettingsController.swift
index bd9aa32be8d81aa9d54793aa073796afd6851f6c..287bd6baf17f89788c5385539cbc886387041de4 100644
--- a/Sources/Settings/Controller/SettingsController.swift
+++ b/Sources/Settings/Controller/SettingsController.swift
@@ -169,7 +169,14 @@ class SettingsController: UITableViewController {
 #if os(iOS)
         setNeedsStatusBarAppearanceUpdate()
 #endif
-        reloadSettingsSections() // When theme changes hide the black theme section if needed
+
+        tableView.visibleCells.forEach { cell in
+            guard let cell = cell as? SettingsCell else { return }
+
+            cell.themeChanged()
+        }
+
+        reloadSettingsSections()
     }
 
     @objc private func miniPlayerIsShown() {
@@ -432,12 +439,6 @@ extension SettingsController: SettingsCellDelegate {
         switch preferenceKey {
         case kVLCSettingPasscodeOnKey:
             passcodeLockSwitchOn(state: isOn)
-        case kVLCSettingHideLibraryInFilesApp:
-            medialibraryHidingLockSwitchOn(state: isOn)
-        case kVLCSettingBackupMediaLibrary:
-            mediaLibraryBackupActivateSwitchOn(state: isOn)
-        case kVLCSettingsDisableGrouping:
-            medialibraryDisableGroupingSwitchOn(state: isOn)
         default:
             break
         }
@@ -488,30 +489,9 @@ extension SettingsController {
     }
 }
 
-extension SettingsController {
-    func medialibraryHidingLockSwitchOn(state: Bool) {
-        mediaLibraryService.hideMediaLibrary(state)
-    }
-}
-
-extension SettingsController {
-    func mediaLibraryBackupActivateSwitchOn(state: Bool) {
-        mediaLibraryService.excludeFromDeviceBackup(state)
-    }
-}
-
-extension SettingsController {
-    func medialibraryDisableGroupingSwitchOn(state _: Bool) {
-        notificationCenter.post(name: .VLCDisableGroupingDidChangeNotification, object: self)
-    }
-}
-
 extension SettingsController: ActionSheetSpecifierDelegate {
     func actionSheetSpecifierHandleToggleSwitch(for cell: ActionSheetCell, state: Bool) {
         switch cell.identifier {
-        case .blackBackground:
-            userDefaults.setValue(state, forKey: kVLCSettingAppThemeBlack)
-            PresentationTheme.themeDidUpdate()
         case .playNextItem:
             userDefaults.setValue(state, forKey: kVLCAutomaticallyPlayNextItem)
         case .playlistPlayNextItem:
diff --git a/Sources/Settings/Model/ActionSheetSpecifier.swift b/Sources/Settings/Model/ActionSheetSpecifier.swift
index ed4e4db9fa7f3b67273604649b6713ac07330b60..1b6c16b77a8a1a3bcf956b7c397668cb45e2a7a3 100644
--- a/Sources/Settings/Model/ActionSheetSpecifier.swift
+++ b/Sources/Settings/Model/ActionSheetSpecifier.swift
@@ -60,12 +60,6 @@ extension ActionSheetSpecifier: ActionSheetDelegate {
             return
         }
 
-        guard preferenceKey != kVLCSettingAppTheme ||
-                (!PresentationTheme.current.isDark || indexPath.row != numberOfRows() - 1) else {
-            // Disable the selection for the black background option cell in the appearance action sheet
-            return
-        }
-
         guard preferenceKey != kVLCAutomaticallyPlayNextItem else {
             // Disable the selection for the automatically play next item options
             return
@@ -73,10 +67,6 @@ extension ActionSheetSpecifier: ActionSheetDelegate {
 
         userDefaults.set(settingSpecifier?.specifier[indexPath.row].value, forKey: preferenceKey)
 
-        if preferenceKey == kVLCSettingAppTheme {
-            PresentationTheme.themeDidUpdate()
-        }
-
 #if os(iOS)
         NotificationFeedbackGenerator().success()
 #endif
@@ -106,15 +96,6 @@ extension ActionSheetSpecifier: ActionSheetDataSource {
             return 0
         }
 
-        if preferenceKey == kVLCSettingAppTheme {
-            let isThemeDark: Bool = PresentationTheme.current.isDark
-            if #available(iOS 13, *) {
-                return isThemeDark ? rowCount : rowCount - 1
-            } else {
-                return isThemeDark ? rowCount - 1 : rowCount - 2
-            }
-        }
-
         return rowCount
     }
 
@@ -128,20 +109,7 @@ extension ActionSheetSpecifier: ActionSheetDataSource {
             return UICollectionViewCell()
         }
 
-        if preferenceKey == kVLCSettingAppTheme &&
-            PresentationTheme.current.isDark && indexPath.row == numberOfRows() - 1 {
-            // Update the black background option cell
-            cell.setAccessoryType(to: .toggleSwitch)
-            cell.setToggleSwitch(state: UserDefaults.standard.bool(forKey: kVLCSettingAppThemeBlack))
-            cell.name.text = settingsBundle.localizedString(forKey: "SETTINGS_THEME_BLACK", value: "", table: "Root")
-            let cellIdentifier = ActionSheetCellIdentifier.blackBackground
-            cell.identifier = cellIdentifier
-            cell.name.accessibilityLabel = cellIdentifier.description
-            cell.name.accessibilityHint = cellIdentifier.accessibilityHint
-            cell.delegate = self
-
-            return cell
-        } else if preferenceKey == kVLCAutomaticallyPlayNextItem {
+        if preferenceKey == kVLCAutomaticallyPlayNextItem {
             cell.setAccessoryType(to: .toggleSwitch)
             let isFirstRow: Bool = indexPath.row == 0
 
diff --git a/Sources/Settings/Model/SettingsSection.swift b/Sources/Settings/Model/SettingsSection.swift
index a7b6ffbe598ddc6c2906c0d78aae9d2ab5a88f9c..c0c76f41edf42e2ff8b8f47601e01282b8a8000d 100644
--- a/Sources/Settings/Model/SettingsSection.swift
+++ b/Sources/Settings/Model/SettingsSection.swift
@@ -23,6 +23,7 @@ struct SettingsItem: Equatable {
     let title: String
     let subtitle: String?
     let action: Action
+    let isEnabled: Bool
     let isTitleEmphasized: Bool
 
     @available(*, deprecated, message: "access from self.action")
@@ -37,15 +38,16 @@ struct SettingsItem: Equatable {
         }
     }
 
-    init(title: String, subtitle: String?, action: Action, isTitleEmphasized: Bool = false) {
+    init(title: String, subtitle: String?, action: Action, isEnabled: Bool = true, isTitleEmphasized: Bool = false) {
         self.title = Localizer.localizedTitle(key: title)
         self.subtitle = subtitle.flatMap(Localizer.localizedTitle(key:))
         self.action = action
+        self.isEnabled = isEnabled
         self.isTitleEmphasized = isTitleEmphasized
     }
 
-    static func toggle(title: String, subtitle: String?, preferenceKey: String) -> Self {
-        return Self(title: title, subtitle: subtitle, action: .toggle(Toggle(preferenceKey: preferenceKey)))
+    static func toggle(title: String, subtitle: String? = nil, preferenceKey: String, isEnabled: Bool = true) -> Self {
+        return Self(title: title, subtitle: subtitle, action: .toggle(Toggle(preferenceKey: preferenceKey)), isEnabled: isEnabled)
     }
 
     enum Action: Equatable {
@@ -176,10 +178,18 @@ enum MainOptions {
                      action: .showActionSheet(title: "SETTINGS_DARKTHEME", preferenceKey: k, hasInfo: false))
     }
 
+    static var blackTheme: SettingsItem {
+        .toggle(title: "SETTINGS_THEME_BLACK",
+                subtitle: "SETTINGS_THEME_BLACK_SUBTITLE",
+                preferenceKey: kVLCSettingAppThemeBlack,
+                isEnabled: UserDefaults.standard.integer(forKey: kVLCSettingAppTheme) != kVLCSettingAppThemeBright)
+    }
+
     static func section() -> SettingsSection? {
         .init(title: nil, items: [
             privacy,
             appearance,
+            blackTheme
         ])
     }
 }
@@ -217,7 +227,6 @@ enum GenericOptions {
 
     static var playVideoInFullScreen: SettingsItem {
         .toggle(title: "SETTINGS_VIDEO_FULLSCREEN",
-                subtitle: nil,
                 preferenceKey: kVLCSettingVideoFullscreenPlayback)
     }
 
@@ -237,19 +246,16 @@ enum GenericOptions {
 
     static var enableTextScrollingInMediaList: SettingsItem {
         .toggle(title: "SETTINGS_ENABLE_MEDIA_CELL_TEXT_SCROLLING",
-                subtitle: nil,
                 preferenceKey: kVLCSettingEnableMediaCellTextScrolling)
     }
 
     static var rememberPlayerState: SettingsItem {
         .toggle(title: "SETTINGS_REMEMBER_PLAYER_STATE",
-                subtitle: nil,
                 preferenceKey: kVLCPlayerShouldRememberState)
     }
 
     static var restoreLastPlayedMedia: SettingsItem {
         .toggle(title: "SETTINGS_RESTORE_LAST_PLAYED_MEDIA",
-                subtitle: nil,
                 preferenceKey: kVLCRestoreLastPlayedMedia)
     }
 
@@ -323,43 +329,36 @@ enum PrivacyOptions {
 enum GestureControlOptions {
     static var swipeUpDownForVolume: SettingsItem {
         .toggle(title: "SETTINGS_GESTURES_VOLUME",
-                subtitle: nil,
                 preferenceKey: kVLCSettingVolumeGesture)
     }
 
     static var twoFingerTap: SettingsItem {
         .toggle(title: "SETTINGS_GESTURES_PLAYPAUSE",
-                subtitle: nil,
                 preferenceKey: kVLCSettingPlayPauseGesture)
     }
 
     static var swipeUpDownForBrightness: SettingsItem {
         .toggle(title: "SETTINGS_GESTURES_BRIGHTNESS",
-                subtitle: nil,
                 preferenceKey: kVLCSettingBrightnessGesture)
     }
 
     static var swipeRightLeftToSeek: SettingsItem {
         .toggle(title: "SETTINGS_GESTURES_SEEK",
-                subtitle: nil,
                 preferenceKey: kVLCSettingSeekGesture)
     }
 
     static var pinchToClose: SettingsItem {
         .toggle(title: "SETTINGS_GESTURES_CLOSE",
-                subtitle: nil,
                 preferenceKey: kVLCSettingCloseGesture)
     }
 
     static var forwardBackwardEqual: SettingsItem {
         .toggle(title: "SETTINGS_GESTURES_FORWARD_BACKWARD_EQUAL",
-                subtitle: nil,
                 preferenceKey: kVLCSettingPlaybackForwardBackwardEqual)
     }
 
     static var tapSwipeEqual: SettingsItem {
         .toggle(title: "SETTINGS_GESTURES_TAP_SWIPE_EQUAL",
-                subtitle: nil,
                 preferenceKey: kVLCSettingPlaybackTapSwipeEqual)
     }
 
@@ -393,7 +392,6 @@ enum GestureControlOptions {
 
     static var longTouchToSpeedUp: SettingsItem {
         .toggle(title: "SETINGS_LONG_TOUCH_SPEED_UP",
-                subtitle: nil,
                 preferenceKey: kVLCSettingPlaybackLongTouchSpeedUp)
     }
 
@@ -492,13 +490,11 @@ enum VideoOptions {
 
     static var rememberPlayerBrightness: SettingsItem {
         .toggle(title: "SETTINGS_REMEMBER_PLAYER_BRIGHTNESS",
-                subtitle: nil,
                 preferenceKey: kVLCPlayerShouldRememberBrightness)
     }
 
     static var lockRotation: SettingsItem {
         .toggle(title: "SETTINGS_LOCK_ROTATION",
-                subtitle: nil,
                 preferenceKey: kVLCSettingRotationLock)
     }
 
@@ -538,7 +534,6 @@ enum SubtitlesOptions {
 
     static var useBoldFont: SettingsItem {
         .toggle(title: "SETTINGS_SUBTITLES_BOLDFONT",
-                subtitle: nil,
                 preferenceKey: kVLCSettingSubtitlesBoldFont)
     }
 
@@ -610,7 +605,6 @@ enum AudioOptions {
 
     static var audioPlaybackInBackground: SettingsItem {
         .toggle(title: "SETTINGS_BACKGROUND_AUDIO",
-                subtitle: nil,
                 preferenceKey: kVLCSettingContinueAudioInBackgroundKey)
     }
 
@@ -635,31 +629,26 @@ enum MediaLibraryOptions {
 
     static var optimiseItemNamesForDisplay: SettingsItem {
         .toggle(title: "SETTINGS_DECRAPIFY",
-                subtitle: nil,
                 preferenceKey: kVLCSettingsDecrapifyTitles)
     }
 
     static var disableGrouping: SettingsItem {
         .toggle(title: "SETTINGS_DISABLE_GROUPING",
-                subtitle: nil,
                 preferenceKey: kVLCSettingsDisableGrouping)
     }
 
     static var showVideoThumbnails: SettingsItem {
         .toggle(title: "SETTINGS_SHOW_THUMBNAILS",
-                subtitle: nil,
                 preferenceKey: kVLCSettingShowThumbnails)
     }
 
     static var showAudioArtworks: SettingsItem {
         .toggle(title: "SETTINGS_SHOW_ARTWORKS",
-                subtitle: nil,
                 preferenceKey: kVLCSettingShowArtworks)
     }
 
     static var includeMediaLibInDeviceBackup: SettingsItem {
         .toggle(title: "SETTINGS_BACKUP_MEDIA_LIBRARY",
-                subtitle: nil,
                 preferenceKey: kVLCSettingBackupMediaLibrary)
     }
 
@@ -698,7 +687,6 @@ enum NetworkOptions {
 
     static var ipv6SupportForWiFiSharing: SettingsItem {
         .toggle(title: "SETTINGS_WIFISHARING_IPv6",
-                subtitle: nil,
                 preferenceKey: kVLCSettingWiFiSharingIPv6)
     }
 
@@ -710,7 +698,6 @@ enum NetworkOptions {
 
     static var rtspctp: SettingsItem {
         .toggle(title: "SETTINGS_RTSP_TCP",
-                subtitle: nil,
                 preferenceKey: kVLCSettingNetworkRTSPTCP)
     }
 
@@ -736,7 +723,6 @@ enum Accessibility {
 
     static var pauseWhenShowingControls: SettingsItem {
         .toggle(title: "SETTINGS_PAUSE_WHEN_SHOWING_CONTROLS",
-                subtitle: nil,
                 preferenceKey: kVLCSettingPauseWhenShowingControls)
     }
 
@@ -753,7 +739,6 @@ enum Accessibility {
 enum Lab {
     static var debugLogging: SettingsItem {
         .toggle(title: "SETTINGS_DEBUG_LOG",
-                subtitle: nil,
                 preferenceKey: kVLCSaveDebugLogs)
     }
 
diff --git a/Sources/Settings/View/SettingsCell.swift b/Sources/Settings/View/SettingsCell.swift
index 0f9a69edc21716f0a46359fadf41f10d97a63945..a529bacec27d1153897ed6773836047a3a87e71a 100644
--- a/Sources/Settings/View/SettingsCell.swift
+++ b/Sources/Settings/View/SettingsCell.swift
@@ -15,6 +15,7 @@ protocol SettingsCellDelegate: AnyObject {
     /// Implementations should only perform side effects on
     /// specific preferences; updating the preference itself
     /// is handled by the cell.
+    @available(*, deprecated, message: "Side effects of toggling a setting should be performed by observing changes to userdefaults")
     func settingsCellDidChangeSwitchState(cell: SettingsCell, preferenceKey: String, isOn: Bool)
 
     func settingsCellInfoButtonPressed(cell: SettingsCell, preferenceKey: String)
@@ -30,6 +31,7 @@ class SettingsCell: UITableViewCell {
         static let marginBottom: CGFloat = 10
         static let marginLeading: CGFloat = 20
         static let marginTrailing: CGFloat = 70
+        static let disabledAlpha: CGFloat = 0.3
     }
 
     weak var delegate: SettingsCellDelegate?
@@ -208,6 +210,15 @@ class SettingsCell: UITableViewCell {
             } else {
                 activityIndicator.stopAnimating()
             }
+
+            if settingsItem.isEnabled {
+                switchControl.isEnabled = true
+                contentView.alpha = 1
+            } else {
+                switchControl.isEnabled = false
+                contentView.alpha = Constants.disabledAlpha
+            }
+
         }
     }
 
@@ -221,6 +232,10 @@ class SettingsCell: UITableViewCell {
         fatalError("init(coder:) has not been implemented")
     }
 
+    func themeChanged() {
+        setupTheme()
+    }
+
     override func prepareForReuse() {
         super.prepareForReuse()
         backgroundColor = .clear // Required to prevent theme mismatch during setupTheme
diff --git a/Sources/UI Elements/PresentationTheme.swift b/Sources/UI Elements/PresentationTheme.swift
index 10585824d615117d0918763f826bdb617a6c728d..7fa2e8c3391a897b053cfec580511da8c2aa141b 100644
--- a/Sources/UI Elements/PresentationTheme.swift	
+++ b/Sources/UI Elements/PresentationTheme.swift	
@@ -43,27 +43,27 @@ extension Notification.Name {
     let thumbnailBackgroundColor: UIColor
 
     init(isDark: Bool,
-                name: String,
-                statusBarStyle: UIStatusBarStyle,
-                navigationbarColor: UIColor,
-                navigationbarTextColor: UIColor,
-                background: UIColor,
-                cellBackgroundA: UIColor,
-                cellBackgroundB: UIColor,
-                cellDetailTextColor: UIColor,
-                cellTextColor: UIColor,
-                lightTextColor: UIColor,
-                sectionHeaderTextColor: UIColor,
-                separatorColor: UIColor,
-                mediaCategorySeparatorColor: UIColor,
-                tabBarColor: UIColor,
-                orangeUI: UIColor,
-                orangeDarkAccent: UIColor,
-                toolBarStyle: UIBarStyle,
-                blurStyle: UIBlurEffect.Style,
-                textfieldBorderColor: UIColor,
-                textfieldPlaceholderColor: UIColor,
-                thumbnailBackgroundColor: UIColor) {
+         name: String,
+         statusBarStyle: UIStatusBarStyle,
+         navigationbarColor: UIColor,
+         navigationbarTextColor: UIColor,
+         background: UIColor,
+         cellBackgroundA: UIColor,
+         cellBackgroundB: UIColor,
+         cellDetailTextColor: UIColor,
+         cellTextColor: UIColor,
+         lightTextColor: UIColor,
+         sectionHeaderTextColor: UIColor,
+         separatorColor: UIColor,
+         mediaCategorySeparatorColor: UIColor,
+         tabBarColor: UIColor,
+         orangeUI: UIColor,
+         orangeDarkAccent: UIColor,
+         toolBarStyle: UIBarStyle,
+         blurStyle: UIBlurEffect.Style,
+         textfieldBorderColor: UIColor,
+         textfieldPlaceholderColor: UIColor,
+         thumbnailBackgroundColor: UIColor) {
         self.isDark = isDark
         self.name = name
         self.statusBarStyle = statusBarStyle
@@ -89,6 +89,8 @@ extension Notification.Name {
     }
 }
 
+// MARK: - Typography
+
 @objcMembers class Typography: NSObject {
     
     let tableHeaderFont: UIFont
@@ -106,6 +108,8 @@ enum PresentationThemeType: Int {
     case auto
 }
 
+// MARK: - PresentationTheme
+
 @objcMembers class PresentationTheme: NSObject {
 
     static let brightTheme = PresentationTheme(colors: brightPalette)
@@ -182,6 +186,8 @@ enum PresentationThemeType: Int {
     let font = defaultFont
 }
 
+// MARK: - UIColor
+
 @objc extension UIColor {
 
     convenience init(_ rgbValue: UInt32, _ alpha: CGFloat = 1.0) {
diff --git a/VLC.xcodeproj/project.pbxproj b/VLC.xcodeproj/project.pbxproj
index 4f743280f4f004331d3647178a63a614cc99cd41..ee52f64ec0a9eead2951ccd6faa8e421dc91cb3f 100644
--- a/VLC.xcodeproj/project.pbxproj
+++ b/VLC.xcodeproj/project.pbxproj
@@ -96,6 +96,8 @@
 		444E5BFA24C6081B0003B69C /* PasscodeLockController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 444E5BF924C6081A0003B69C /* PasscodeLockController.swift */; };
 		444E5C0024C719480003B69C /* AboutController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 444E5BFF24C719480003B69C /* AboutController.swift */; };
 		44B5822024E434FD001A2583 /* MediaGridCollectionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44B5821F24E434FD001A2583 /* MediaGridCollectionCell.swift */; };
+		44BA0BD62D80CF4D004CF52E /* DefaultsChangeListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44BA0BD52D80CF20004CF52E /* DefaultsChangeListener.swift */; };
+		44BA0BD72D80CF4D004CF52E /* DefaultsChangeListener.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44BA0BD52D80CF20004CF52E /* DefaultsChangeListener.swift */; };
 		44C8BBA324AF2B5C003F8940 /* FeedbackGenerators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44C8BBA224AF2B5C003F8940 /* FeedbackGenerators.swift */; };
 		44C8BBAE24AF36F4003F8940 /* SettingsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44C8BBA624AF36F4003F8940 /* SettingsController.swift */; };
 		44C8BBAF24AF36F4003F8940 /* SettingsSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 44C8BBA824AF36F4003F8940 /* SettingsSection.swift */; };
@@ -1013,6 +1015,7 @@
 		444E5BF924C6081A0003B69C /* PasscodeLockController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasscodeLockController.swift; sourceTree = "<group>"; };
 		444E5BFF24C719480003B69C /* AboutController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutController.swift; sourceTree = "<group>"; };
 		44B5821F24E434FD001A2583 /* MediaGridCollectionCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaGridCollectionCell.swift; sourceTree = "<group>"; };
+		44BA0BD52D80CF20004CF52E /* DefaultsChangeListener.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultsChangeListener.swift; sourceTree = "<group>"; };
 		44C8BBA224AF2B5C003F8940 /* FeedbackGenerators.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FeedbackGenerators.swift; sourceTree = "<group>"; };
 		44C8BBA624AF36F4003F8940 /* SettingsController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsController.swift; sourceTree = "<group>"; };
 		44C8BBA824AF36F4003F8940 /* SettingsSection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsSection.swift; sourceTree = "<group>"; };
@@ -3100,6 +3103,7 @@
 				418B144C20179C74000447AA /* TabBarCoordinator.swift */,
 				8F9108342A67AC76007EB0D5 /* SirikitIntentCoordinator.swift */,
 				91562F582CAEBC1500D42986 /* PlayMediaIntent.swift */,
+				44BA0BD52D80CF20004CF52E /* DefaultsChangeListener.swift */,
 			);
 			path = iOS;
 			sourceTree = "<group>";
@@ -4444,6 +4448,7 @@
 				7D50C6902BBD20DF00B9F1A0 /* VLCLocalNetworkServiceNetService.m in Sources */,
 				7D274D582D2AE81C00ADDC41 /* LongPressPlaybackSpeedView.swift in Sources */,
 				7D50C6912BBD20DF00B9F1A0 /* VLCPlexWebAPI.m in Sources */,
+				44BA0BD72D80CF4D004CF52E /* DefaultsChangeListener.swift in Sources */,
 				7D50C6922BBD20DF00B9F1A0 /* VLCDonationNagScreenViewController.m in Sources */,
 				7D50C6932BBD20DF00B9F1A0 /* ButtonBarView.swift in Sources */,
 				7D50C6942BBD20DF00B9F1A0 /* MediaPlayerActionSheet.swift in Sources */,
@@ -4641,6 +4646,7 @@
 				DD3EFF411BDEBCE500B68579 /* VLCNetworkServerBrowserSharedLibrary.m in Sources */,
 				7DC1865A2A0BB0C3009E84E1 /* UIImage+Gradient.swift in Sources */,
 				8D15A1F022B0FB9300CFA758 /* QueueViewController.swift in Sources */,
+				44BA0BD62D80CF4D004CF52E /* DefaultsChangeListener.swift in Sources */,
 				D96C9EBC28105F5B005F13BB /* AlbumHeader.swift in Sources */,
 				418E88412110E51B00DDA6A7 /* URLHandler.swift in Sources */,
 				8DE187812105DAB100A091D2 /* VideoViewController.swift in Sources */,