### Install FMPFeedbackForm with Carthage Source: https://github.com/macpaw/fmpfeedbackform/blob/master/README.md Add this line to your Cartfile to install the FMPFeedbackForm framework using Carthage. ```ruby github "MacPaw/FMPFeedbackForm" ``` -------------------------------- ### Implement Custom Backend for FMPFeedbackSender Source: https://context7.com/macpaw/fmpfeedbackform/llms.txt Create a custom feedback submission backend by conforming to the FMPFeedbackSender protocol. This example shows how to initialize a custom sender with an API endpoint and key, and how to send feedback data to your own service. ```objc // CustomFeedbackSender.h #import #import @interface CustomFeedbackSender : NSObject @property (nonatomic, assign) NSUInteger maxAttachmentsCount; @property (nonatomic, assign) NSUInteger maxAttachmentFileSize; - (instancetype)initWithAPIEndpoint:(NSString *)endpoint apiKey:(NSString *)apiKey; @end // CustomFeedbackSender.m #import "CustomFeedbackSender.h" #import @implementation CustomFeedbackSender { NSString *_endpoint; NSString *_apiKey; } - (instancetype)initWithAPIEndpoint:(NSString *)endpoint apiKey:(NSString *)apiKey { self = [super init]; if (self) { _endpoint = endpoint; _apiKey = apiKey; _maxAttachmentsCount = 5; // Limit to 5 user attachments _maxAttachmentFileSize = 10; // Limit to 10 MB per file } return self; } - (void)sendFeedbackWithParameters:(NSDictionary *)parameters completion:(FMPSendFeedbackCompletion)completion { // Extract form data from parameters dictionary NSString *name = parameters[FMPFeedbackParameterName]; NSString *email = parameters[FMPFeedbackParameterEmail]; NSString *subject = parameters[FMPFeedbackParameterSubject]; NSString *details = parameters[FMPFeedbackParameterDetails]; NSArray *attachments = parameters[FMPFeedbackParameterAttachments]; NSURL *systemProfileURL = parameters[FMPFeedbackParameterSystemProfile]; // Build your API request NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:_endpoint]]; request.HTTPMethod = @"POST"; [request setValue:_apiKey forHTTPHeaderField:@"Authorization"]; [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]; NSDictionary *body = @{ @"name": name ?: @"", @"email": email ?: @"", @"subject": subject ?: @"", @"message": details ?: @"" }; request.HTTPBody = [NSJSONSerialization dataWithJSONObject:body options:0 error:nil]; // Send request NSURLSessionDataTask *task = [[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { dispatch_async(dispatch_get_main_queue(), ^{ if (error) { completion(error); } else { NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response; if (httpResponse.statusCode >= 200 && httpResponse.statusCode < 300) { completion(nil); // Success } else { NSError *apiError = [NSError errorWithDomain:@"CustomFeedbackError" code:httpResponse.statusCode userInfo:@{NSLocalizedDescriptionKey: @"API request failed"}]; completion(apiError); } } }); }]; [task resume]; } @end ``` -------------------------------- ### Install FMPFeedbackForm with CocoaPods Source: https://github.com/macpaw/fmpfeedbackform/blob/master/README.md Add this line to your Podfile to install the FMPFeedbackForm framework using CocoaPods. ```ruby pod 'FMPFeedbackForm' ``` -------------------------------- ### Initialize FMPFeedbackController with Zendesk Sender Source: https://github.com/macpaw/fmpfeedbackform/blob/master/README.md Instantiate an FMPZendeskFeedbackSender with your Zendesk credentials and then use it to initialize the FMPFeedbackController. Hold a reference to the controller to prevent deallocation. ```swift // Hold a reference to the controller object somewhere, otherwise it'll get deallocated var feedbackController: FMPFeedbackController? // User wants to display the feedback form @IBAction func provideFeedbackButtonClick(_ sender: Any) { // Instantiate an FMPFeedbackSender object let zendeskSender = FMPZendeskFeedbackSender(zendeskSubdomain: "subdomain", // (1) authToken: "sometoken", // (2) productName: "My App") // (3) // Create the controller feedbackController = FMPFeedbackController(feedbackSender: zendeskSender) // Present the form feedbackController?.showWindow(self) } ``` -------------------------------- ### Initialize FMPZendeskFeedbackSender Source: https://context7.com/macpaw/fmpfeedbackform/llms.txt Initialize `FMPZendeskFeedbackSender` with your Zendesk subdomain, API token, and product name. Anonymous submissions are possible by omitting the auth token. Custom ticket fields can be configured using an array of dictionaries. ```swift import FMPFeedbackForm // Basic initialization with Zendesk credentials let zendeskSender = FMPZendeskFeedbackSender( zendeskSubdomain: "mycompany", // subdomain from https://mycompany.zendesk.com authToken: "abc123xyz", // API token from Zendesk admin panel productName: "MyApp" // Appears as "[MyApp] Bug Report" in ticket subject ) // Alternative initialization without auth token (for anonymous submissions) let anonymousSender = FMPZendeskFeedbackSender( zendeskSubdomain: "mycompany", productName: "MyApp" ) // Configure custom Zendesk ticket fields zendeskSender.customFields = [ ["id": 123456789, "value": "premium"], // Custom field for user tier ["id": 987654321, "value": "2.5.0"] // Custom field for app version ] // Use with FMPFeedbackController let feedbackController = FMPFeedbackController(feedbackSender: zendeskSender) feedbackController.showWindow(nil) ``` -------------------------------- ### Configure System Profile Report Source: https://context7.com/macpaw/fmpfeedbackform/llms.txt Configure the system profile report for feedback. This Swift code shows how to initialize the sender, controller, and customize log files and user defaults domain. ```swift import FMPFeedbackForm let zendeskSender = FMPZendeskFeedbackSender( zendeskSubdomain: "mycompany", authToken: "token", productName: "MyApp" ) let feedbackController = FMPFeedbackController(feedbackSender: zendeskSender) // Add custom log files to be included in system profile report // These are appended to the automatically gathered console logs feedbackController.logURLs = [ URL(fileURLWithPath: NSHomeDirectory() + "/Library/Logs/MyApp/app.log"), URL(fileURLWithPath: NSHomeDirectory() + "/Library/Logs/MyApp/network.log"), URL(fileURLWithPath: NSHomeDirectory() + "/Library/Logs/MyApp/crash.log") ] // Specify custom UserDefaults domain if your app uses a non-standard domain // By default, the framework uses your app's bundle identifier feedbackController.userDefaultsDomain = "com.mycompany.myapp.preferences" // The system profile report includes: // - macOS version and build number // - Hardware model and specifications // - Memory and disk information // - Recent console logs related to your app // - Contents of specified custom log files // - UserDefaults/preferences for your app feedbackController.showWindow(nil) ``` -------------------------------- ### Send Feedback with Parameters Source: https://context7.com/macpaw/fmpfeedbackform/llms.txt Use this Objective-C method to send feedback with various parameters. Ensure all required keys are present in the parameters dictionary. ```objc #import - (void)sendFeedbackWithParameters:(NSDictionary *)parameters completion:(FMPSendFeedbackCompletion)completion { // Available parameter keys: // FMPFeedbackParameterName - NSString: User's name // FMPFeedbackParameterEmail - NSString: User's email address // FMPFeedbackParameterSubject - NSString: Selected subject from dropdown // FMPFeedbackParameterDetails - NSString: Feedback message body // FMPFeedbackParameterAttachments - NSArray: User-attached files // FMPFeedbackParameterSystemProfile - NSURL: System profile text file (if checkbox enabled) NSString *userName = parameters[FMPFeedbackParameterName]; NSString *userEmail = parameters[FMPFeedbackParameterEmail]; NSString *ticketSubject = parameters[FMPFeedbackParameterSubject]; NSString *messageBody = parameters[FMPFeedbackParameterDetails]; NSArray *userAttachments = parameters[FMPFeedbackParameterAttachments]; NSURL *systemProfileFile = parameters[FMPFeedbackParameterSystemProfile]; // Process attachments NSMutableArray *attachmentData = [NSMutableArray array]; for (NSURL *fileURL in userAttachments) { NSData *data = [NSData dataWithContentsOfURL:fileURL]; if (data) { [attachmentData addObject:data]; } } // Include system profile if user opted in if (systemProfileFile) { NSString *profileContent = [NSString stringWithContentsOfURL:systemProfileFile encoding:NSUTF8StringEncoding error:nil]; NSLog(@"System Profile:\n%@", profileContent); } // ... send to your backend completion(nil); } ``` -------------------------------- ### Presenting Feedback Form with Zendesk Integration Source: https://context7.com/macpaw/fmpfeedbackform/llms.txt Use `FMPFeedbackController` to present a customizable feedback form. Configure Zendesk sender, behavior options, custom logs, and handle submission callbacks. Ensure a strong reference to `feedbackController` to prevent deallocation. ```swift import Cocoa import FMPFeedbackForm class AppDelegate: NSObject, NSApplicationDelegate { // Hold a strong reference to prevent deallocation var feedbackController: FMPFeedbackController? @IBAction func showFeedbackForm(_ sender: Any) { // Create Zendesk sender with credentials let zendeskSender = FMPZendeskFeedbackSender( zendeskSubdomain: "mycompany", authToken: "your_zendesk_api_token", productName: "MyApp" ) // Initialize controller with sender feedbackController = FMPFeedbackController(feedbackSender: zendeskSender) // Configure behavior options feedbackController?.showsGenericSuccessAlert = true feedbackController?.showsGenericErrorSheet = true // Add custom log files for system profile report feedbackController?.logURLs = [ URL(fileURLWithPath: "/path/to/app.log"), URL(fileURLWithPath: "/path/to/debug.log") ] // Set custom user defaults domain if needed feedbackController?.userDefaultsDomain = "com.mycompany.myapp.custom" // Handle submission completion feedbackController?.onDidSendFeedback = { [weak self] error in if let error = error { print("Feedback submission failed: \(error.localizedDescription)") } else { print("Feedback sent successfully!") self?.feedbackController?.close() } } // Present the feedback window feedbackController?.showWindow(self) } } ``` -------------------------------- ### Customize Feedback Form UI Settings (Initializer) Source: https://github.com/macpaw/fmpfeedbackform/blob/master/README.md Initialize FMPFeedbackController with custom UI settings by creating an FMPInterfaceSettings object, modifying its properties, and passing it to the controller's initializer. ```swift let settings = FMPInterfaceSettings.default settings.title = "My App feedback" settings.subtitle = "We'd love to know what you think of our product." settings.subjectOptions = ["Feedback", "Bug Report", "Support Request"] if let iconResource = NSImage(contentsOf: "path/to/icon.png") { settings.icon = iconResource settings.iconSize = NSSize(width: 64, height: 64) // default value } feedbackController = FMPFeedbackController(feedbackSender: sender, settings: settings) ``` -------------------------------- ### Include Custom Log Files in Report Source: https://github.com/macpaw/fmpfeedbackform/blob/master/README.md Specify URLs to custom log files to be included in the system profile report. This enhances data quality beyond console logs. ```swift feedbackController?.logURLs = [URL(fileURLWithPath: "path/to/file.log"), URL(fileURLWithPath: "path/to/otherFile.txt")] ``` -------------------------------- ### FMPInterfaceSettings - UI Customization Source: https://context7.com/macpaw/fmpfeedbackform/llms.txt Configure the visual elements and text labels of the feedback form. ```APIDOC ## FMPInterfaceSettings - UI Customization Configuration object for customizing all text labels, placeholders, and visual elements of the feedback form. ### Usage Example ```swift import Cocoa import FMPFeedbackForm // Get default settings with localized values let settings = FMPInterfaceSettings.default // Customize window and form titles settings.windowTitle = "Send Feedback" settings.title = "We'd love to hear from you" settings.subtitle = "Please describe your issue or suggestion below." // Customize form field placeholders settings.namePlaceholder = "Your name" settings.emailPlaceholder = "your.email@example.com" settings.detailsPlaceholder = "Describe your feedback in detail..." // Pre-fill user information if known settings.defaultName = "John Doe" settings.defaultEmail = "john.doe@example.com" // Configure subject dropdown options settings.subjectOptions = [ "Bug Report", "Feature Request", "General Feedback", "Technical Support" ] // Add custom app icon (displayed in top-left corner) if let appIcon = NSImage(named: "AppIcon") { settings.icon = appIcon settings.iconSize = NSSize(width: 64, height: 64) // Default size } // Initialize controller with custom settings let zendeskSender = FMPZendeskFeedbackSender( zendeskSubdomain: "mycompany", authToken: "token", productName: "MyApp" ) let feedbackController = FMPFeedbackController( feedbackSender: zendeskSender, settings: settings ) feedbackController.showWindow(nil) ``` ### Properties - **windowTitle** (String) - The title of the feedback window. - **title** (String) - The main title displayed on the feedback form. - **subtitle** (String) - A subtitle or descriptive text below the main title. - **namePlaceholder** (String) - Placeholder text for the name input field. - **emailPlaceholder** (String) - Placeholder text for the email input field. - **detailsPlaceholder** (String) - Placeholder text for the feedback details textarea. - **defaultName** (String) - Pre-filled default value for the name field. - **defaultEmail** (String) - Pre-filled default value for the email field. - **subjectOptions** (Array) - An array of strings for the subject dropdown options. - **icon** (NSImage) - A custom icon to display in the top-left corner of the form. - **iconSize** (NSSize) - The size of the custom icon. ``` -------------------------------- ### Set Default User Information Source: https://github.com/macpaw/fmpfeedbackform/blob/master/README.md Simplify form filling by pre-setting the user's name and email in the FMPInterfaceSettings. This can be done after the controller has been initialized. ```swift feedbackController?.settings.defaultName = "John Doe" feedbackController?.settings.defaultEmail = "john.doe@gmail.com" ``` -------------------------------- ### Customize FMPFeedbackForm UI with FMPInterfaceSettings Source: https://context7.com/macpaw/fmpfeedbackform/llms.txt Configure text labels, placeholders, titles, and the app icon for the feedback form. Pre-fill user information and set subject dropdown options. This is useful for tailoring the form to your application's branding and user experience. ```swift import Cocoa import FMPFeedbackForm // Get default settings with localized values let settings = FMPInterfaceSettings.default // Customize window and form titles settings.windowTitle = "Send Feedback" settings.title = "We'd love to hear from you" settings.subtitle = "Please describe your issue or suggestion below." // Customize form field placeholders settings.namePlaceholder = "Your name" settings.emailPlaceholder = "your.email@example.com" settings.detailsPlaceholder = "Describe your feedback in detail..." // Pre-fill user information if known settings.defaultName = "John Doe" settings.defaultEmail = "john.doe@example.com" // Configure subject dropdown options settings.subjectOptions = [ "Bug Report", "Feature Request", "General Feedback", "Technical Support" ] // Add custom app icon (displayed in top-left corner) if let appIcon = NSImage(named: "AppIcon") { settings.icon = appIcon settings.iconSize = NSSize(width: 64, height: 64) // Default size } // Initialize controller with custom settings let zendeskSender = FMPZendeskFeedbackSender( zendeskSubdomain: "mycompany", authToken: "token", productName: "MyApp" ) let feedbackController = FMPFeedbackController( feedbackSender: zendeskSender, settings: settings ) feedbackController.showWindow(nil) ``` -------------------------------- ### Customize Feedback Form UI Settings (After Init) Source: https://github.com/macpaw/fmpfeedbackform/blob/master/README.md Update the FMPFeedbackController's UI settings after initialization by accessing and modifying the 'settings' property. This allows for dynamic changes to the form's appearance and behavior. ```swift feedbackController?.settings.title = "My App feedback" feedbackController?.settings.subtitle = "We'd love to know what you think of our product." feedbackController?.settings.subjectOptions = ["Feedback", "Bug Report", "Support Request"] if let iconResource = NSImage(contentsOf: "path/to/icon.png") { feedbackController?.settings.icon = iconResource feedbackController?.settings.iconSize = NSSize(width: 64, height: 64) // default value } ``` -------------------------------- ### FMPFeedbackSender Protocol - Custom Backend Integration Source: https://context7.com/macpaw/fmpfeedbackform/llms.txt Implement this protocol to send feedback to custom backend services. ```APIDOC ## FMPFeedbackSender Protocol - Custom Backend Integration Protocol for implementing custom feedback submission backends. Implement this to send feedback to services other than Zendesk. ### CustomFeedbackSender Class This class is an example implementation of the `FMPFeedbackSender` protocol for sending feedback to a custom API endpoint. #### Initialization ```objc - (instancetype)initWithAPIEndpoint:(NSString *)endpoint apiKey:(NSString *)apiKey; ``` - **endpoint** (String) - The URL of your custom API endpoint. - **apiKey** (String) - The API key for authenticating with your custom backend. #### Properties - **maxAttachmentsCount** (NSUInteger) - The maximum number of attachments allowed (default: 5). - **maxAttachmentFileSize** (NSUInteger) - The maximum file size for each attachment in MB (default: 10). #### Method ```objc - (void)sendFeedbackWithParameters:(NSDictionary *)parameters completion:(FMPSendFeedbackCompletion)completion; ``` This method is called when the user submits the feedback form. You should implement the logic to send the feedback data to your backend. ##### Parameters - **parameters** (NSDictionary) - A dictionary containing feedback data. Keys include: - `FMPFeedbackParameterName` (String) - `FMPFeedbackParameterEmail` (String) - `FMPFeedbackParameterSubject` (String) - `FMPFeedbackParameterDetails` (String) - `FMPFeedbackParameterAttachments` (Array) - `FMPFeedbackParameterSystemProfile` (NSURL *) - **completion** (FMPSendFeedbackCompletion) - A block to be called upon completion. It receives an `NSError` object if an error occurred, otherwise `nil`. ### Request Body Example (for Custom Backend) ```json { "name": "John Doe", "email": "john.doe@example.com", "subject": "Bug Report", "message": "The application crashes when I try to save the file." } ``` ### Error Handling The `completion` block will receive an `NSError` object if the API request fails or if the HTTP response status code is not in the 2xx range. ``` -------------------------------- ### Modify Feedback Form Settings After Initialization Source: https://context7.com/macpaw/fmpfeedbackform/llms.txt Update interface settings dynamically after the feedback controller has been created. This includes setting default user information, customizing the form title and subtitle, and defining subject options. ```swift import Cocoa import FMPFeedbackForm class FeedbackManager { private var feedbackController: FMPFeedbackController? func showFeedback(for user: User?) { let sender = FMPZendeskFeedbackSender( zendeskSubdomain: "mycompany", authToken: "token", productName: "MyApp" ) feedbackController = FMPFeedbackController(feedbackSender: sender) // Modify settings after initialization if let user = user { feedbackController?.settings.defaultName = user.fullName feedbackController?.settings.defaultEmail = user.email } // Dynamically update based on app context feedbackController?.settings.title = "Contact Support" feedbackController?.settings.subtitle = "We typically respond within 24 hours." feedbackController?.settings.subjectOptions = [ "Account Issue", "Billing Question", "Bug Report", "Feature Request" ] // Access current form values (read-only) feedbackController?.onDidSendFeedback = { [weak self] error in if error == nil { let name = self?.feedbackController?.name ?? "" let email = self?.feedbackController?.email ?? "" let subject = self?.feedbackController?.subject ?? "" print("Feedback from \(name) (\(email)) - Subject: \(subject)") } } feedbackController?.showWindow(nil) } } ``` -------------------------------- ### Handle Feedback Submission Events Source: https://github.com/macpaw/fmpfeedbackform/blob/master/README.md Implement the onDidSendFeedback completion to handle submission success or failure with custom logic. It executes after default behavior if not disabled. ```swift feedbackController?.onDidSendFeedback = { [weak self] error in guard let error = error else { // Error is nil, display your custom success message self?.showSuccessMessage() self?.feedbackController?.close() return } // Error is not nil, submission failed, display error self?.showErrorMessage(with: error) } ``` -------------------------------- ### Add FMPFeedbackForm as a Swift Package Dependency Source: https://github.com/macpaw/fmpfeedbackform/blob/master/README.md Include FMPFeedbackForm as a dependency in your Swift package's Package.swift file. ```swift dependencies: [ ... .package(url: "https://github.com/MacPaw/FMPFeedbackForm", .upToNextMajor(from: "1.0.0")) ], ... targets: [ .target( name: ... dependencies: [ ..., "FMPFeedbackForm" ] ) ] ``` -------------------------------- ### Specify Custom UserDefaults Domain Source: https://github.com/macpaw/fmpfeedbackform/blob/master/README.md Set a custom NSUserDefaults domain (suite name) if your application uses one different from its bundle ID. ```swift feedbackController?.userDefaultsDomain = "com.MyCompany.MyAppsNonDefaultDomain" ``` -------------------------------- ### Disable Default Submission Handling Source: https://github.com/macpaw/fmpfeedbackform/blob/master/README.md Set these properties to false to disable the default success alert and error sheet. ```swift feedbackController?.showsGenericSuccessAlert = false feedbackController?.showsGenericErrorSheet = false ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.