[vlc-commits] [Git][videolan/vlc][master] 3 commits: macosx: Remove bookmarked locations that no longer exist on load

Felix Paul Kühne (@fkuehne) gitlab at videolan.org
Sat Feb 8 11:04:50 UTC 2025


Felix Paul Kühne pushed to branch master at VideoLAN / VLC


Commits:
65cacb6e by Claudio Cambra at 2025-02-08T10:45:48+00:00
macosx: Remove bookmarked locations that no longer exist on load

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

- - - - -
3a034869 by Claudio Cambra at 2025-02-08T10:45:48+00:00
macosx: Observe changes to bookmarked locations and delete bookmark if location is deleted immediately

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

- - - - -
5923be34 by Claudio Cambra at 2025-02-08T10:45:48+00:00
macosx: Detect bookmark location rename and adjust the bookmark location rather than delete it

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

- - - - -


2 changed files:

- modules/gui/macosx/library/VLCLibrarySegment.m
- modules/gui/macosx/library/VLCLibraryWindowNavigationSidebarViewController.m


Changes:

=====================================
modules/gui/macosx/library/VLCLibrarySegment.m
=====================================
@@ -732,8 +732,13 @@ NSArray<NSString *> *defaultBookmarkedLocations()
 
         const VLCLibrarySegmentType segmentType = VLCLibraryBrowseBookmarkedLocationSubSegmentType;
         NSMutableArray<NSTreeNode *> * const bookmarkedLocationNodes = NSMutableArray.array;
+        NSMutableArray<NSString *> * const remainingBookmarkedLocations = bookmarkedLocations.mutableCopy;
 
         for (NSString * const locationMrl in bookmarkedLocations) {
+            if (![NSFileManager.defaultManager fileExistsAtPath:[NSURL URLWithString:locationMrl].path]) {
+                [remainingBookmarkedLocations removeObject:locationMrl];
+                continue;
+            }
             NSString * const locationName = locationMrl.lastPathComponent;
             VLCLibrarySegmentBookmarkedLocation * const descriptor =
                 [[VLCLibrarySegmentBookmarkedLocation alloc] initWithSegmentType:segmentType
@@ -745,6 +750,10 @@ NSArray<NSString *> *defaultBookmarkedLocations()
         }
 
         self.internalChildNodes = bookmarkedLocationNodes.copy;
+
+        if (bookmarkedLocations.count != remainingBookmarkedLocations.count) {
+            [defaults setObject:remainingBookmarkedLocations forKey:VLCLibraryBookmarkedLocationsKey];
+        }
     }
     return self;
 }


=====================================
modules/gui/macosx/library/VLCLibraryWindowNavigationSidebarViewController.m
=====================================
@@ -34,6 +34,11 @@
 
 #import "views/VLCStatusNotifierView.h"
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
 // This needs to match whatever identifier has been set in the library window XIB
 static NSString * const VLCLibrarySegmentCellIdentifier = @"VLCLibrarySegmentCellIdentifier";
 
@@ -41,6 +46,7 @@ static NSString * const VLCLibrarySegmentCellIdentifier = @"VLCLibrarySegmentCel
 
 @property BOOL ignoreSegmentSelectionChanges;
 @property (readonly) NSEdgeInsets scrollViewInsets;
+ at property (readonly) NSMutableDictionary<NSString *, dispatch_source_t> *observedPathDispatchSources;
 
 @end
 
@@ -53,6 +59,7 @@ static NSString * const VLCLibrarySegmentCellIdentifier = @"VLCLibrarySegmentCel
         _libraryWindow = libraryWindow;
         _segments = VLCLibrarySegment.librarySegments;
         _ignoreSegmentSelectionChanges = NO;
+        _observedPathDispatchSources = NSMutableDictionary.dictionary;
     }
     return self;
 }
@@ -134,6 +141,76 @@ static NSString * const VLCLibrarySegmentCellIdentifier = @"VLCLibrarySegmentCel
                   byExtendingSelection:NO];
 
     self.ignoreSegmentSelectionChanges = NO;
+
+    [self updateBookmarkObservation];
+}
+
+- (void)updateBookmarkObservation
+{
+    NSUserDefaults * const defaults = NSUserDefaults.standardUserDefaults;
+    NSArray<NSString *> * const bookmarkedLocations =
+        [defaults stringArrayForKey:VLCLibraryBookmarkedLocationsKey];
+    if (bookmarkedLocations.count == 0) {
+        return;
+    }
+
+    NSMutableArray<NSString *> * const deletedLocations = self.observedPathDispatchSources.allKeys.mutableCopy;
+    const __weak typeof(self) weakSelf = self;
+
+    for (NSString * const locationMrl in bookmarkedLocations) {
+        [deletedLocations removeObject:locationMrl];
+        if ([self.observedPathDispatchSources objectForKey:locationMrl] != nil) {
+            continue;
+        }
+        NSURL * const locationUrl = [NSURL URLWithString:locationMrl];
+        const uintptr_t descriptor = open(locationUrl.path.UTF8String, O_EVTONLY);
+        if (descriptor == -1) {
+            continue;
+        }
+        struct stat fileStat;
+        const int statResult = fstat(descriptor, &fileStat);
+
+        const dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
+        const dispatch_source_t fileDispatchSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, descriptor, DISPATCH_VNODE_DELETE | DISPATCH_VNODE_RENAME, globalQueue);
+        dispatch_source_set_event_handler(fileDispatchSource, ^{
+            const unsigned long eventFlags = dispatch_source_get_data(fileDispatchSource);
+            if (eventFlags & DISPATCH_VNODE_RENAME && statResult != -1) {
+                NSURL * const parentLocationUrl = locationUrl.URLByDeletingLastPathComponent;
+                NSString * const parentLocationPath = parentLocationUrl.path;
+                NSArray<NSString *> * const files = [NSFileManager.defaultManager contentsOfDirectoryAtPath:parentLocationPath error:nil];
+                NSString *newFileName = nil;
+
+                for (NSString * const file in files) {
+                    NSString * const fullChildPath = [parentLocationPath stringByAppendingPathComponent:file];
+                    struct stat currentFileStat;
+                    if (stat(fullChildPath.UTF8String, &currentFileStat) == -1) {
+                        continue;
+                    } else if (currentFileStat.st_ino == fileStat.st_ino) {
+                        newFileName = fullChildPath.lastPathComponent;
+                        break;
+                    }
+                }
+
+                if (newFileName != nil) {
+                    NSMutableArray<NSString *> * const mutableBookmarkedLocations = bookmarkedLocations.mutableCopy;
+                    const NSUInteger locationIndex = [mutableBookmarkedLocations indexOfObject:locationMrl];
+                    NSString * const newLocationMrl = [parentLocationUrl URLByAppendingPathComponent:newFileName].absoluteString;
+                    [mutableBookmarkedLocations replaceObjectAtIndex:locationIndex withObject:newLocationMrl];
+                    [defaults setObject:mutableBookmarkedLocations forKey:VLCLibraryBookmarkedLocationsKey];
+                }
+            }
+            dispatch_async(dispatch_get_main_queue(), ^{
+                [weakSelf internalNodesChanged:nil];
+            });
+        });
+        dispatch_source_set_cancel_handler(fileDispatchSource, ^{
+            close(descriptor);
+        });
+        dispatch_resume(fileDispatchSource);
+        [self.observedPathDispatchSources setObject:fileDispatchSource forKey:locationMrl];
+    }
+
+    [self.observedPathDispatchSources removeObjectsForKeys:deletedLocations];
 }
 
 - (void)statusViewActivated:(NSNotification *)notification



View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/4d225c66e678656bd0b50f1461a452d4bfc5fe65...5923be34f415c13b045066cf0135dd0f5e0beb21

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/compare/4d225c66e678656bd0b50f1461a452d4bfc5fe65...5923be34f415c13b045066cf0135dd0f5e0beb21
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