mirror of
https://github.com/kunkundi/crossdesk.git
synced 2026-11-13 20:25:53 +08:00
[feat] add feedback dialog and diagnostic log export, refs #149
This commit is contained in:
1 parent
6a8e79d4a9
commit
097add9397
14 files changed
+731
-10
No files matched your search
@@ -1,6 +1,7 @@
|
||||
#include "platform/window_drag.h"
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
#import <UniformTypeIdentifiers/UniformTypeIdentifiers.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
@@ -46,9 +47,10 @@ NSApplicationPresentationOptions stream_restore_presentation_options =
|
||||
struct FileDialogRequest {
|
||||
std::string title;
|
||||
std::function<void(std::string)> completion;
|
||||
std::string filename;
|
||||
};
|
||||
std::shared_ptr<FileDialogRequest> file_dialog_request;
|
||||
NSOpenPanel *file_dialog = nil;
|
||||
NSSavePanel *file_dialog = nil;
|
||||
NSOpenPanel *prepared_file_dialog = nil;
|
||||
uint64_t file_dialog_prepare_generation = 0;
|
||||
|
||||
@@ -500,12 +502,47 @@ void OpenNativeFileDialog(const std::string& title,
|
||||
});
|
||||
}
|
||||
|
||||
void SaveNativeFileDialog(const std::string& title, const std::string& filename,
|
||||
std::function<void(std::string)> completion) {
|
||||
if (file_dialog_request) { completion({}); return; }
|
||||
const auto request = std::make_shared<FileDialogRequest>(
|
||||
FileDialogRequest{title, std::move(completion), filename});
|
||||
file_dialog_request = request;
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (file_dialog_request != request) return;
|
||||
NSSavePanel *panel = [NSSavePanel savePanel];
|
||||
file_dialog = panel;
|
||||
panel.title = [NSString stringWithUTF8String:request->title.c_str()];
|
||||
panel.nameFieldStringValue = [NSString stringWithUTF8String:request->filename.c_str()];
|
||||
panel.allowedContentTypes = @[UTTypeZIP];
|
||||
panel.allowsOtherFileTypes = NO;
|
||||
panel.canCreateDirectories = YES;
|
||||
[NSApp activateIgnoringOtherApps:YES];
|
||||
NSWindow *owner = NSApp.keyWindow ?: NSApp.mainWindow;
|
||||
CenterWindowOnScreen(panel, owner.screen ?: NSScreen.mainScreen);
|
||||
__weak NSSavePanel *weak_panel = panel;
|
||||
[panel beginWithCompletionHandler:^(NSModalResponse result) {
|
||||
if (file_dialog_request != request) return;
|
||||
NSSavePanel *finished_panel = weak_panel;
|
||||
const char *selected = result == NSModalResponseOK
|
||||
? finished_panel.URL.fileSystemRepresentation : nullptr;
|
||||
const std::string path = selected ? selected : "";
|
||||
[finished_panel orderOut:nil];
|
||||
file_dialog = nil;
|
||||
file_dialog_request.reset();
|
||||
auto finished = std::move(request->completion);
|
||||
finished(path);
|
||||
}];
|
||||
if (file_dialog_request == request) [panel makeKeyAndOrderFront:nil];
|
||||
});
|
||||
}
|
||||
|
||||
void CancelNativeFileDialog() {
|
||||
++file_dialog_prepare_generation;
|
||||
prepared_file_dialog = nil;
|
||||
const auto request = std::move(file_dialog_request);
|
||||
if (!request) return;
|
||||
NSOpenPanel *panel = file_dialog;
|
||||
NSSavePanel *panel = file_dialog;
|
||||
file_dialog = nil;
|
||||
[panel cancel:nil];
|
||||
[panel orderOut:nil];
|
||||
|
||||
@@ -62,6 +62,9 @@ void PrepareNativeFileDialog();
|
||||
// nested modal loop. Completion receives an empty path on cancel or failure.
|
||||
void OpenNativeFileDialog(const std::string& title,
|
||||
std::function<void(std::string)> completion);
|
||||
// Asynchronous ZIP destination picker with native overwrite confirmation.
|
||||
void SaveNativeFileDialog(const std::string& title, const std::string& filename,
|
||||
std::function<void(std::string)> completion);
|
||||
// Cancels an open or pending picker, completes it once with an empty path, and
|
||||
// releases the cached panel and pending initialization during application exit.
|
||||
void CancelNativeFileDialog();
|
||||
|
||||
Reference in new issue
Block a user