[vlc-commits] [Git][videolan/vlc][master] 22 commits: macosx: Add started VLCLibraryHeroView XIB

Steve Lhomme (@robUx4) gitlab at videolan.org
Sun Sep 10 08:59:42 UTC 2023



Steve Lhomme pushed to branch master at VideoLAN / VLC


Commits:
fb1526eb by Claudio Cambra at 2023-09-10T08:42:52+00:00
macosx: Add started VLCLibraryHeroView XIB

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
b31aa8e4 by Claudio Cambra at 2023-09-10T08:42:52+00:00
macosx: Implement starter design for hero view

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
2e922eeb by Claudio Cambra at 2023-09-10T08:42:52+00:00
macosx: Track count of leading custom containers in VLCLibraryVideoCollectionViewsStackViewController

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
1f165214 by Claudio Cambra at 2023-09-10T08:42:52+00:00
macosx: Add VLCLibraryHeroView class

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
0a702a0e by Claudio Cambra at 2023-09-10T08:42:52+00:00
macosx: Add fromNibWithOwner method to VLCLibraryHeroView

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
e6fae356 by Claudio Cambra at 2023-09-10T08:42:52+00:00
macosx: Separate constraint setup for new container views for video library view into new method

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
94fc2361 by Claudio Cambra at 2023-09-10T08:42:52+00:00
macosx: Add convenience method to add NSView to video library view stack view

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
82ad32f7 by Claudio Cambra at 2023-09-10T08:42:52+00:00
macosx: Initialise hero view in VLCLibraryVideoCollectionViewsStackViewController

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
85fe4306 by Claudio Cambra at 2023-09-10T08:42:52+00:00
macosx: Add outlets for main hero view components

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
f277c393 by Claudio Cambra at 2023-09-10T08:42:52+00:00
macosx: Accept objects conforming to media library item protocol in VLCLibraryImageCache

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
b035c493 by Claudio Cambra at 2023-09-10T08:42:52+00:00
macosx: Add ability to set represented media library item on VLCLibraryHeroView

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
e322c06b by Claudio Cambra at 2023-09-10T08:42:52+00:00
macosx: Add a convenience method to set a represented item at random on VLCHeroView

- - - - -
34dd520d by Claudio Cambra at 2023-09-10T08:42:52+00:00
macosx: Improve visibility of labels in VLCLibraryHeroView

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
9cdb4548 by Claudio Cambra at 2023-09-10T08:42:52+00:00
macosx: Rewrite "setRandomItem" as a property-based getter instead

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
3ed1036c by Claudio Cambra at 2023-09-10T08:42:52+00:00
macosx: Add internal property to get latest partially played video item

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
558390ac by Claudio Cambra at 2023-09-10T08:42:52+00:00
macosx: Add setOptimalRepresentedItem method for VLCLibraryHeroView

Finds either the most recently played item or a random item from the
library to present in the hero view

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
9173362e by Claudio Cambra at 2023-09-10T08:42:52+00:00
macosx: Set optimal represented item on hero view upon reload of library video view

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
cd50cf9d by Claudio Cambra at 2023-09-10T08:42:52+00:00
macosx: Replace standard NSImageView with VLCImageView in VLCLibraryHeroView

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
35050510 by Claudio Cambra at 2023-09-10T08:42:52+00:00
macosx: Make hero view play button functional

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
52baf740 by Claudio Cambra at 2023-09-10T08:42:52+00:00
macosx: Adjust text of hero view playh button depending on set optimal item

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
57527179 by Claudio Cambra at 2023-09-10T08:42:52+00:00
macosx: Add a explanatory text field to display why video is being shown in hero view

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -
9196b9f8 by Claudio Cambra at 2023-09-10T08:42:52+00:00
macosx: Update hero view explanation text field depending on optimal item set

Signed-off-by: Claudio Cambra <developer at claudiocambra.com>

- - - - -


9 changed files:

- extras/package/macosx/VLC.xcodeproj/project.pbxproj
- modules/gui/macosx/Makefile.am
- + modules/gui/macosx/UI/VLCLibraryHeroView.xib
- + modules/gui/macosx/library/VLCLibraryHeroView.h
- + modules/gui/macosx/library/VLCLibraryHeroView.m
- modules/gui/macosx/library/VLCLibraryImageCache.h
- modules/gui/macosx/library/VLCLibraryImageCache.m
- modules/gui/macosx/library/video-library/VLCLibraryVideoCollectionViewsStackViewController.h
- modules/gui/macosx/library/video-library/VLCLibraryVideoCollectionViewsStackViewController.m


Changes:

=====================================
extras/package/macosx/VLC.xcodeproj/project.pbxproj
=====================================
@@ -108,6 +108,7 @@
 		539BA79F298C726200918C36 /* VLCAspectRatioRetainingVideoWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 539BA79E298C726200918C36 /* VLCAspectRatioRetainingVideoWindow.m */; };
 		539F114B29E83A4200F13460 /* VLCLibraryTwoPaneSplitViewDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 539F114A29E83A4200F13460 /* VLCLibraryTwoPaneSplitViewDelegate.m */; };
 		539F116D29F9785C00F13460 /* VLCMainVideoViewAudioMediaDecorativeView.m in Sources */ = {isa = PBXBuildFile; fileRef = 539F116C29F9785C00F13460 /* VLCMainVideoViewAudioMediaDecorativeView.m */; };
+		53B40FD72AA878E400C814E4 /* VLCLibraryHeroView.m in Sources */ = {isa = PBXBuildFile; fileRef = 53B40FD62AA878E400C814E4 /* VLCLibraryHeroView.m */; };
 		53B447CA2939823E00857588 /* VLCLibrarySongsTableViewSongPlayingTableCellView.m in Sources */ = {isa = PBXBuildFile; fileRef = 53B447C92939823E00857588 /* VLCLibrarySongsTableViewSongPlayingTableCellView.m */; };
 		53B447F6293BB47B00857588 /* VLCLibraryVideoCollectionViewContainerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 53B447EC293BB47A00857588 /* VLCLibraryVideoCollectionViewContainerView.m */; };
 		53B447F7293BB47B00857588 /* VLCLibraryVideoCollectionViewContainerViewDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 53B447ED293BB47A00857588 /* VLCLibraryVideoCollectionViewContainerViewDataSource.m */; };
@@ -331,6 +332,9 @@
 		539F116A29F9756000F13460 /* VLCMainVideoViewAudioMediaDecorativeView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = VLCMainVideoViewAudioMediaDecorativeView.xib; sourceTree = "<group>"; };
 		539F116B29F9785C00F13460 /* VLCMainVideoViewAudioMediaDecorativeView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCMainVideoViewAudioMediaDecorativeView.h; sourceTree = "<group>"; };
 		539F116C29F9785C00F13460 /* VLCMainVideoViewAudioMediaDecorativeView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCMainVideoViewAudioMediaDecorativeView.m; sourceTree = "<group>"; };
+		53B40FD42AA7618000C814E4 /* VLCLibraryHeroView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = VLCLibraryHeroView.xib; sourceTree = "<group>"; };
+		53B40FD52AA878E400C814E4 /* VLCLibraryHeroView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCLibraryHeroView.h; sourceTree = "<group>"; };
+		53B40FD62AA878E400C814E4 /* VLCLibraryHeroView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCLibraryHeroView.m; sourceTree = "<group>"; };
 		53B447C82939823E00857588 /* VLCLibrarySongsTableViewSongPlayingTableCellView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VLCLibrarySongsTableViewSongPlayingTableCellView.h; sourceTree = "<group>"; };
 		53B447C92939823E00857588 /* VLCLibrarySongsTableViewSongPlayingTableCellView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VLCLibrarySongsTableViewSongPlayingTableCellView.m; sourceTree = "<group>"; };
 		53B447EC293BB47A00857588 /* VLCLibraryVideoCollectionViewContainerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VLCLibraryVideoCollectionViewContainerView.m; sourceTree = "<group>"; };
@@ -1216,6 +1220,8 @@
 				7DFBDCA72269E77500B700A5 /* VLCLibraryController.m */,
 				7DFBDCB2226CD00900B700A5 /* VLCLibraryDataTypes.h */,
 				7DFBDCB3226CD00900B700A5 /* VLCLibraryDataTypes.m */,
+				53B40FD52AA878E400C814E4 /* VLCLibraryHeroView.h */,
+				53B40FD62AA878E400C814E4 /* VLCLibraryHeroView.m */,
 				7D92AF1F23DDCA8D00D81EA3 /* VLCLibraryImageCache.h */,
 				7D92AF2023DDCA8D00D81EA3 /* VLCLibraryImageCache.m */,
 				7DFBDCAF226A518400B700A5 /* VLCLibraryMenuController.h */,
@@ -1843,6 +1849,7 @@
 				536283FB2911476A00640C15 /* VLCLibraryCollectionViewAudioGroupSupplementaryDetailView.xib */,
 				7D0F64052202047900FDB91F /* VLCLibraryCollectionViewItem.xib */,
 				536283FC2911476A00640C15 /* VLCLibraryCollectionViewMediaItemSupplementaryDetailView.xib */,
+				53B40FD42AA7618000C814E4 /* VLCLibraryHeroView.xib */,
 				536283FA2911476A00640C15 /* VLCLibrarySongTableCellView.xib */,
 				7DE2F0482282D7980040DD0A /* VLCLibraryTableCellView.xib */,
 				7D713D332201BB130042BEB7 /* VLCLibraryWindow.xib */,
@@ -1942,6 +1949,7 @@
 				7DFBDCA82269E77500B700A5 /* VLCLibraryController.m in Sources */,
 				1CCC88F12078A3D500E5626F /* AddonManager.xib in Sources */,
 				7DFBDCC1226DC16200B700A5 /* VLCInputItem.m in Sources */,
+				53B40FD72AA878E400C814E4 /* VLCLibraryHeroView.m in Sources */,
 				537976BA2A4319330036827E /* VLCSettingTextField.m in Sources */,
 				1CCC88F22078A3D500E5626F /* AudioEffects.xib in Sources */,
 				1CCC88F32078A3D500E5626F /* VideoEffects.xib in Sources */,


=====================================
modules/gui/macosx/Makefile.am
=====================================
@@ -110,6 +110,8 @@ libmacosx_plugin_la_SOURCES = \
 	gui/macosx/library/VLCLibraryController.m \
 	gui/macosx/library/VLCLibraryDataTypes.h \
 	gui/macosx/library/VLCLibraryDataTypes.m \
+	gui/macosx/library/VLCLibraryHeroView.h \
+	gui/macosx/library/VLCLibraryHeroView.m \
 	gui/macosx/library/VLCLibraryImageCache.h \
 	gui/macosx/library/VLCLibraryImageCache.m \
 	gui/macosx/library/VLCLibraryMenuController.h \
@@ -410,6 +412,7 @@ libmacosx_plugin_la_XIB_SOURCES = \
 	gui/macosx/UI/VLCLibraryCollectionViewAlbumSupplementaryDetailView.xib \
 	gui/macosx/UI/VLCLibraryCollectionViewAudioGroupSupplementaryDetailView.xib \
 	gui/macosx/UI/VLCLibraryCollectionViewMediaItemSupplementaryDetailView.xib \
+	gui/macosx/UI/VLCLibraryHeroView.xib \
 	gui/macosx/UI/VLCLibrarySongTableCellView.xib \
 	gui/macosx/UI/VLCMainVideoView.xib \
 	gui/macosx/UI/VLCMainVideoViewAudioMediaDecorativeView.xib \


=====================================
modules/gui/macosx/UI/VLCLibraryHeroView.xib
=====================================
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21701" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
+    <dependencies>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21701"/>
+        <capability name="Named colors" minToolsVersion="9.0"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <customObject id="-2" userLabel="File's Owner"/>
+        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+        <customObject id="-3" userLabel="Application" customClass="NSObject"/>
+        <customView wantsLayer="YES" translatesAutoresizingMaskIntoConstraints="NO" id="LPV-K6-7AE" customClass="VLCLibraryHeroView">
+            <rect key="frame" x="0.0" y="0.0" width="833" height="357"/>
+            <subviews>
+                <customView translatesAutoresizingMaskIntoConstraints="NO" id="qdP-As-qZ0" customClass="VLCImageView">
+                    <rect key="frame" x="0.0" y="0.0" width="833" height="357"/>
+                    <constraints>
+                        <constraint firstAttribute="height" constant="357" id="y7Y-rw-LCu"/>
+                    </constraints>
+                </customView>
+                <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="GoN-QI-mru">
+                    <rect key="frame" x="18" y="309" width="155" height="28"/>
+                    <shadow key="shadow" blurRadius="20">
+                        <color key="color" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
+                    </shadow>
+                    <textFieldCell key="cell" lineBreakMode="clipping" title="Last watched" id="Ggw-iA-v2x">
+                        <font key="font" metaFont="systemBold" size="24"/>
+                        <color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
+                        <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                    </textFieldCell>
+                </textField>
+                <stackView distribution="fill" orientation="vertical" alignment="leading" spacing="5" horizontalStackHuggingPriority="249.99998474121094" verticalStackHuggingPriority="249.99998474121094" detachesHiddenViews="YES" translatesAutoresizingMaskIntoConstraints="NO" id="U3j-Zx-fFf">
+                    <rect key="frame" x="20" y="20" width="250" height="86"/>
+                    <subviews>
+                        <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" textCompletion="NO" translatesAutoresizingMaskIntoConstraints="NO" id="kFW-i6-3hg">
+                            <rect key="frame" x="-2" y="58" width="103" height="28"/>
+                            <shadow key="shadow" blurRadius="20">
+                                <color key="color" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                            </shadow>
+                            <textFieldCell key="cell" controlSize="large" alignment="left" title="Item title" id="0Cs-Ex-sMn">
+                                <font key="font" metaFont="systemBold" size="24"/>
+                                <color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
+                                <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                            </textFieldCell>
+                        </textField>
+                        <textField horizontalHuggingPriority="251" verticalHuggingPriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="aVp-p4-DHX">
+                            <rect key="frame" x="-2" y="33" width="139" height="20"/>
+                            <shadow key="shadow" blurRadius="20">
+                                <color key="color" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
+                            </shadow>
+                            <textFieldCell key="cell" controlSize="large" title="Item detail string" id="P7c-bg-dPX">
+                                <font key="font" metaFont="systemSemibold" size="17"/>
+                                <color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
+                                <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
+                            </textFieldCell>
+                        </textField>
+                        <button verticalHuggingPriority="1000" verticalCompressionResistancePriority="1000" translatesAutoresizingMaskIntoConstraints="NO" id="5zZ-VM-Lb9">
+                            <rect key="frame" x="-3" y="-4" width="256" height="35"/>
+                            <buttonCell key="cell" type="bevel" title=" Resume playing" bezelStyle="regularSquare" image="play.circle.fill" catalog="system" imagePosition="leading" alignment="left" controlSize="large" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="639-6i-zsD">
+                                <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
+                                <font key="font" metaFont="systemSemibold" size="17"/>
+                            </buttonCell>
+                            <color key="bezelColor" name="VLCAccentColor"/>
+                            <color key="contentTintColor" name="VLCAccentColor"/>
+                            <connections>
+                                <action selector="playRepresentedItem:" target="LPV-K6-7AE" id="fGM-xi-Y8E"/>
+                            </connections>
+                        </button>
+                    </subviews>
+                    <constraints>
+                        <constraint firstAttribute="trailing" secondItem="5zZ-VM-Lb9" secondAttribute="trailing" id="2eF-oY-rR1"/>
+                        <constraint firstItem="5zZ-VM-Lb9" firstAttribute="leading" secondItem="U3j-Zx-fFf" secondAttribute="leading" id="8fY-R2-NIT"/>
+                        <constraint firstAttribute="bottom" secondItem="5zZ-VM-Lb9" secondAttribute="bottom" id="yDI-oU-4c7"/>
+                    </constraints>
+                    <visibilityPriorities>
+                        <integer value="1000"/>
+                        <integer value="1000"/>
+                        <integer value="1000"/>
+                    </visibilityPriorities>
+                    <customSpacing>
+                        <real value="3.4028234663852886e+38"/>
+                        <real value="3.4028234663852886e+38"/>
+                        <real value="3.4028234663852886e+38"/>
+                    </customSpacing>
+                </stackView>
+            </subviews>
+            <constraints>
+                <constraint firstAttribute="width" secondItem="LPV-K6-7AE" secondAttribute="height" multiplier="21:9" id="2HS-zo-d22"/>
+                <constraint firstItem="qdP-As-qZ0" firstAttribute="top" secondItem="LPV-K6-7AE" secondAttribute="top" id="9aA-Ma-Vvy"/>
+                <constraint firstItem="U3j-Zx-fFf" firstAttribute="leading" secondItem="LPV-K6-7AE" secondAttribute="leading" constant="20" symbolic="YES" id="A9P-6v-TYB"/>
+                <constraint firstItem="U3j-Zx-fFf" firstAttribute="width" secondItem="LPV-K6-7AE" secondAttribute="width" multiplier="0.3" id="CkN-iH-QJd"/>
+                <constraint firstAttribute="bottom" secondItem="U3j-Zx-fFf" secondAttribute="bottom" constant="20" id="GKS-hS-EhI"/>
+                <constraint firstItem="GoN-QI-mru" firstAttribute="leading" secondItem="LPV-K6-7AE" secondAttribute="leading" constant="20" id="UTF-IS-5xp"/>
+                <constraint firstItem="U3j-Zx-fFf" firstAttribute="top" relation="greaterThanOrEqual" secondItem="GoN-QI-mru" secondAttribute="bottom" constant="20" id="ZCB-XT-8xc"/>
+                <constraint firstAttribute="bottom" secondItem="qdP-As-qZ0" secondAttribute="bottom" id="lyx-Ea-nZ1"/>
+                <constraint firstItem="qdP-As-qZ0" firstAttribute="leading" secondItem="LPV-K6-7AE" secondAttribute="leading" id="p3I-zN-Dxs"/>
+                <constraint firstItem="GoN-QI-mru" firstAttribute="top" secondItem="LPV-K6-7AE" secondAttribute="top" constant="20" id="xOv-2n-nx5"/>
+                <constraint firstAttribute="trailing" secondItem="qdP-As-qZ0" secondAttribute="trailing" id="yrR-6i-uoU"/>
+            </constraints>
+            <connections>
+                <outlet property="detailTextField" destination="aVp-p4-DHX" id="OZu-HX-Re8"/>
+                <outlet property="explanationTextField" destination="GoN-QI-mru" id="ynd-Jb-Vmn"/>
+                <outlet property="largeImageView" destination="qdP-As-qZ0" id="sD5-PT-ggF"/>
+                <outlet property="playButton" destination="5zZ-VM-Lb9" id="quv-CP-87R"/>
+                <outlet property="titleTextField" destination="kFW-i6-3hg" id="TXW-Kf-ZRh"/>
+            </connections>
+            <point key="canvasLocation" x="260" y="95"/>
+        </customView>
+    </objects>
+    <resources>
+        <image name="play.circle.fill" catalog="system" width="15" height="15"/>
+        <namedColor name="VLCAccentColor">
+            <color red="1" green="0.37999999523162842" blue="0.039999999105930328" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
+        </namedColor>
+    </resources>
+</document>


=====================================
modules/gui/macosx/library/VLCLibraryHeroView.h
=====================================
@@ -0,0 +1,47 @@
+/*****************************************************************************
+ * VLCLibraryHeroView.h: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2023 VLC authors and VideoLAN
+ *
+ * Authors: Claudio Cambra <developer at claudiocambra.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#import <Cocoa/Cocoa.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+ at class VLCImageView;
+ at protocol VLCMediaLibraryItemProtocol;
+
+ at interface VLCLibraryHeroView : NSView
+
+ at property (readwrite) IBOutlet VLCImageView *largeImageView;
+ at property (readwrite) IBOutlet NSTextField *explanationTextField;
+ at property (readwrite) IBOutlet NSTextField *titleTextField;
+ at property (readwrite) IBOutlet NSTextField *detailTextField;
+ at property (readwrite) IBOutlet NSButton *playButton;
+
+ at property (readwrite, nonatomic) id<VLCMediaLibraryItemProtocol> representedItem;
+
++ (instancetype)fromNibWithOwner:(id)owner;
+
+- (IBAction)playRepresentedItem:(id)sender;
+- (void)setOptimalRepresentedItem;
+
+ at end
+
+NS_ASSUME_NONNULL_END


=====================================
modules/gui/macosx/library/VLCLibraryHeroView.m
=====================================
@@ -0,0 +1,128 @@
+/*****************************************************************************
+ * VLCLibraryHeroView.m: MacOS X interface module
+ *****************************************************************************
+ * Copyright (C) 2023 VLC authors and VideoLAN
+ *
+ * Authors: Claudio Cambra <developer at claudiocambra.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ *****************************************************************************/
+
+#import "VLCLibraryHeroView.h"
+
+#import "extensions/NSString+Helpers.h"
+#import "extensions/NSView+VLCAdditions.h"
+
+#import "library/VLCLibraryController.h"
+#import "library/VLCLibraryDataTypes.h"
+#import "library/VLCLibraryImageCache.h"
+#import "library/VLCLibraryModel.h"
+
+#import "main/VLCMain.h"
+
+#import "views/VLCImageView.h"
+
+ at interface VLCLibraryHeroView ()
+
+ at property (readonly) VLCMediaLibraryMediaItem *randomItem;
+ at property (readonly) VLCMediaLibraryMediaItem *latestPartiallyPlayedItem;
+
+ at end
+
+ at implementation VLCLibraryHeroView
+
++ (instancetype)fromNibWithOwner:(id)owner
+{
+    return (VLCLibraryHeroView*)[NSView fromNibNamed:@"VLCLibraryHeroView"
+                                                     withClass:VLCLibraryHeroView.class
+                                                     withOwner:owner];
+}
+
+- (void)awakeFromNib
+{
+    self.largeImageView.contentGravity = VLCImageViewContentGravityResizeAspectFill;
+}
+
+- (void)updateRepresentedItem
+{
+    NSAssert(self.representedItem != nil, @"Should not update nil represented item!");
+    self.largeImageView.image = [VLCLibraryImageCache thumbnailForLibraryItem:self.representedItem];
+    self.titleTextField.stringValue = self.representedItem.displayString;
+    self.detailTextField.stringValue = self.representedItem.detailString;
+}
+
+- (void)setRepresentedItem:(id<VLCMediaLibraryItemProtocol>)representedItem
+{
+    NSParameterAssert(representedItem != nil);
+    if (representedItem == self.representedItem) {
+        return;
+    }
+
+    _representedItem = representedItem;
+    [self updateRepresentedItem];
+}
+
+- (VLCMediaLibraryMediaItem *)randomItem
+{
+    VLCLibraryModel * const libraryModel = VLCMain.sharedInstance.libraryController.libraryModel;
+    const size_t videoCount = libraryModel.numberOfVideoMedia;
+    const uint32_t randIdx = arc4random_uniform((uint32_t)(videoCount - 1));
+    return [libraryModel.listOfVideoMedia objectAtIndex:randIdx];
+}
+
+- (VLCMediaLibraryMediaItem *)latestPartiallyPlayedItem
+{
+    VLCLibraryModel * const libraryModel = VLCMain.sharedInstance.libraryController.libraryModel;
+    NSArray<VLCMediaLibraryMediaItem *> * const recentMedia = libraryModel.listOfRecentMedia;
+    const NSUInteger firstPartialPlayItemIdx = [recentMedia indexOfObjectPassingTest:^BOOL(VLCMediaLibraryMediaItem *testedItem, NSUInteger idx, BOOL *stop) {
+        const float playProgress = testedItem.progress;
+        return playProgress > 0 && playProgress < 100;
+    }];
+
+    if (firstPartialPlayItemIdx == NSNotFound) {
+        return nil;
+    }
+
+    return [recentMedia objectAtIndex:firstPartialPlayItemIdx];
+}
+
+- (void)setOptimalRepresentedItem
+{
+    VLCMediaLibraryMediaItem * const latestPartialPlayItem = self.latestPartiallyPlayedItem;
+    if (latestPartialPlayItem != nil) {
+        self.representedItem = latestPartialPlayItem;
+        self.explanationTextField.stringValue = _NS("Last watched");
+        self.playButton.title = _NS("Resume playing");
+        return;
+    }
+
+    VLCMediaLibraryMediaItem * const randomItem = self.randomItem;
+    if (randomItem != nil) {
+        self.representedItem = randomItem;
+        self.explanationTextField.stringValue = _NS("From your library");
+        self.playButton.title = _NS("Play now");
+        return;
+    }
+
+    NSLog(@"Could not find a food media item for hero view!");
+}
+
+- (IBAction)playRepresentedItem:(id)sender
+{
+    VLCLibraryController * const libraryController = VLCMain.sharedInstance.libraryController;
+    [libraryController appendItemToPlaylist:self.representedItem playImmediately:YES];
+}
+
+ at end


=====================================
modules/gui/macosx/library/VLCLibraryImageCache.h
=====================================
@@ -26,15 +26,15 @@ NS_ASSUME_NONNULL_BEGIN
 
 @class VLCInputItem;
 @class VLCPlaylistItem;
- at class VLCAbstractMediaLibraryItem;
+ at protocol VLCMediaLibraryItemProtocol;
 
 @interface VLCLibraryImageCache : NSObject
 
-+ (nullable NSImage *)thumbnailForLibraryItem:(VLCAbstractMediaLibraryItem*)libraryItem;
++ (nullable NSImage *)thumbnailForLibraryItem:(id<VLCMediaLibraryItemProtocol>)libraryItem;
 + (nullable NSImage *)thumbnailForInputItem:(VLCInputItem*)inputItem;
 + (nullable NSImage *)thumbnailForPlaylistItem:(VLCPlaylistItem*)playlistItem;
 
-+ (void)thumbnailForLibraryItem:(VLCAbstractMediaLibraryItem *)libraryItem
++ (void)thumbnailForLibraryItem:(id<VLCMediaLibraryItemProtocol>)libraryItem
                  withCompletion:(void(^)(const NSImage *))completionHandler;
 + (void)thumbnailForInputItem:(VLCInputItem *)inputItem
                withCompletion:(void(^)(const NSImage *))completionHandler;


=====================================
modules/gui/macosx/library/VLCLibraryImageCache.m
=====================================
@@ -64,12 +64,12 @@ float kVLCDefaultThumbnailPosition = .15;
     return sharedImageCache;
 }
 
-+ (NSImage *)thumbnailForLibraryItem:(VLCAbstractMediaLibraryItem*)libraryItem
++ (NSImage *)thumbnailForLibraryItem:(id<VLCMediaLibraryItemProtocol>)libraryItem
 {
     return [[VLCLibraryImageCache sharedImageCache] imageForLibraryItem:libraryItem];
 }
 
-- (NSImage *)imageForLibraryItem:(VLCAbstractMediaLibraryItem*)libraryItem
+- (NSImage *)imageForLibraryItem:(id<VLCMediaLibraryItemProtocol>)libraryItem
 {
     NSImage *cachedImage = [_imageCache objectForKey:libraryItem.smallArtworkMRL];
     if (cachedImage) {
@@ -78,7 +78,7 @@ float kVLCDefaultThumbnailPosition = .15;
     return [self smallThumbnailForLibraryItem:libraryItem];
 }
 
-- (NSImage *)smallThumbnailForLibraryItem:(VLCAbstractMediaLibraryItem*)libraryItem
+- (NSImage *)smallThumbnailForLibraryItem:(id<VLCMediaLibraryItemProtocol>)libraryItem
 {
     NSImage *image;
     NSString * const artworkMRL = libraryItem.smallArtworkMRL;
@@ -157,7 +157,7 @@ float kVLCDefaultThumbnailPosition = .15;
     return [VLCLibraryImageCache.sharedImageCache imageForInputItem:playlistItem.inputItem];
 }
 
-+ (void)thumbnailForLibraryItem:(VLCAbstractMediaLibraryItem *)libraryItem
++ (void)thumbnailForLibraryItem:(id<VLCMediaLibraryItemProtocol>)libraryItem
                withCompletion:(void(^)(const NSImage *))completionHandler
 {
     dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{


=====================================
modules/gui/macosx/library/video-library/VLCLibraryVideoCollectionViewsStackViewController.h
=====================================
@@ -24,6 +24,8 @@
 
 NS_ASSUME_NONNULL_BEGIN
 
+ at class VLCLibraryHeroView;
+
 @interface VLCLibraryVideoCollectionViewsStackViewController : NSObject
 
 @property (readwrite, assign, nonatomic) NSSize collectionViewItemSize;
@@ -34,6 +36,8 @@ NS_ASSUME_NONNULL_BEGIN
 @property (readwrite, assign, nonatomic) NSStackView *collectionsStackView;
 @property (readwrite, assign, nonatomic) NSScrollView *collectionsStackViewScrollView;
 
+ at property (readonly) VLCLibraryHeroView *heroView;
+
 - (void)reloadData;
 
 @end


=====================================
modules/gui/macosx/library/video-library/VLCLibraryVideoCollectionViewsStackViewController.m
=====================================
@@ -26,6 +26,7 @@
 #import "library/VLCLibraryCollectionViewFlowLayout.h"
 #import "library/VLCLibraryCollectionViewSupplementaryElementView.h"
 #import "library/VLCLibraryController.h"
+#import "library/VLCLibraryHeroView.h"
 #import "library/VLCLibraryModel.h"
 #import "library/VLCLibraryUIUnits.h"
 
@@ -40,6 +41,7 @@
 @interface VLCLibraryVideoCollectionViewsStackViewController()
 {
     NSArray *_collectionViewContainers;
+    NSUInteger _leadingContainerCount;
 }
 @end
 
@@ -66,9 +68,19 @@
                                 name:VLCLibraryModelRecentsMediaItemDeleted
                                 object:nil];
 
+    _leadingContainerCount = 0;
+    [self generateCustomContainers];
     [self generateCollectionViewContainers];
 }
 
+- (void)generateCustomContainers
+{
+    _heroView = [VLCLibraryHeroView fromNibWithOwner:self];
+    _leadingContainerCount += 1;
+    [self addView:self.heroView toStackView:self.collectionsStackView];
+    [self.heroView setOptimalRepresentedItem];
+}
+
 - (BOOL)recentMediaPresent
 {
     VLCLibraryModel * const model = VLCMain.sharedInstance.libraryController.libraryModel;
@@ -94,7 +106,8 @@
         containerView.videoGroup = VLCLibraryVideoRecentsGroup;
         [mutableContainers insertObject:containerView atIndex:0];
 
-        [_collectionsStackView insertArrangedSubview:containerView atIndex:0];
+        // Insert at top after leading containers, hence _leadingContainerCount
+        [_collectionsStackView insertArrangedSubview:containerView atIndex:_leadingContainerCount];
         [self setupContainerView:containerView forStackView:_collectionsStackView];
     } else {
         [mutableContainers removeObjectAtIndex:recentsContainerIndex];
@@ -125,21 +138,23 @@
 {
     dispatch_async(dispatch_get_main_queue(), ^{
         for (VLCLibraryVideoCollectionViewContainerView *containerView in self->_collectionViewContainers) {
+            [self.heroView setOptimalRepresentedItem];
             [containerView.collectionView reloadData];
         }
     });
 }
 
-- (void)setupContainerView:(VLCLibraryVideoCollectionViewContainerView *)containerView
-              forStackView:(NSStackView *)stackView
+- (NSArray<NSLayoutConstraint*> *)setupViewConstraints:(NSView *)view
+                                          forStackView:(NSStackView *)stackView
 {
-    if (containerView == nil || stackView == nil) {
-        return;
+    if (view == nil || stackView == nil) {
+        return @[];
     }
 
-    containerView.translatesAutoresizingMaskIntoConstraints = NO;
+    view.translatesAutoresizingMaskIntoConstraints = NO;
+
     NSArray<NSLayoutConstraint*> * const constraintsWithSuperview = @[
-        [NSLayoutConstraint constraintWithItem:containerView
+        [NSLayoutConstraint constraintWithItem:view
                                      attribute:NSLayoutAttributeLeft
                                      relatedBy:NSLayoutRelationEqual
                                         toItem:stackView
@@ -147,7 +162,7 @@
                                     multiplier:1
                                       constant:0
         ],
-        [NSLayoutConstraint constraintWithItem:containerView
+        [NSLayoutConstraint constraintWithItem:view
                                      attribute:NSLayoutAttributeRight
                                      relatedBy:NSLayoutRelationEqual
                                         toItem:stackView
@@ -156,8 +171,31 @@
                                       constant:0
         ],
     ];
-    containerView.constraintsWithSuperview = constraintsWithSuperview;
     [stackView addConstraints:constraintsWithSuperview];
+
+    return constraintsWithSuperview;
+}
+
+- (void)setupContainerView:(VLCLibraryVideoCollectionViewContainerView *)containerView
+              forStackView:(NSStackView *)stackView
+{
+    if (containerView == nil || stackView == nil) {
+        return;
+    }
+
+    NSArray<NSLayoutConstraint*> * const constraintsWithSuperview = [self setupViewConstraints:containerView forStackView:stackView];
+    containerView.constraintsWithSuperview = constraintsWithSuperview;
+}
+
+- (void)addView:(NSView *)view
+    toStackView:(NSStackView *)stackView
+{
+    if (view == nil || stackView == nil) {
+        return;
+    }
+
+    [stackView addArrangedSubview:view];
+    [self setupViewConstraints:view forStackView:stackView];
 }
 
 - (void)addContainerView:(VLCLibraryVideoCollectionViewContainerView *)containerView
@@ -192,6 +230,9 @@
                                forOrientation:NSLayoutConstraintOrientationVertical];
 
 
+    [self addView:self.heroView toStackView:_collectionsStackView];
+    [self.heroView setOptimalRepresentedItem];
+
     for (VLCLibraryVideoCollectionViewContainerView * const containerView in _collectionViewContainers) {
         [self addContainerView:containerView toStackView:_collectionsStackView];
     }
@@ -235,7 +276,7 @@
     }
 }
 
-- (void) setCollectionViewMinimumInteritemSpacing:(CGFloat)collectionViewMinimumInteritemSpacing
+- (void)setCollectionViewMinimumInteritemSpacing:(CGFloat)collectionViewMinimumInteritemSpacing
 {
     _collectionViewMinimumInteritemSpacing = collectionViewMinimumInteritemSpacing;
 



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b8e72e4ce4467ea1cd253f9fcfee8f0500f37451...9196b9f8bb7a856e914c6e3ab2dabd9b0debd34b

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/b8e72e4ce4467ea1cd253f9fcfee8f0500f37451...9196b9f8bb7a856e914c6e3ab2dabd9b0debd34b
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list