diff --git a/Yattee/Localizable.xcstrings b/Yattee/Localizable.xcstrings index 3a41e253..e022f58e 100644 --- a/Yattee/Localizable.xcstrings +++ b/Yattee/Localizable.xcstrings @@ -19865,6 +19865,16 @@ } } }, + "videoInfo.playTip.messageWithSwipe" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tap the thumbnail to start playing this video. Swipe it left or right to browse other videos from this list." + } + } + } + }, "videoInfo.playTip.title" : { "localizations" : { "en" : { diff --git a/Yattee/Views/Video/VideoInfoPlayThumbnailTip.swift b/Yattee/Views/Video/VideoInfoPlayThumbnailTip.swift index d1ef9441..f94ffc43 100644 --- a/Yattee/Views/Video/VideoInfoPlayThumbnailTip.swift +++ b/Yattee/Views/Video/VideoInfoPlayThumbnailTip.swift @@ -4,6 +4,7 @@ // // TipKit hint that the hero thumbnail plays the video. Shown once, only while the // toolbar action layout is active (the inline layout has an explicit Play button). +// When the thumbnail is a carousel over the video's context, it also mentions swiping. // #if !os(tvOS) @@ -15,12 +16,17 @@ struct VideoInfoPlayThumbnailTip: Tip { @Parameter static var isToolbarLayout: Bool = false + /// Whether the thumbnail can be swiped to browse other videos in the context. + var canSwipe = false + var title: Text { Text(String(localized: "videoInfo.playTip.title")) } var message: Text? { - Text(String(localized: "videoInfo.playTip.message")) + Text(canSwipe + ? String(localized: "videoInfo.playTip.messageWithSwipe") + : String(localized: "videoInfo.playTip.message")) } var image: Image? { @@ -35,10 +41,11 @@ struct VideoInfoPlayThumbnailTip: Tip { /// Attaches the play-thumbnail tip to the hero thumbnail when enabled. struct VideoInfoPlayThumbnailTipModifier: ViewModifier { let enabled: Bool - private let tip = VideoInfoPlayThumbnailTip() + private let tip: VideoInfoPlayThumbnailTip - init(enabled: Bool) { + init(enabled: Bool, canSwipe: Bool) { self.enabled = enabled + self.tip = VideoInfoPlayThumbnailTip(canSwipe: canSwipe) } func body(content: Content) -> some View { diff --git a/Yattee/Views/Video/VideoInfoView.swift b/Yattee/Views/Video/VideoInfoView.swift index d64d86ca..f5c97da5 100644 --- a/Yattee/Views/Video/VideoInfoView.swift +++ b/Yattee/Views/Video/VideoInfoView.swift @@ -1128,7 +1128,7 @@ struct VideoInfoView: View { } } #if !os(tvOS) - .modifier(VideoInfoPlayThumbnailTipModifier(enabled: isCurrent && showsThumbnailPlayTip)) + .modifier(VideoInfoPlayThumbnailTipModifier(enabled: isCurrent && showsThumbnailPlayTip, canSwipe: canSwipeThumbnails)) #endif // Title - full card width so long titles fit more characters per line. @@ -1381,6 +1381,15 @@ struct VideoInfoView: View { usesToolbarActions && primaryAction != .play } + /// The hero thumbnail is a swipeable carousel over the queue context (iOS only, see headerSection). + private var canSwipeThumbnails: Bool { + #if os(iOS) + videoQueueContext != nil && (allVideos?.count ?? 0) > 1 + #else + false + #endif + } + /// One toolbar action rendered either as a standalone toolbar item or as a menu row. /// The same Label works in both places: the toolbar shows the icon, the menu shows icon + text. @ViewBuilder