@@ -78,8 +78,7 @@ class WelcomePanel final : public Component
7878 return ;
7979
8080 if (clearButtonBounds.contains (e.getPosition ())) {
81- auto const settingsTree = SettingsFile::getInstance ()->getValueTree ();
82- settingsTree.getChildWithName (" RecentlyOpened" ).removeAllChildren (nullptr );
81+ SettingsFile::getInstance ()->getListProperty (" recently_opened" ).clear ();
8382 panel.triggerAsyncUpdate ();
8483 }
8584 }
@@ -266,12 +265,12 @@ class WelcomePanel final : public Component
266265 resized ();
267266 }
268267
269- WelcomePanelTile (WelcomePanel& welcomePanel, ValueTree subTree , String const & svgImage, bool const favourited, File const & thumbnail)
268+ WelcomePanelTile (WelcomePanel& welcomePanel, File const & patchFile, int64 lastOpenTime , String const & svgImage, bool const favourited, File const & thumbnail)
270269 : isFavourited(favourited)
271270 , parent(welcomePanel)
272271 , thumbnailFile(thumbnail)
272+ , patchFile(patchFile)
273273 {
274- patchFile = File (subTree.getProperty (" Path" ).toString ());
275274 tileName = patchFile.getFileNameWithoutExtension ();
276275
277276 auto is24Hour = OSUtils::is24HourTimeFormat ();
@@ -299,8 +298,7 @@ class WelcomePanel final : public Component
299298 return (dateOrDay.isNotEmpty () ? dateOrDay : openTime.toString (true , false )) + " , " + time;
300299 };
301300
302- auto const accessedInPlugdata = Time (subTree.getProperty (" Time" ));
303-
301+ auto const accessedInPlugdata = Time (lastOpenTime);
304302 tileSubtitle = formatTimeDescription (accessedInPlugdata);
305303
306304 auto const fileSize = patchFile.getSize ();
@@ -801,8 +799,7 @@ class WelcomePanel final : public Component
801799
802800 recentlyOpenedTiles.clear ();
803801
804- auto const settingsTree = SettingsFile::getInstance ()->getValueTree ();
805- auto recentlyOpenedTree = settingsTree.getChildWithName (" RecentlyOpened" );
802+ auto recentlyOpenedTree = SettingsFile::getInstance ()->getListProperty (" recently_opened" );
806803
807804 if (currentTab == Home) {
808805 contentComponent.addAndMakeVisible (*newPatchTile);
@@ -811,88 +808,90 @@ class WelcomePanel final : public Component
811808 contentComponent.addAndMakeVisible (*storeTile);
812809 }
813810
814- if (recentlyOpenedTree.isValid ()) {
815- for (int i = recentlyOpenedTree.getNumChildren () - 1 ; i >= 0 ; i--) {
816- auto subTree = recentlyOpenedTree.getChild (i);
817- auto patchFile = File (subTree.getProperty (" Path" ).toString ());
818- if (!File (patchFile).existsAsFile () && !subTree.hasProperty (" Removable" )) {
819- recentlyOpenedTree.removeChild (i, nullptr );
820- }
811+ for (int i = recentlyOpenedTree.size () - 1 ; i >= 0 ; i--) {
812+ auto & subTree = recentlyOpenedTree.getReference (i);
813+ auto patchFile = File (subTree.getProperty (" path" , " " ).toString ());
814+ if (!File (patchFile).existsAsFile () && !subTree.hasProperty (" removable" )) {
815+ recentlyOpenedTree.remove (i);
821816 }
817+ }
822818
823- // Place favourited patches at the top
824- for (int i = 0 ; i < recentlyOpenedTree.getNumChildren (); i++) {
825- auto subTree = recentlyOpenedTree.getChild (i);
826- auto patchFile = File (subTree.getProperty (" Path " ).toString ());
819+ // Place favourited patches at the top
820+ for (int i = 0 ; i < recentlyOpenedTree.size (); i++) {
821+ auto & subTree = recentlyOpenedTree.getReference (i);
822+ auto patchFile = File (subTree.getProperty (" path " , " " ).toString ());
827823
828- auto patchThumbnailBase = File (patchFile.getSiblingFile (patchFile.getFileNameWithoutExtension ()).getFullPathName () + " _thumb" );
829- auto const favourited = subTree. hasProperty ( " Pinned " ) && static_cast <bool >(subTree.getProperty (" Pinned " ));
824+ auto patchThumbnailBase = File (patchFile.getSiblingFile (patchFile.getFileNameWithoutExtension ()).getFullPathName () + " _thumb" );
825+ auto const favourited = static_cast <bool >(subTree.getProperty (" pinned " , false ));
830826
831- auto thumbnailImage = File ();
832- for (auto const & ext : StringArray { " .png" , " .jpg" , " .jpeg" , " .gif" }) {
833- auto patchThumbnail = patchThumbnailBase.withFileExtension (ext);
834- if (patchThumbnail.existsAsFile ()) {
835- thumbnailImage = patchThumbnail;
836- }
827+ auto thumbnailImage = File ();
828+ for (auto const & ext : StringArray { " .png" , " .jpg" , " .jpeg" , " .gif" }) {
829+ auto patchThumbnail = patchThumbnailBase.withFileExtension (ext);
830+ if (patchThumbnail.existsAsFile ()) {
831+ thumbnailImage = patchThumbnail;
837832 }
833+ }
838834
839- String silhoutteSvg;
840- if (patchFile.existsAsFile () && thumbnailImage == File ()) {
841- auto cachedSilhouette = patchSvgCache.find (patchFile.getFullPathName ());
842- if (cachedSilhouette != patchSvgCache.end ()) {
843- silhoutteSvg = cachedSilhouette->second ;
844- } else {
835+ String silhoutteSvg;
836+ if (patchFile.existsAsFile () && thumbnailImage == File ()) {
837+ auto cachedSilhouette = patchSvgCache.find (patchFile.getFullPathName ());
838+ if (cachedSilhouette != patchSvgCache.end ()) {
839+ silhoutteSvg = cachedSilhouette->second ;
840+ } else {
845841#if JUCE_IOS
846- // Recover file permission bookmark from valuetree if possible
847- auto url = URL (patchFile);
848- auto bookmarkData = subTree.getProperty (" Bookmark" ).toString ();
849- std::unique_ptr<InputStream> scopedStream;
850- if (bookmarkData.isNotEmpty ()) {
851- url.setBookmarkData (bookmarkData);
852- scopedStream = url.createInputStream (URL::InputStreamOptions (URL::ParameterHandling::inAddress));
853- }
854- #endif
855- silhoutteSvg = OfflineObjectRenderer::patchToSVG (patchFile.loadFileAsString ());
856- patchSvgCache[patchFile.getFullPathName ()] = silhoutteSvg;
842+ // Recover file permission bookmark from valuetree if possible
843+ auto url = URL (patchFile);
844+ auto bookmarkData = subTree.getProperty (" bookmark" ).toString ();
845+ std::unique_ptr<InputStream> scopedStream;
846+ if (bookmarkData.isNotEmpty ()) {
847+ url.setBookmarkData (bookmarkData);
848+ scopedStream = url.createInputStream (URL::InputStreamOptions (URL::ParameterHandling::inAddress));
857849 }
850+ #endif
851+ silhoutteSvg = OfflineObjectRenderer::patchToSVG (patchFile.loadFileAsString ());
852+ patchSvgCache[patchFile.getFullPathName ()] = silhoutteSvg;
858853 }
854+ }
855+ auto patch = File (subTree.getProperty (" path" , " " ));
856+ auto time = static_cast <int64>(subTree.getProperty (" path" , " " ));
857+ auto * tile = recentlyOpenedTiles.add (new WelcomePanelTile (*this , patch, time, silhoutteSvg, favourited, thumbnailImage));
859858
860- auto * tile = recentlyOpenedTiles.add (new WelcomePanelTile (*this , subTree, silhoutteSvg, favourited, thumbnailImage));
861-
862- tile->onClick = [this , patchFile, subTree]() mutable {
863- auto patchURL = URL (patchFile);
859+ tile->onClick = [this , patchFile, subTree]() mutable {
860+ auto patchURL = URL (patchFile);
864861#if JUCE_IOS
865- // Load bookmark to keep file access permissions from last open
866- patchURL.setBookmarkData (subTree.getProperty (" Bookmark " ).toString ());
862+ // Load bookmark to keep file access permissions from last open
863+ patchURL.setBookmarkData (subTree.getProperty (" bookmark " ).toString ());
867864#endif
868- if (patchFile.existsAsFile ()) {
869- editor->getTabComponent ().openPatch (patchURL);
870- } else {
871- editor->pd ->logError (" Patch not found" );
865+ if (patchFile.existsAsFile ()) {
866+ editor->getTabComponent ().openPatch (patchURL);
867+ } else {
868+ editor->pd ->logError (" Patch not found" );
869+ }
870+ };
871+ tile->onFavourite = [this , path = subTree.getProperty (" path" , " " )](bool const shouldBeFavourite) mutable {
872+ auto recentlyOpenedTree = SettingsFile::getInstance ()->getListProperty (" recently_opened" );
873+ for (auto & recentPatch : recentlyOpenedTree) {
874+ if (recentPatch.getProperty (" path" , " " ) == path) {
875+ recentPatch.getDynamicObject ()->setProperty (" pinned" , shouldBeFavourite);
876+ break ;
872877 }
873- };
874- tile->onFavourite = [this , path = subTree.getProperty (" Path" )](bool const shouldBeFavourite) mutable {
875- auto const settingsTree = SettingsFile::getInstance ()->getValueTree ();
876- auto const recentlyOpenedTree = settingsTree.getChildWithName (" RecentlyOpened" );
877-
878- // Settings file could be reloaded, we can't assume the old recently opened tree is still valid!
879- // So look up the entry by file path
880- auto subTree = recentlyOpenedTree.getChildWithProperty (" Path" , path);
881- subTree.setProperty (" Pinned" , shouldBeFavourite, nullptr );
882- resized ();
883- };
884- tile->onRemove = [this , path = subTree.getProperty (" Path" )] {
885- auto const settingsTree = SettingsFile::getInstance ()->getValueTree ();
886- auto recentlyOpenedTree = settingsTree.getChildWithName (" RecentlyOpened" );
887- auto const subTree = recentlyOpenedTree.getChildWithProperty (" Path" , path);
888- recentlyOpenedTree.removeChild (subTree, nullptr );
889- // Make sure to clear the recent items in the current welcome panel
890- if (editor->welcomePanel )
891- editor->welcomePanel ->triggerAsyncUpdate ();
892- };
893-
894- contentComponent.addAndMakeVisible (tile);
895- }
878+ }
879+ resized ();
880+ };
881+ tile->onRemove = [this , path = subTree.getProperty (" path" , " " )] {
882+ auto recentlyOpenedTree = SettingsFile::getInstance ()->getListProperty (" recently_opened" );
883+ for (auto & recentPatch : recentlyOpenedTree) {
884+ if (recentPatch.getProperty (" path" , " " ) == path) {
885+ recentlyOpenedTree.remove (&recentPatch);
886+ break ;
887+ }
888+ }
889+
890+ if (editor->welcomePanel )
891+ editor->welcomePanel ->triggerAsyncUpdate ();
892+ };
893+
894+ contentComponent.addAndMakeVisible (tile);
896895 }
897896
898897 contentComponent.repaint ();
0 commit comments