From df56bfd57c9b6fc74cf3b6cfa058d1d300c856f2 Mon Sep 17 00:00:00 2001 From: Ty Clifford Date: Sun, 5 Jul 2026 21:22:17 -0400 Subject: [PATCH] =?UTF-8?q?-=20Added=20native=20confirmation=20sheets=20in?= =?UTF-8?q?=20the=20Mac=20client.=20Manual=20content=20actions=20now=20con?= =?UTF-8?q?firm=20clearly:=20Draft=20shows=20=E2=80=9CDraft=20Saved?= =?UTF-8?q?=E2=80=9D=20Publish=20shows=20=E2=80=9CPublished=E2=80=9D=20Upd?= =?UTF-8?q?ate=20shows=20=E2=80=9CUpdated=E2=80=9D=20Delete=20first=20asks?= =?UTF-8?q?=20=E2=80=9CDelete=20Post/Page=3F=E2=80=9D=20and=20then=20shows?= =?UTF-8?q?=20=E2=80=9CDeleted=E2=80=9D=20after=20the=20API=20succeeds=20A?= =?UTF-8?q?utosave=20stays=20quiet=20so=20it=20does=20not=20spam=20popups.?= =?UTF-8?q?=20Updated:=20[macclient/AppKitClient/main.m](/Users/tyemecliff?= =?UTF-8?q?ord/Documents/GH/blog/macclient/AppKitClient/main.m)=20[macclie?= =?UTF-8?q?nt/README.md](/Users/tyemeclifford/Documents/GH/blog/macclient/?= =?UTF-8?q?README.md)=20[CHANGELOG.md](/Users/tyemeclifford/Documents/GH/b?= =?UTF-8?q?log/CHANGELOG.md)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 4 + README.md | 2 +- macclient/AppKitClient/main.m | 338 +++++++++++++++++++++++-- macclient/README.md | 9 +- macclient/TCMS.app/Contents/Info.plist | 26 ++ macclient/TCMS.app/Contents/MacOS/TCMS | Bin 0 -> 244560 bytes macclient/TCMS.app/Contents/PkgInfo | 1 + macclient/build-app.sh | 24 +- 8 files changed, 366 insertions(+), 38 deletions(-) create mode 100644 macclient/TCMS.app/Contents/Info.plist create mode 100755 macclient/TCMS.app/Contents/MacOS/TCMS create mode 100644 macclient/TCMS.app/Contents/PkgInfo diff --git a/CHANGELOG.md b/CHANGELOG.md index 8feaae3..8a210f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,9 @@ All notable changes to Ty Clifford's Content Management System are documented he - Added a native AppKit macOS 12+ client under `macclient/` for editing posts/pages, uploading media, moderating comments, local autosave, and optional remote draft autosave. - Added Mac client post/page list pagination with configurable per-page counts. - Added Mac client media pagination plus native image preview and audio/video playback. +- Added Mac client editor-screen media upload with automatic Markdown/shortcode insertion. +- Added Mac client Media context-menu actions to copy a file URL or a ready-to-paste Markdown embed. +- Added Mac client confirmation sheets for saving drafts, publishing, updating, and deleting posts/pages. - Added Mac client editor spell-check and auto-correct options. - Added a Mac client Update action for saving existing posts/pages without changing their current draft/published status. - Added a public post lightbox slideshow for images, native videos, video embeds, and direct media links within the same post. @@ -19,6 +22,7 @@ All notable changes to Ty Clifford's Content Management System are documented he ### Changed - Simplified API and Mac client authentication to `.env` username/password only, removing token-based auth. +- Rebranded the native Mac client bundle and menus to `TCMS`. - Fixed Mac client resizing, maximized editor text reflow, startup layout refresh, guarded undo/redo behavior, keyboard focus traversal, and standard Command-key shortcuts including Settings and Update. - Fixed Mac client Update so edited Markdown is read from the live text storage and stale save responses no longer overwrite the editor. - Expanded the API content save endpoint to accept `markdown`, `content`, or `body` payload fields for editor content. diff --git a/README.md b/README.md index 46982f5..414c97d 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ The native AppKit macOS 12+ client lives in `macclient/`. ```bash cd macclient ./build-app.sh -open TCMSMacClient.app +open TCMS.app ``` Point the client at any TCMS site URL. It will call `api.php` at that site for posts, pages, media, comments, local autosave, and optional remote draft autosave. diff --git a/macclient/AppKitClient/main.m b/macclient/AppKitClient/main.m index f946c37..cfbb705 100644 --- a/macclient/AppKitClient/main.m +++ b/macclient/AppKitClient/main.m @@ -72,6 +72,22 @@ static NSString *TCMSFormatBytes(id value) { } @end +@interface TCMSTableView : NSTableView +@end + +@implementation TCMSTableView +- (NSMenu *)menuForEvent:(NSEvent *)event { + NSPoint point = [self convertPoint:event.locationInWindow fromView:nil]; + NSInteger row = [self rowAtPoint:point]; + if (row >= 0) { + [self selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO]; + } else { + return nil; + } + return [super menuForEvent:event]; +} +@end + @interface TCMSAPIClient : NSObject @property (nonatomic, copy) NSString *baseURLString; @property (nonatomic, copy) NSString *username; @@ -270,6 +286,8 @@ static NSString *TCMSFormatBytes(id value) { @property (nonatomic, strong) NSImageView *mediaImageView; @property (nonatomic, strong) AVPlayerView *mediaPlayerView; @property (nonatomic, strong) NSButton *openMediaButton; +@property (nonatomic, strong) NSButton *mediaURLCopyButton; +@property (nonatomic, strong) NSButton *mediaEmbedCopyButton; @property (nonatomic, copy) NSString *mediaPreviewURLString; @property (nonatomic, strong) NSPopUpButton *commentStatusPopup; @property (nonatomic, strong) NSButton *previousPageButton; @@ -413,8 +431,8 @@ static NSString *TCMSFormatBytes(id value) { NSMenuItem *appItem = [NSMenuItem new]; [mainMenu addItem:appItem]; - NSMenu *appMenu = [[NSMenu alloc] initWithTitle:@"TCMS Mac Client"]; - [appMenu addItemWithTitle:@"About TCMS Mac Client" action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; + NSMenu *appMenu = [[NSMenu alloc] initWithTitle:@"TCMS"]; + [appMenu addItemWithTitle:@"About TCMS" action:@selector(orderFrontStandardAboutPanel:) keyEquivalent:@""]; [appMenu addItem:[NSMenuItem separatorItem]]; NSMenuItem *settings = [appMenu addItemWithTitle:@"Settings..." action:@selector(showSettingsFromMenu:) keyEquivalent:@","]; settings.target = self; @@ -425,12 +443,12 @@ static NSString *TCMSFormatBytes(id value) { [appMenu addItem:servicesItem]; NSApp.servicesMenu = servicesMenu; [appMenu addItem:[NSMenuItem separatorItem]]; - [appMenu addItemWithTitle:@"Hide TCMS Mac Client" action:@selector(hide:) keyEquivalent:@"h"]; + [appMenu addItemWithTitle:@"Hide TCMS" action:@selector(hide:) keyEquivalent:@"h"]; NSMenuItem *hideOthers = [appMenu addItemWithTitle:@"Hide Others" action:@selector(hideOtherApplications:) keyEquivalent:@"h"]; hideOthers.keyEquivalentModifierMask = NSEventModifierFlagCommand | NSEventModifierFlagOption; [appMenu addItemWithTitle:@"Show All" action:@selector(unhideAllApplications:) keyEquivalent:@""]; [appMenu addItem:[NSMenuItem separatorItem]]; - [appMenu addItemWithTitle:@"Quit TCMS Mac Client" action:@selector(terminate:) keyEquivalent:@"q"]; + [appMenu addItemWithTitle:@"Quit TCMS" action:@selector(terminate:) keyEquivalent:@"q"]; appItem.submenu = appMenu; NSMenuItem *fileItem = [NSMenuItem new]; @@ -523,6 +541,8 @@ static NSString *TCMSFormatBytes(id value) { self.mediaImageView = nil; self.mediaPlayerView = nil; self.openMediaButton = nil; + self.mediaURLCopyButton = nil; + self.mediaEmbedCopyButton = nil; self.mediaPreviewURLString = nil; } @@ -534,12 +554,13 @@ static NSString *TCMSFormatBytes(id value) { NSTextField *heading = [self label:[section capitalizedString] frame:NSMakeRect(20, 690, 180, 28) font:[NSFont boldSystemFontOfSize:24]]; [self.workspace addSubview:heading]; - [self addButton:@"Refresh" frame:NSMakeRect(210, 690, 90, 30) action:@selector(refreshCurrentSection)]; - [self addButton:@"New" frame:NSMakeRect(310, 690, 70, 30) action:@selector(newContent)]; - [self addButton:@"Save Draft" frame:NSMakeRect(390, 690, 100, 30) action:@selector(saveDraft)]; - [self addButton:@"Publish" frame:NSMakeRect(500, 690, 90, 30) action:@selector(publishContent)]; - [self addButton:@"Update" frame:NSMakeRect(600, 690, 80, 30) action:@selector(updateContent)]; - [self addButton:@"Delete" frame:NSMakeRect(690, 690, 80, 30) action:@selector(deleteContent)]; + [self addButton:@"Refresh" frame:NSMakeRect(210, 690, 78, 30) action:@selector(refreshCurrentSection)]; + [self addButton:@"New" frame:NSMakeRect(296, 690, 58, 30) action:@selector(newContent)]; + [self addButton:@"Draft" frame:NSMakeRect(362, 690, 70, 30) action:@selector(saveDraft)]; + [self addButton:@"Update" frame:NSMakeRect(440, 690, 76, 30) action:@selector(updateContent)]; + [self addButton:@"Publish" frame:NSMakeRect(524, 690, 78, 30) action:@selector(publishContent)]; + [self addButton:@"Upload Media" frame:NSMakeRect(610, 690, 118, 30) action:@selector(uploadEditorMedia)]; + [self addButton:@"Delete" frame:NSMakeRect(736, 690, 70, 30) action:@selector(deleteContent)]; NSScrollView *listScroll = [self buildTableWithFrame:NSMakeRect(20, 56, 280, 614) columns:@[@"title", @"status"]]; listScroll.autoresizingMask = NSViewHeightSizable | NSViewMaxXMargin; @@ -649,15 +670,20 @@ static NSString *TCMSFormatBytes(id value) { [self clearWorkspace]; self.contentListPage = 1; [self.workspace addSubview:[self label:@"Media" frame:NSMakeRect(20, 690, 180, 28) font:[NSFont boldSystemFontOfSize:24]]]; - [self addButton:@"Refresh" frame:NSMakeRect(210, 690, 90, 30) action:@selector(refreshCurrentSection)]; - [self addButton:@"Upload" frame:NSMakeRect(310, 690, 90, 30) action:@selector(uploadMedia)]; - self.openMediaButton = [self addButton:@"Open" frame:NSMakeRect(410, 690, 80, 30) action:@selector(openSelectedMedia:)]; + [self addButton:@"Refresh" frame:NSMakeRect(210, 690, 78, 30) action:@selector(refreshCurrentSection)]; + [self addButton:@"Upload" frame:NSMakeRect(296, 690, 78, 30) action:@selector(uploadMedia)]; + self.openMediaButton = [self addButton:@"Open" frame:NSMakeRect(382, 690, 66, 30) action:@selector(openSelectedMedia:)]; self.openMediaButton.enabled = NO; + self.mediaURLCopyButton = [self addButton:@"Copy URL" frame:NSMakeRect(456, 690, 88, 30) action:@selector(copySelectedMediaURL:)]; + self.mediaURLCopyButton.enabled = NO; + self.mediaEmbedCopyButton = [self addButton:@"Copy Embed" frame:NSMakeRect(552, 690, 104, 30) action:@selector(copySelectedMediaEmbed:)]; + self.mediaEmbedCopyButton.enabled = NO; NSScrollView *mediaScroll = [self buildTableWithFrame:NSMakeRect(20, 56, 420, 614) columns:@[@"name", @"mime", @"size"]]; mediaScroll.autoresizingMask = NSViewHeightSizable | NSViewMaxXMargin; self.tableView.target = self; self.tableView.doubleAction = @selector(openSelectedMedia:); + [self configureMediaContextMenu]; self.previousPageButton = [NSButton buttonWithTitle:@"Previous" target:self action:@selector(previousContentPage)]; self.previousPageButton.frame = NSMakeRect(20, 20, 78, 28); @@ -791,7 +817,7 @@ static NSString *TCMSFormatBytes(id value) { NSScrollView *scroll = [[NSScrollView alloc] initWithFrame:frame]; scroll.borderType = NSBezelBorder; scroll.hasVerticalScroller = YES; - self.tableView = [[NSTableView alloc] initWithFrame:scroll.bounds]; + self.tableView = [[TCMSTableView alloc] initWithFrame:scroll.bounds]; self.tableView.delegate = self; self.tableView.dataSource = self; self.tableView.columnAutoresizingStyle = NSTableViewUniformColumnAutoresizingStyle; @@ -996,6 +1022,9 @@ static NSString *TCMSFormatBytes(id value) { if (action == @selector(updateContent) || action == @selector(saveDraft) || action == @selector(publishContent)) { return [self isContentSection] && self.markdownView != nil; } + if (action == @selector(copySelectedMediaURL:) || action == @selector(copySelectedMediaEmbed:) || action == @selector(openSelectedMedia:)) { + return [self.section isEqualToString:@"media"] && [self selectedTableItem] != nil; + } return YES; } @@ -1145,20 +1174,73 @@ static NSString *TCMSFormatBytes(id value) { return item; } +- (NSString *)contentKindForItem:(NSDictionary *)item capitalized:(BOOL)capitalized { + NSString *type = [TCMSString(item[@"type"]) lowercaseString]; + NSString *kind = [type isEqualToString:@"page"] ? @"page" : @"post"; + return capitalized ? [kind capitalizedString] : kind; +} + +- (NSString *)contentTitleForItem:(NSDictionary *)item { + NSString *title = TCMSString(item[@"title"]); + if (title.length == 0) { + title = TCMSString(item[@"slug"]); + } + return title.length > 0 ? title : @"Untitled"; +} + +- (NSString *)confirmationMessageForItem:(NSDictionary *)item action:(NSString *)action { + NSString *kind = [self contentKindForItem:item capitalized:YES]; + NSString *title = [self contentTitleForItem:item]; + return [NSString stringWithFormat:@"%@ \"%@\" was %@.", kind, title, action]; +} + +- (void)showConfirmationWithTitle:(NSString *)title message:(NSString *)message { + NSAlert *alert = [NSAlert new]; + alert.alertStyle = NSAlertStyleInformational; + alert.messageText = title.length > 0 ? title : @"Done"; + alert.informativeText = message.length > 0 ? message : @"The action completed successfully."; + [alert addButtonWithTitle:@"OK"]; + if (self.window) { + [alert beginSheetModalForWindow:self.window completionHandler:nil]; + } else { + [alert runModal]; + } +} + +- (void)confirmDestructiveActionWithTitle:(NSString *)title message:(NSString *)message confirmButton:(NSString *)confirmButton completion:(void (^)(BOOL confirmed))completion { + NSAlert *alert = [NSAlert new]; + alert.alertStyle = NSAlertStyleWarning; + alert.messageText = title.length > 0 ? title : @"Confirm"; + alert.informativeText = message.length > 0 ? message : @"This action cannot be undone."; + NSButton *primary = [alert addButtonWithTitle:confirmButton.length > 0 ? confirmButton : @"Delete"]; + primary.keyEquivalent = @"\r"; + [alert addButtonWithTitle:@"Cancel"]; + void (^handler)(NSModalResponse) = ^(NSModalResponse response) { + if (completion) { + completion(response == NSAlertFirstButtonReturn); + } + }; + if (self.window) { + [alert beginSheetModalForWindow:self.window completionHandler:handler]; + } else { + handler([alert runModal]); + } +} + - (void)saveDraft { - [self saveContentWithStatus:@"draft" message:@"Draft saved."]; + [self saveContentWithStatus:@"draft" message:@"Draft saved." confirmationTitle:@"Draft Saved" confirmationAction:@"saved as a draft"]; } - (void)publishContent { - [self saveContentWithStatus:@"published" message:@"Content published."]; + [self saveContentWithStatus:@"published" message:@"Content published." confirmationTitle:@"Published" confirmationAction:@"published"]; } - (void)saveContentWithStatus:(NSString *)status { - [self saveContentWithStatus:status message:@"Content saved."]; + [self saveContentWithStatus:status message:@"Content saved." confirmationTitle:nil confirmationAction:nil]; } - (void)updateContent { - [self saveContentWithStatus:nil message:@"Content updated."]; + [self saveContentWithStatus:nil message:@"Content updated." confirmationTitle:@"Updated" confirmationAction:@"updated"]; } - (NSString *)currentEditorMarkdown { @@ -1172,7 +1254,7 @@ static NSString *TCMSFormatBytes(id value) { return self.markdownView.string ?: @""; } -- (void)saveContentWithStatus:(NSString *)status message:(NSString *)message { +- (void)saveContentWithStatus:(NSString *)status message:(NSString *)message confirmationTitle:(NSString *)confirmationTitle confirmationAction:(NSString *)confirmationAction { if (![self isContentSection] || !self.markdownView) { [self setStatus:@"Open Posts or Pages to save content."]; return; @@ -1204,23 +1286,36 @@ static NSString *TCMSFormatBytes(id value) { [self loadEditorFields]; [self refreshContentType:TCMSString(self.editorItem[@"type"]).length ? TCMSString(self.editorItem[@"type"]) : @"post"]; [self setStatus:serverEchoedSubmittedMarkdown ? (message ?: @"Content saved.") : @"Server response did not include the updated Markdown. Editor changes preserved."]; + if (serverEchoedSubmittedMarkdown && confirmationTitle.length > 0) { + [self showConfirmationWithTitle:confirmationTitle message:[self confirmationMessageForItem:self.editorItem action:confirmationAction ?: @"saved"]]; + } }]; } - (void)deleteContent { - NSString *slug = TCMSString(self.editorItem[@"slug"]); + NSDictionary *item = [self.editorItem copy] ?: @{}; + NSString *slug = TCMSString(item[@"slug"]); if (slug.length == 0) { [self setStatus:@"Nothing selected to delete."]; return; } - [self.client requestAction:@"content.delete" query:@{} method:@"POST" body:@{@"slug": slug} completion:^(NSDictionary *json, NSError *error) { - if (error) { - [self setStatus:error.localizedDescription]; + NSString *kind = [self contentKindForItem:item capitalized:YES]; + NSString *title = [self contentTitleForItem:item]; + NSString *message = [NSString stringWithFormat:@"Delete \"%@\" from the server? This cannot be undone.", title]; + [self confirmDestructiveActionWithTitle:[NSString stringWithFormat:@"Delete %@?", kind] message:message confirmButton:@"Delete" completion:^(BOOL confirmed) { + if (!confirmed) { return; } - [self setStatus:@"Content deleted."]; - [self newContent]; - [self refreshCurrentSection]; + [self.client requestAction:@"content.delete" query:@{} method:@"POST" body:@{@"slug": slug} completion:^(NSDictionary *json, NSError *error) { + if (error) { + [self setStatus:error.localizedDescription]; + return; + } + [self setStatus:@"Content deleted."]; + [self newContent]; + [self refreshCurrentSection]; + [self showConfirmationWithTitle:@"Deleted" message:[self confirmationMessageForItem:item action:@"deleted"]]; + }]; }]; } @@ -1237,7 +1332,7 @@ static NSString *TCMSFormatBytes(id value) { }]; } -- (void)uploadMedia { +- (void)chooseAndUploadMediaWithCompletion:(void (^)(NSDictionary *item))completion { NSOpenPanel *panel = [NSOpenPanel openPanel]; panel.canChooseDirectories = NO; panel.canChooseFiles = YES; @@ -1250,11 +1345,35 @@ static NSString *TCMSFormatBytes(id value) { [self setStatus:error.localizedDescription]; return; } + NSDictionary *item = [json[@"item"] isKindOfClass:[NSDictionary class]] ? json[@"item"] : @{}; + completion(item); + }]; +} + +- (void)uploadMedia { + [self chooseAndUploadMediaWithCompletion:^(NSDictionary *item) { [self setStatus:@"Media uploaded."]; [self refreshMedia]; }]; } +- (void)uploadEditorMedia { + if (![self isContentSection] || !self.markdownView) { + [self setStatus:@"Open Posts or Pages to insert media."]; + return; + } + + [self chooseAndUploadMediaWithCompletion:^(NSDictionary *item) { + NSString *snippet = [self mediaMarkdownEmbedForItem:item]; + if (snippet.length == 0) { + [self setStatus:@"Media uploaded, but no embed could be generated."]; + return; + } + [self insertMarkdownSnippet:snippet]; + [self setStatus:@"Media uploaded and inserted."]; + }]; +} + - (NSURL *)absoluteURLForMediaItem:(NSDictionary *)item { NSString *url = TCMSString(item[@"url"]); if (url.length == 0) { @@ -1263,6 +1382,165 @@ static NSString *TCMSFormatBytes(id value) { return [self.client absoluteURLForPath:url]; } +- (NSString *)mediaEmbedURLForItem:(NSDictionary *)item { + NSString *url = TCMSString(item[@"url"]); + if (url.length == 0) { + url = TCMSString(item[@"path"]); + } + return url; +} + +- (NSString *)mediaTitleForItem:(NSDictionary *)item { + NSString *name = TCMSString(item[@"name"]); + if (name.length == 0) { + name = TCMSString(item[@"path"]).lastPathComponent; + } + NSString *base = name.stringByDeletingPathExtension; + return base.length > 0 ? base : name; +} + +- (BOOL)mediaItem:(NSDictionary *)item hasMimePrefix:(NSString *)prefix extensions:(NSArray *)extensions { + NSString *mime = [TCMSString(item[@"mime"]) lowercaseString]; + if ([mime hasPrefix:prefix]) { + return YES; + } + NSString *extension = [[TCMSString(item[@"name"]).pathExtension lowercaseString] stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet]; + if (extension.length == 0) { + extension = [[TCMSString(item[@"path"]).pathExtension lowercaseString] stringByTrimmingCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet]; + } + return [extensions containsObject:extension]; +} + +- (BOOL)isImageMediaItem:(NSDictionary *)item { + return [self mediaItem:item hasMimePrefix:@"image/" extensions:@[@"avif", @"bmp", @"gif", @"jpeg", @"jpg", @"png", @"svg", @"webp"]]; +} + +- (BOOL)isVideoMediaItem:(NSDictionary *)item { + return [self mediaItem:item hasMimePrefix:@"video/" extensions:@[@"m4v", @"mov", @"mp4", @"ogv", @"ogg", @"webm"]]; +} + +- (BOOL)isAudioMediaItem:(NSDictionary *)item { + return [self mediaItem:item hasMimePrefix:@"audio/" extensions:@[@"aac", @"aif", @"aiff", @"flac", @"m4a", @"mp3", @"oga", @"ogg", @"wav", @"weba"]]; +} + +- (NSString *)markdownSafeLabel:(NSString *)value { + NSString *label = [TCMSString(value) stringByReplacingOccurrencesOfString:@"\n" withString:@" "]; + label = [label stringByReplacingOccurrencesOfString:@"[" withString:@"("]; + label = [label stringByReplacingOccurrencesOfString:@"]" withString:@")"]; + return label.length > 0 ? label : @"media"; +} + +- (NSString *)shortcodeSafeValue:(NSString *)value { + NSString *clean = [TCMSString(value) stringByReplacingOccurrencesOfString:@"\"" withString:@"%22"]; + clean = [clean stringByReplacingOccurrencesOfString:@"\n" withString:@""]; + return clean; +} + +- (NSString *)mediaMarkdownEmbedForItem:(NSDictionary *)item { + NSString *url = [self mediaEmbedURLForItem:item]; + if (url.length == 0) { + return @""; + } + + NSString *title = [self markdownSafeLabel:[self mediaTitleForItem:item]]; + if ([self isImageMediaItem:item]) { + return [NSString stringWithFormat:@"![%@](%@)", title, url]; + } + if ([self isVideoMediaItem:item]) { + return [NSString stringWithFormat:@"[video file=\"%@\"]", [self shortcodeSafeValue:url]]; + } + if ([self isAudioMediaItem:item]) { + return [NSString stringWithFormat:@"", [self shortcodeSafeValue:url]]; + } + return [NSString stringWithFormat:@"[%@](%@)", title, url]; +} + +- (void)insertMarkdownSnippet:(NSString *)snippet { + if (!self.markdownView || snippet.length == 0) { + return; + } + + NSString *current = self.markdownView.string ?: @""; + NSRange range = self.markdownView.selectedRange; + if (range.location == NSNotFound || range.location > current.length) { + range = NSMakeRange(current.length, 0); + } else if (NSMaxRange(range) > current.length) { + range.length = current.length - range.location; + } + + NSString *prefix = @""; + NSString *suffix = @""; + if (range.location > 0) { + NSString *before = [current substringToIndex:range.location]; + if (![before hasSuffix:@"\n\n"]) { + prefix = [before hasSuffix:@"\n"] ? @"\n" : @"\n\n"; + } + } + NSUInteger afterLocation = MIN(NSMaxRange(range), current.length); + if (afterLocation < current.length) { + NSString *after = [current substringFromIndex:afterLocation]; + if (![after hasPrefix:@"\n\n"]) { + suffix = [after hasPrefix:@"\n"] ? @"\n" : @"\n\n"; + } + } else { + suffix = @"\n"; + } + + NSString *insert = [NSString stringWithFormat:@"%@%@%@", prefix, snippet, suffix]; + if ([self.markdownView shouldChangeTextInRange:range replacementString:insert]) { + [self.markdownView.textStorage replaceCharactersInRange:range withString:insert]; + [self.markdownView didChangeText]; + [self.markdownView setSelectedRange:NSMakeRange(range.location + prefix.length + snippet.length, 0)]; + } + [self.window makeFirstResponder:self.markdownView]; + [self markDirty]; +} + +- (void)configureMediaContextMenu { + NSMenu *menu = [[NSMenu alloc] initWithTitle:@"Media"]; + NSMenuItem *copyURL = [[NSMenuItem alloc] initWithTitle:@"Copy URL" action:@selector(copySelectedMediaURL:) keyEquivalent:@""]; + copyURL.target = self; + [menu addItem:copyURL]; + NSMenuItem *copyEmbed = [[NSMenuItem alloc] initWithTitle:@"Copy Markdown Embed" action:@selector(copySelectedMediaEmbed:) keyEquivalent:@""]; + copyEmbed.target = self; + [menu addItem:copyEmbed]; + [menu addItem:[NSMenuItem separatorItem]]; + NSMenuItem *open = [[NSMenuItem alloc] initWithTitle:@"Open" action:@selector(openSelectedMedia:) keyEquivalent:@""]; + open.target = self; + [menu addItem:open]; + self.tableView.menu = menu; +} + +- (void)copyTextToPasteboard:(NSString *)text status:(NSString *)status { + if (text.length == 0) { + [self setStatus:@"Nothing to copy."]; + return; + } + NSPasteboard *pasteboard = NSPasteboard.generalPasteboard; + [pasteboard clearContents]; + [pasteboard setString:text forType:NSPasteboardTypeString]; + [self setStatus:status]; +} + +- (void)copySelectedMediaURL:(id)sender { + NSDictionary *item = [self selectedTableItem]; + if (!item) { + [self setStatus:@"Select a media item first."]; + return; + } + NSURL *url = [self absoluteURLForMediaItem:item]; + [self copyTextToPasteboard:url.absoluteString ?: [self mediaEmbedURLForItem:item] status:@"Media URL copied."]; +} + +- (void)copySelectedMediaEmbed:(id)sender { + NSDictionary *item = [self selectedTableItem]; + if (!item) { + [self setStatus:@"Select a media item first."]; + return; + } + [self copyTextToPasteboard:[self mediaMarkdownEmbedForItem:item] status:@"Markdown embed copied."]; +} + - (NSString *)mediaDetailForItem:(NSDictionary *)item { NSMutableArray *parts = [NSMutableArray array]; NSString *mime = TCMSString(item[@"mime"]); @@ -1288,6 +1566,8 @@ static NSString *TCMSFormatBytes(id value) { self.mediaImageView.hidden = YES; self.mediaPreviewURLString = nil; self.openMediaButton.enabled = NO; + self.mediaURLCopyButton.enabled = NO; + self.mediaEmbedCopyButton.enabled = NO; self.mediaPreviewLabel.stringValue = @"No media selected"; self.mediaDetailLabel.stringValue = @""; } @@ -1304,6 +1584,8 @@ static NSString *TCMSFormatBytes(id value) { NSString *urlString = url.absoluteString ?: @""; self.mediaPreviewURLString = urlString; self.openMediaButton.enabled = YES; + self.mediaURLCopyButton.enabled = YES; + self.mediaEmbedCopyButton.enabled = YES; self.mediaPreviewLabel.stringValue = TCMSString(item[@"name"]).length ? TCMSString(item[@"name"]) : url.lastPathComponent; self.mediaDetailLabel.stringValue = [self mediaDetailForItem:item]; self.mediaImageView.image = nil; @@ -1455,7 +1737,7 @@ static NSString *TCMSFormatBytes(id value) { return; } NSURL *base = [NSFileManager.defaultManager URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask].firstObject; - NSURL *folder = [base URLByAppendingPathComponent:@"TCMS Mac Client/Drafts" isDirectory:YES]; + NSURL *folder = [base URLByAppendingPathComponent:@"TCMS/Drafts" isDirectory:YES]; [NSFileManager.defaultManager createDirectoryAtURL:folder withIntermediateDirectories:YES attributes:nil error:nil]; NSString *name = TCMSString(item[@"slug"]).length ? TCMSString(item[@"slug"]) : TCMSString(item[@"title"]); name = [name stringByReplacingOccurrencesOfString:@"[^A-Za-z0-9._-]+" withString:@"-" options:NSRegularExpressionSearch range:NSMakeRange(0, name.length)]; diff --git a/macclient/README.md b/macclient/README.md index 6fe9211..ce0b708 100644 --- a/macclient/README.md +++ b/macclient/README.md @@ -1,4 +1,4 @@ -# TCMS Mac Client +# TCMS Native AppKit macOS 12+ client for Ty Clifford's Content Management System. @@ -7,10 +7,10 @@ Native AppKit macOS 12+ client for Ty Clifford's Content Management System. ```bash cd macclient ./build-app.sh -open TCMSMacClient.app +open TCMS.app ``` -The built app bundle is written to `macclient/TCMSMacClient.app`. +The built app bundle is written to `macclient/TCMS.app`. ## Connect @@ -29,8 +29,11 @@ The client automatically calls `api.php` under that URL. Enter the username/pass - Page through large post/page lists with configurable per-page counts. - Toggle spell check and auto-correct in the Markdown editor. - Use standard Mac shortcuts, including Command-S for Update, Command-Comma for Settings, and Command-Q for Quit. +- Confirm successful draft, publish, update, and delete actions with native sheets. - Upload media to `bl-content/uploads`. - Page through media, preview images, play audio/video, and open files in the default Mac app. +- Upload media from the editor and insert the correct Markdown image, video shortcode, audio tag, or link automatically. +- Right-click media to copy its URL or a ready-to-paste Markdown embed. - List and moderate comments. - Local autosave to Application Support. - Optional remote autosave as draft. diff --git a/macclient/TCMS.app/Contents/Info.plist b/macclient/TCMS.app/Contents/Info.plist new file mode 100644 index 0000000..404a816 --- /dev/null +++ b/macclient/TCMS.app/Contents/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + TCMS + CFBundleIdentifier + com.tyclifford.tcms.macclient + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + TCMS + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + LSMinimumSystemVersion + 12.0 + NSHighResolutionCapable + + + diff --git a/macclient/TCMS.app/Contents/MacOS/TCMS b/macclient/TCMS.app/Contents/MacOS/TCMS new file mode 100755 index 0000000000000000000000000000000000000000..4de4dd554e75b4fb28f0e573c563819b9697e097 GIT binary patch literal 244560 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

{O>J%FYvRielY<2s}_Idpvbq^?J9mN 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

ul$Np@|q88*7)T4J8ECw#TyB^?r+= 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 "$APP/Contents/PkgInfo" +build_app() { + app="$1" + mkdir -p "$app/Contents/MacOS" "$app/Contents/Resources" + rm -f "$app/Contents/MacOS"/* + cp "$ROOT/AppKitClient/Info.plist" "$app/Contents/Info.plist" + /usr/bin/clang -fobjc-arc -mmacosx-version-min=12.0 -framework Cocoa -framework AVKit -framework AVFoundation "$SRC" -o "$app/Contents/MacOS/$EXECUTABLE" + printf 'APPL????' > "$app/Contents/PkgInfo" +} -echo "Built $APP" +build_app "$PRIMARY_APP" + +if [ -d "$LEGACY_APP" ]; then + build_app "$LEGACY_APP" + echo "Updated legacy bundle $LEGACY_APP" +fi + +echo "Built $PRIMARY_APP"