Construct and manage a graphical, event-driven user interface for your macOS app using AppKit.

Posts under AppKit tag

173 Posts
Sort by:

Post

Replies

Boosts

Views

Activity

NSMenuToolbarItem not showing first menu item when using NSMenuDelegate
I am using NSMenuToolbarItem to show a drop-down menu in my NSToolbar. This works as expected when creating an NSMenu beforehand and assign it to the menu property of NSMenuToolbarItem. However, my menu needs to be built dynamically when the user clicks the dropdown button. To do that, I am using NSMenuDelegate. When creating the menu in the menuNeedsUpdate of the delegate, the first menu item isn't shown to the user. Why? Menu when using delegate: Menu when pre-assigning menu: I also cannot just add a placeholder menu item at the start of the NSMenuToolbarItem as all menu items do show in the overflow menu. Example code: import Cocoa class AppDelegate: NSObject, NSApplicationDelegate, NSToolbarDelegate, NSMenuDelegate { var window: NSWindow! func applicationDidFinishLaunching(_ aNotification: Notification) { window = NSWindow(contentRect: NSRect(x: 0, y: 0, width: 400, height: 300), styleMask: [.titled, .closable, .resizable], backing: .buffered, defer: false) window.makeKeyAndOrderFront(nil) let toolbar = NSToolbar(identifier: "MainToolbar") toolbar.delegate = self window.toolbar = toolbar } func toolbarAllowedItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] { return [NSToolbarItem.Identifier("item1"), NSToolbarItem.Identifier("item2")] } func toolbarDefaultItemIdentifiers(_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] { return [NSToolbarItem.Identifier("item1"), NSToolbarItem.Identifier("item2")] } func toolbar(_ toolbar: NSToolbar, itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier, willBeInsertedIntoToolbar: Bool) -> NSToolbarItem? { let item = NSMenuToolbarItem(itemIdentifier: itemIdentifier) if itemIdentifier == NSToolbarItem.Identifier("item1") { let menu = NSMenu() fillMenuWithItems(menu) item.menu = menu } else if itemIdentifier == NSToolbarItem.Identifier("item2") { item.menu = NSMenu() item.menu.delegate = self } return item } func menuNeedsUpdate(_ menu: NSMenu) { menu.removeAllItems() fillMenuWithItems(menu) } func fillMenuWithItems(_ menu: NSMenu) { menu.addItem(NSMenuItem(title: "Option 1", action: nil, keyEquivalent: "")) menu.addItem(NSMenuItem(title: "Option 2", action: nil, keyEquivalent: "")) } }
1
0
393
Sep ’24
Cannot Display MTKView on a sheeted view on macOS15
I use xcode16 and swiftUI for programming on a macos15 system. There is a problem. When I render a picture through mtkview, it is normal when displayed on a regular view. However, when the view is displayed through the .sheet method, the image cannot be displayed. There is no error message from xcode. import Foundation import MetalKit import SwiftUI struct CIImageDisplayView: NSViewRepresentable { typealias NSViewType = MTKView var ciImage: CIImage init(ciImage: CIImage) { self.ciImage = ciImage } func makeNSView(context: Context) -> MTKView { let view = MTKView() view.delegate = context.coordinator view.preferredFramesPerSecond = 60 view.enableSetNeedsDisplay = true view.isPaused = true view.framebufferOnly = false if let defaultDevice = MTLCreateSystemDefaultDevice() { view.device = defaultDevice } view.delegate = context.coordinator return view } func updateNSView(_ nsView: MTKView, context: Context) { } func makeCoordinator() -> RawDisplayRender { RawDisplayRender(ciImage: self.ciImage) } class RawDisplayRender: NSObject, MTKViewDelegate { // MARK: Metal resources var device: MTLDevice! var commandQueue: MTLCommandQueue! // MARK: Core Image resources var context: CIContext! var ciImage: CIImage init(ciImage: CIImage) { self.ciImage = ciImage self.device = MTLCreateSystemDefaultDevice() self.commandQueue = self.device.makeCommandQueue() self.context = CIContext(mtlDevice: self.device) } func mtkView(_ view: MTKView, drawableSizeWillChange size: CGSize) {} func draw(in view: MTKView) { guard let currentDrawable = view.currentDrawable, let commandBuffer = commandQueue.makeCommandBuffer() else { return } let dSize = view.drawableSize let drawImage = self.ciImage let destination = CIRenderDestination(width: Int(dSize.width), height: Int(dSize.height), pixelFormat: view.colorPixelFormat, commandBuffer: commandBuffer, mtlTextureProvider: { () -> MTLTexture in return currentDrawable.texture }) _ = try? self.context.startTask(toClear: destination) _ = try? self.context.startTask(toRender: drawImage, from: drawImage.extent, to: destination, at: CGPoint(x: (dSize.width - drawImage.extent.width) / 2, y: 0)) commandBuffer.present(currentDrawable) commandBuffer.commit() } } } struct ShowCIImageView: View { let cii = CIImage.init(contentsOf: Bundle.main.url(forResource: "9-10", withExtension: "jpg")!)! var body: some View { CIImageDisplayView.init(ciImage: cii).frame(width: 500, height: 500).background(.red) } } struct ContentView: View { @State var showImage = false var body: some View { VStack { Image(systemName: "globe") .imageScale(.large) .foregroundStyle(.tint) Text("Hello, world!") ShowCIImageView() Button { showImage = true } label: { Text("showImage") } } .frame(width: 800, height: 800) .padding() .sheet(isPresented: $showImage) { ShowCIImageView() } } }
2
1
602
Oct ’24
Creating file bookmarks doesn't work anymore on macOS 15 Sequoia
Before updating to macOS 15 Sequoia, I used to be able to create file bookmarks with this code: let openPanel = NSOpenPanel() openPanel.runModal() let url = openPanel.urls[0] do { let _ = try url.bookmarkData(options: [.withSecurityScope]) } catch { print(error) } Now I get an error Error Domain=NSCocoaErrorDomain Code=256 "Failed to retrieve app-scope key" These are the entitlements: com.apple.security.app-sandbox com.apple.security.files.user-selected.read-write com.apple.security.files.bookmarks.app-scope Strangely, my own apps continued working, after updating to macOS 15 some days ago, until a few moments ago. Then it seems that all of a sudden my existing bookmarks couldn't be resolved anymore, and no new bookmarks could be created. What could be the problem?
28
3
3.1k
Feb ’25
Possible to have NSWindow *without* NSWindowStyleMaskTitled to make the screen its on the main screen?
I have a NSWindow subclass. The window has a custom shape, and thus has a custom contentView which overrides drawRect to draw . Since the window has a custom shape it cannot use the system provided titlebar. The problem I'm having is when there are multiple screens, if my window is on the inactive screen (not mainScreen with menu bar) and I move the mouse over to the second monitor and click the window....the menu bar doesn't travel to the screen my app is on after the window is clicked. This does not happen with any other window. In all other windows, the menu bar moves to the screen once you click a window on that screen. So it appears this is because my window is not using NSWindowStyleMaskTitled. As far as I know, I can't use the system title bar and draw my custom window shape. Abandoning the custom window shape is not an option. Without going into too many details as to why I care, the menu bar really should travel with first click on my window like other apps.. Is there a way to tell the system (other than using the NSWindowStyleMaskTitled) that clicking on my window should make that screen the "main screen" (bring the menu bar over? I tried programmatically activating the application, ordering the window to the front, etc. but none of this works. This forces the user to click outside my app window, say on the desktop, to move the menu bar over, which feels wrong. Thanks in advance if anyone has any suggestions.
Topic: UI Frameworks SubTopic: AppKit Tags:
5
0
623
Dec ’24
Apps not quitting immediately
Hello all, Recently I observed a strange behaviour on macOS. Some apps with UI, after you quit them (right click on the Dock, select Quit or select Quit from the menubar), the apps are not actually quitting immediately, but in a few seconds (including in Activity Monitor the apps are staying alive). Also, if you open the apps again fast, the same PID is kept. Not all apps do this, some of them, for example WhatsApp. I'm not referring to closing all windows, but explicitly quitting. This was not the case in the past. Is there any reason for this? Is some kind of optimisation I'm not aware of? The actual issue is that in a Swift developed app events like NSWorkspace.didLaunchApplicationNotification or NSWorkspace.didTerminateApplicationNotification are not triggered. Is there any way to tell if an app was closed, even if macOS still keeps it around for a few more seconds? Thank you.
1
0
658
Sep ’24
Wait for some completion in main thread using Catalyst environment
I need to bring an iOS application to macOS using Catalyst. This application contain parts where it waits for a button to be pressed in the main thread, using [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; in a while loop to allow some dispatching while waiting. I know that this is not good style, but I need to convert this old source code and mentioned that when using this part of code under Catalyst, the main thread will not dispatch. So the button cannot be clicked, and a beach ball appears after two seconds. I saw a similar construct for native macOS applications: NSEvent *event= [[NSApplication sharedApplication] nextEventMatchingMask:NSEventMaskAny untilDate:[NSDate dateWithTimeIntervalSinceNow:0.1] inMode:NSDefaultRunLoopMode dequeue:YES]; if (event) { [[NSApplication sharedApplication] sendEvent:event]; } but I do not have access to NSEvent and NSApplication in a Catalyst environment. Question: I there any code snippet which I can use to achieve the above? I do not want to completely rewrite old code if there is a solution for this. Any ideas or hints are highly appreciated. Thank you! Markus
4
0
554
Oct ’24
[macOS Sequoia] Using RegisterEventHotkey with option and shift modifiers doesn't working anymore
Hello. In my app, I use RegisterEventHotkey to implement global keyboard shortcuts to trigger actions. Up until macOS Sequoia, I was able to use a keyboard shortcut with option and shift as the modifiers, like option shift 2 (⌥ ⇧ 2). Now, on macOS Sequoia, using RegisterEventHotkey to register a hotkey with those exact modifiers (option and shift), regardless of the key, fails with the error -9868 (eventInternalErr). Is this a documented and wanted change, or is this a bug? Other modifier keys (just command, command option, command shift, command control, control shift, etc), all work. Any insight into this would be appreciated. (Feedback filed: FB15163561) Thank you, Matthias
21
10
11k
Jan ’25
How can I set my window title in Cocoa?
I have a simple cocoa project, it has the default files like AppDelegate.m, AppDelegate.h , ViewController.h and ViewController.m what I want is to set the Window title to the dimension of the current window and update it as the user resizes it. My Storyboard has an Application Scene, a Window Controller Scene and a test Scene which contains my view: how do I go about this? should my ViewController or AppController implement NSWindowDelegate ?
2
0
533
Sep ’24
NSClickGestureRecognizer not working to invoked the registered event method
I have created a NSView inside the NSWindow. I m trying to identify when the view gets clicked by the user. For this I m using NSClickGestureRecognizer, but the registered method is not getting invoked. I have tried adding this for other widgets like button but it does not work either. Am I missing something? class SelectionList :NSObject, NSTextFieldDelegate{ let containerView = NSView() func createSelectionList (pWindow: NSWindow) { // created container View ... let clickRecognizer = NSClickGestureRecognizer() clickRecognizer.target = self clickRecognizer.buttonMask = 0x2 // right button clickRecognizer.numberOfClicksRequired = 1 clickRecognizer.action = #selector(ClickGestured) containerView .addGestureRecognizer(clickRecognizer) } @objc func clickRecognizer() { print("clicked") } }
Topic: UI Frameworks SubTopic: AppKit Tags:
0
0
391
Sep ’24
autoreleasepool still gives me a memory leak
So I have this program that displays events on the window using NSWindow and a NSTextField. Basically it tracks the mouse position and the keyboard state. I created a simple class named MyEventWindow: // // MyEventWindow.h // AppTest #ifndef MyEventWindow_h #define MyEventWindow_h @interface MyEventWindow : NSWindow { } @property(nonatomic, strong) NSTextField* label; @property(nonatomic, strong) NSString* labelText; - (BOOL)windowShouldClose:(id)sender; - (instancetype) init; - (void) setLabelText:(NSString *)labelText; @end @implementation MyEventWindow -(instancetype) init { self = [super initWithContentRect:NSMakeRect(100, 100, 300, 300) styleMask:(NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable) backing:NSBackingStoreBuffered defer:NO]; if( !self ) { return nil; } [self setTitle: @"Event tracker"]; [self setIsVisible: YES]; _label = [[NSTextField alloc] initWithFrame:NSMakeRect(5, 100, 290, 100)]; [_label setBezeled: NO]; [_label setDrawsBackground: NO]; [_label setEditable: NO]; [_label setSelectable: YES]; NSFont *currentFont = [_label font]; NSFont *resizedFont = [NSFont fontWithName:[currentFont fontName] size:18]; NSFont *boldFont = [[NSFontManager sharedFontManager] convertFont:resizedFont toHaveTrait:NSFontBoldTrait]; // convert the bold font to have the italic trait NSFont *boldItalicFont = [[NSFontManager sharedFontManager] convertFont:boldFont toHaveTrait:NSFontItalicTrait]; [_label setFont:boldItalicFont]; [_label setTextColor:[NSColor colorWithSRGBRed:0.0 green:0.5 blue:0.0 alpha:1.0]]; // attach label to the damn window [[self contentView] addSubview: _label]; return self; } -(BOOL)windowShouldClose:(id)sender { return YES; } -(void) setLabelText:(NSString *)newText { [_label setStringValue: newText]; } @end #endif /* MyEventWindow_h */ Then in the main file I try to handle event loop manually: // // main.m #import <Cocoa/Cocoa.h> #import "MyEventWindow.h" NSString* NSEventTypeToNSString(NSEventType eventType); NSString* NSEventModifierFlagsToNSString(NSEventModifierFlags modifierFlags); int main(int argc, char* argv[]) { @autoreleasepool { [NSApplication sharedApplication]; MyEventWindow* eventWindow = [[MyEventWindow alloc] init]; [eventWindow makeKeyAndOrderFront:nil]; NSString* log = [NSString string]; // my own message loop [NSApp finishLaunching]; while (true) { @autoreleasepool { NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny untilDate: [NSDate distantFuture] inMode:NSDefaultRunLoopMode dequeue:YES]; log = [NSString stringWithFormat:@"Event [type=%@ location={%d, %d} modifierFlags={%@}]", NSEventTypeToNSString([event type]), (int)[event locationInWindow].x, (int)[event locationInWindow].y, NSEventModifierFlagsToNSString([event modifierFlags])]; //NSLog(@"log: %@", log); [eventWindow setLabelText: log]; [NSApp sendEvent:event]; //[NSApp updateWindows]; // redundant? } } } return 0; } NSString* NSEventTypeToNSString(NSEventType eventType) { switch (eventType) { case NSEventTypeLeftMouseDown: return @"LeftMouseDown"; case NSEventTypeLeftMouseUp: return @"LeftMouseUp"; case NSEventTypeRightMouseDown: return @"RightMouseDown"; case NSEventTypeRightMouseUp: return @"RightMouseUp"; case NSEventTypeMouseMoved: return @"MouseMoved"; case NSEventTypeLeftMouseDragged: return @"LeftMouseDragged"; case NSEventTypeRightMouseDragged: return @"RightMouseDragged"; case NSEventTypeMouseEntered: return @"MouseEntered"; case NSEventTypeMouseExited: return @"MouseExited"; case NSEventTypeKeyDown: return @"KeyDown"; case NSEventTypeKeyUp: return @"KeyUp"; case NSEventTypeFlagsChanged: return @"FlagsChanged"; case NSEventTypeAppKitDefined: return @"AppKitDefined"; case NSEventTypeSystemDefined: return @"SystemDefined"; case NSEventTypeApplicationDefined: return @"ApplicationDefined"; case NSEventTypePeriodic: return @"Periodic"; case NSEventTypeCursorUpdate: return @"CursorUpdate"; case NSEventTypeScrollWheel: return @"ScrollWheel"; case NSEventTypeTabletPoint: return @"TabletPoint"; case NSEventTypeTabletProximity: return @"TabletProximity"; case NSEventTypeOtherMouseDown: return @"OtherMouseDown"; case NSEventTypeOtherMouseUp: return @"OtherMouseUp"; case NSEventTypeOtherMouseDragged: return @"OtherMouseDragged"; default: return [NSString stringWithFormat:@"%lu", eventType]; } } NSString* NSEventModifierFlagsToNSString(NSEventModifierFlags modifierFlags) { NSString* result = @""; if ((modifierFlags & NSEventModifierFlagCapsLock) == NSEventModifierFlagCapsLock) result = [result stringByAppendingString:@"CapsLock, "]; if ((modifierFlags & NSEventModifierFlagShift) == NSEventModifierFlagShift) result = [result stringByAppendingString:@"NShift, "]; if ((modifierFlags & NSEventModifierFlagControl) == NSEventModifierFlagControl) result = [result stringByAppendingString:@"Control, "]; if ((modifierFlags & NSEventModifierFlagOption) == NSEventModifierFlagOption) result = [result stringByAppendingString:@"Option, "]; if ((modifierFlags & NSEventModifierFlagCommand) == NSEventModifierFlagCommand) result = [result stringByAppendingString:@"Command, "]; if ((modifierFlags & NSEventModifierFlagNumericPad) == NSEventModifierFlagNumericPad) result = [result stringByAppendingString:@"NumericPad, "]; if ((modifierFlags & NSEventModifierFlagHelp) == NSEventModifierFlagHelp) result = [result stringByAppendingString:@"Help, "]; if ((modifierFlags & NSEventModifierFlagFunction) == NSEventModifierFlagFunction) result = [result stringByAppendingString:@"Function, "]; return result; } in main I added a second @autoreleasepool inside the while loop it seemed to decrease memory usage significanly, however if I keep moving my mouse a lot the memory usage will still increase. I don't think this should be happening since the labelText is being destroying and recreated each iteration, is something wrong with my code? Why do I have a memory leak here? Any feedback regarding the code is also appreciated Cheers
1
0
547
Sep ’24
vImageConverter_CreateWithCGImageFormat Fails with kvImageInvalidImageFormat When Trying to Convert CMYK to RGB
So I get JPEG data in my app. Previously I was using the higher level NSBitmapImageRep API and just feeding the JPEG data to it. But now I've noticed on Sonoma If I get a JPEG in the CMYK color space the NSBitmapImageRep renders mostly black and is corrupted. So I'm trying to drop down to the lower level APIs. Specifically I grab a CGImageRef and and trying to use the Accelerate API to convert it to another format (to hopefully workaround the issue... CGImageRef sourceCGImage = `CGImageCreateWithJPEGDataProvider(jpegDataProvider,` NULL, shouldInterpolate, kCGRenderingIntentDefault); Now I use vImageConverter_CreateWithCGImageFormat... with the following values for source and destination formats: Source format: (derived from sourceCGImage) bitsPerComponent = 8 bitsPerPixel = 32 colorSpace = (kCGColorSpaceICCBased; kCGColorSpaceModelCMYK; Generic CMYK Profile) bitmapInfo = kCGBitmapByteOrderDefault version = 0 decode = 0x000060000147f780 renderingIntent = kCGRenderingIntentDefault Destination format: bitsPerComponent = 8 bitsPerPixel = 24 colorSpace = (DeviceRBG) bitmapInfo = 8197 version = 0 decode = 0x0000000000000000 renderingIntent = kCGRenderingIntentDefault But vImageConverter_CreateWithCGImageFormat fails with kvImageInvalidImageFormat. Now if I change the destination format to use 32 bitsPerpixel and use alpha in the bitmap info the vImageConverter_CreateWithCGImageFormat does not return an error but I get a black image just like NSBitmapImageRep
13
0
1.3k
Nov ’24
PrintCore API is lagging on the Sequoia
The performance of the PrintCore API on macOS Sequoia system has significantly deteriorated. When switching between page options in the print dialog, the application hangs. It can be observed through Instruments that the execution time of PrintCore() is higher on the Sequoia system than on the Sonoma system. 479.00 ms 17.0% 0 s PMBaseObject::PMBaseObject(char const*) 456.00 ms 16.2% 0 s PMBaseObject::~PMBaseObject()
0
0
393
Sep ’24
How to instantiate subclass of NSDocumentController?
Hello, I want to subclass NSDocumentController, but I could not find the information in Apple document how to subclass. According to ChatGPT, it can be instantiated by [MyDocumentController sharedDocumentController]; before NSApplicationMain() as the following code. It seems working well in my test environment. int main(int argc, const char * argv[]) { [MyDocumentController sharedDocumentController]; NSApplicationMain(argc, argv); } But, I am not sure whether it is officially correct to instantiate so early (before calling NSApplicationMain). Is there any official information what is correct way to instantiate subclass of NSDocumentController?
Topic: UI Frameworks SubTopic: AppKit Tags:
1
0
582
Sep ’24
How to simulate a mouse click on an iPad connected as an external display
Hello. What API or framework to use to simulate a mouse click on an iPad connected as an external display? An iPad connected to the Mac via USB in a mode "Linked keyboard and mouse". What is the way to simulate a mouse click at a specific coordinate at such a display? So far I tried to simulate a click with CGEvent like so if let eventDown = CGEvent(mouseEventSource: source, mouseType: .leftMouseDown, mouseCursorPosition: point, mouseButton: .left), let eventUp = CGEvent(mouseEventSource: source, mouseType: .leftMouseUp, mouseCursorPosition: point, mouseButton: .left) { eventDown.post(tap: .cghidEventTap) usleep(500_000) eventUp.post(tap: .cghidEventTap) } but it seems it does not work even on the main display. I set the point to the coordinate outside of the app window so that on a click another app should be focused but it does not happen on a simulated click. I also tried to find a way to get a mouse coordinate on the external screen with addLocalMonitorForEvents. If I listen for the event NSEvent.addLocalMonitorForEvents(matching: [.mouseMoved]) { event in debugPrint("NSEvent.mouseLocation:", NSEvent.mouseLocation) return event } it only works when the cursor is on the main screen and stops reporting as soon as the mouse enters the iPad. So, any advice is welcomed on which direction I should look.
0
0
599
Sep ’24
Programatically changing the brightness of your Macbook
Hi all, I was wondering if anyone knew a way to change the brightness of your MacBook screen in Swift without using an overlay that changes the colours? I want the effect of just pressing the F1 and F2 brightness controls but done without using system events/ Applescript popping up windows on the screen. I think the UIScreen.brightness is something similar to what I want but it is not available for NSscreen. I can't figure out a way to do it with IOKit either. Things like ddccl doesn't work as the screen is not an external monitor. If there is a solution using Swift or terminal commands any help is much appreciated. Thanks, James
1
0
790
Sep ’24
How do I get available printer list
I am trying to get the list of printers using NSPrinter.printerNames, but it doesn't return any items. static func getPrinterList() -> [(name: String, isAvailable: Bool)] { let printerNames = NSPrinter.printerNames return printerNames.map { name in let isAvailable = NSPrinter(name: name) != nil return (name: name, isAvailable: isAvailable) } } The printerNames is a empty string array. I checked the settings for printers and screens, and there is a printer device listed. I need to set something else?
2
0
615
Aug ’24
does simulator accurately reflect translucent UIs?
Im building a macOS application where the UI is a blurry transparent background that is somewhat see through like what apple uses for the macOS control center and I'm using the NSVisualEffectView from AppKit to do so. My question is, does the Xcode simulator accurately portray translucent UI views? in other words: "what you see is what you get" or will the vibrancy be more pronounced when the app is run on my machine itself. var material: NSVisualEffectView.Material = .contentBackground //blurry background to cover the whole UI var blendUI: NSVisualEffectView.BlendingMode = .behindWindow // applying the blurry background to the UI window itself var allowsVibrancy: Bool = true func makeNSView(context: Context) -> NSVisualEffectView { let blurryEffectView = NSVisualEffectView() blurryEffectView.material = material blurryEffectView.blendingMode = blendUI return NSVisualEffectView() } func updateNSView(_ nsView: NSVisualEffectView, context: Context) { // _ added, no argument label needed nsView.material = .contentBackground nsView.blendingMode = blendUI } } struct ContentView: View { var body: some View { ZStack{ EffectView(material: NSVisualEffectView.Material.contentBackground, blendUI: NSVisualEffectView.BlendingMode.behindWindow ) } } }
2
0
592
Aug ’24
Dynamic Notch
If anyone there is familiar with Cocoa, can you please help with the following issue: How to make the NSWindow resize based on the contentView? Here is a video of the problem: https://drive.google.com/file/d/19LN98xdF9OLcqRZhMJsGGSa0dgMvj_za/view?usp=sharing Thanks!
0
0
523
Aug ’24