Commit c2f15dac authored by Kourser's avatar Kourser
Browse files

fix(macos): make the menu-bar commands actually work

Two defects in the first wiring:

- The command closures read the playback controller straight from the
  scene body, where observation never re-fires: the Lecture menu items
  kept the state captured at launch (no episode -> permanently disabled,
  so none of the shortcuts responded). The menu content now lives in
  child views (PlaybackCommands / AddCommands), where the observable
  state re-renders labels and disabled flags live.
- The Fichier additions used CommandGroup(after: .newItem), leaving the
  default 'Nouvelle fenetre' owning the ⌘N key equivalent. The group now
  replaces .newItem so ⌘N reaches 'Ajouter un podcast…'.

Co-Authored-By: Claude (RCA)
parent e1dd94d4
Loading
Loading
Loading
Loading
+48 −0
Original line number Diff line number Diff line
@@ -1587,6 +1587,9 @@
          }
        }
      }
    },
    "Ajouter la station" : {
    },
    "Ajouter par URL" : {
      "localizations" : {
@@ -1811,6 +1814,12 @@
          }
        }
      }
    },
    "Ajouter un podcast ou une radio" : {
    },
    "Ajouter un podcast…" : {
    },
    "Ajouter une radio" : {
      "localizations" : {
@@ -1923,6 +1932,9 @@
          }
        }
      }
    },
    "Ajouter une radio…" : {
    },
    "Ajoutez des épisodes à la file depuis un podcast." : {
      "localizations" : {
@@ -3379,6 +3391,9 @@
          }
        }
      }
    },
    "Avancer de %lld s" : {
    },
    "Basses" : {
      "localizations" : {
@@ -8535,6 +8550,9 @@
          }
        }
      }
    },
    "Général" : {
    },
    "gpodder.net" : {
      "shouldTranslate" : false
@@ -9328,6 +9346,9 @@
          }
        }
      }
    },
    "Importer un fichier OPML…" : {
    },
    "Impossible de charger ce podcast." : {
      "localizations" : {
@@ -10896,6 +10917,12 @@
          }
        }
      }
    },
    "Minuteur de sommeil" : {
    },
    "Moins vite" : {
    },
    "Mot de passe" : {
      "localizations" : {
@@ -12246,6 +12273,9 @@
          }
        }
      }
    },
    "Ouvrir le lecteur" : {
    },
    "Partager" : {
      "localizations" : {
@@ -12918,6 +12948,9 @@
          }
        }
      }
    },
    "Plus vite" : {
    },
    "Populaires" : {
      "localizations" : {
@@ -14374,6 +14407,9 @@
          }
        }
      }
    },
    "Reculer de %lld s" : {
    },
    "Redémarrez l'application pour appliquer la langue de l'interface. Les suggestions s'adaptent immédiatement." : {
      "localizations" : {
@@ -21209,6 +21245,9 @@
          }
        }
      }
    },
    "Tous les épisodes seront retirés de la file d'attente." : {
    },
    "Tous les épisodes téléchargés seront supprimés. Ils pourront être retéléchargés." : {
      "localizations" : {
@@ -22217,6 +22256,9 @@
          }
        }
      }
    },
    "Trier et filtrer les abonnements" : {
    },
    "URL de votre instance Nextcloud (app GPodder Sync), p. ex. https://cloud.exemple.com" : {
      "localizations" : {
@@ -23001,6 +23043,9 @@
          }
        }
      }
    },
    "Vider la file ?" : {
    },
    "Vider le cache" : {
      "localizations" : {
@@ -23897,6 +23942,9 @@
          }
        }
      }
    },
    "Volume de l'application" : {
    },
    "WiFi uniquement" : {
      "localizations" : {
+56 −30
Original line number Diff line number Diff line
@@ -52,29 +52,76 @@ struct SkingomzApp: App {
        .defaultSize(width: 1000, height: 700)
        #endif
        .commands {
            CommandGroup(after: .newItem) {
                Button("Ajouter un podcast…") { commandCenter.showAddPodcast = true }
            // Replacing .newItem drops the default "Nouvelle fenêtre" (⌘N),
            // which would otherwise win the ⌘N key equivalent.
            CommandGroup(replacing: .newItem) {
                AddCommands(commands: commandCenter)
            }
            CommandMenu("Lecture") {
                // A child view, so the menu observes the playback state
                // (labels and enabled/disabled update live).
                PlaybackCommands(playback: playback, settings: playbackSettings)
            }
        }
        #if os(iOS)
        .backgroundTask(.appRefresh(BackgroundRefresh.taskIdentifier)) {
            await model.backgroundRefresh()
            BackgroundRefresh.schedule()
        }
        #endif

        #if os(macOS)
        Settings {
            MacSettingsView()
                .environment(model)
                .environment(playbackSettings)
                .environment(languageSettings)
                .environment(model.syncSettings)
                .environment(model.downloadSettings)
                .environment(model.notifications)
                .environment(model.equalizerSettings)
        }
        #endif
    }

}

/// Fichier menu additions (⌘N, ⇧⌘N, ⌘O), bridged to RootView's sheets.
private struct AddCommands: View {
    let commands: CommandCenter

    var body: some View {
        Button("Ajouter un podcast…") { commands.showAddPodcast = true }
            .keyboardShortcut("n")
                Button("Ajouter une radio…") { commandCenter.showAddRadio = true }
        Button("Ajouter une radio…") { commands.showAddRadio = true }
            .keyboardShortcut("n", modifiers: [.command, .shift])
                Button("Importer un fichier OPML…") { commandCenter.showOPMLImporter = true }
        Button("Importer un fichier OPML…") { commands.showOPMLImporter = true }
            .keyboardShortcut("o")
    }
            CommandMenu("Lecture") {
}

/// Lecture menu content. Lives in its own view so the observable playback
/// state re-renders the menu items — command closures evaluated at the scene
/// level would freeze labels and disabled states at launch time.
private struct PlaybackCommands: View {
    let playback: PlaybackController
    let settings: PlaybackSettings

    var body: some View {
        Button(playback.isPlaying ? "Pause" : "Lecture") {
            playback.togglePlayPause()
        }
        .keyboardShortcut(.space, modifiers: [])
        .disabled(playback.currentEpisode == nil)

                Button("Reculer de \(playbackSettings.skipBackward) s") {
                    playback.skipBackward(TimeInterval(playbackSettings.skipBackward))
        Button("Reculer de \(settings.skipBackward) s") {
            playback.skipBackward(TimeInterval(settings.skipBackward))
        }
        .keyboardShortcut(.leftArrow)
        .disabled(playback.currentEpisode == nil)

                Button("Avancer de \(playbackSettings.skipForward) s") {
                    playback.skipForward(TimeInterval(playbackSettings.skipForward))
        Button("Avancer de \(settings.skipForward) s") {
            playback.skipForward(TimeInterval(settings.skipForward))
        }
        .keyboardShortcut(.rightArrow)
        .disabled(playback.currentEpisode == nil)
@@ -102,27 +149,6 @@ struct SkingomzApp: App {
        }
        .disabled(playback.currentEpisode == nil)
    }
        }
        #if os(iOS)
        .backgroundTask(.appRefresh(BackgroundRefresh.taskIdentifier)) {
            await model.backgroundRefresh()
            BackgroundRefresh.schedule()
        }
        #endif

        #if os(macOS)
        Settings {
            MacSettingsView()
                .environment(model)
                .environment(playbackSettings)
                .environment(languageSettings)
                .environment(model.syncSettings)
                .environment(model.downloadSettings)
                .environment(model.notifications)
                .environment(model.equalizerSettings)
        }
        #endif
    }

    /// Mirrors the player's rate stepper: snapped to 0.1, clamped to 0.5×–3×.
    private func adjustRate(_ delta: Float) {