Skip to content
Merged
41 changes: 36 additions & 5 deletions Shared/Sources/Document/Documents/iCloudContainer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,40 @@

import Foundation

let containerId = "iCloud.com.akaDuality.VoiceOver-Designer"
public let containerId = "iCloud.com.akaDuality.VoiceOver-Designer"

public let iCloudContainer = //( FileManager.default.url(forUbiquityContainerIdentifier: containerId)
// ??
FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! // When iCloud is disabled
.appendingPathComponent("Documents")
private let fileManager = FileManager.default

public let iCloudContainer: URL = {
#if DEBUG
print("Use documents directory in DEBUG")
return documentDirectory
#else
print("Use \(iCloudDirectory != nil ? "cloud" : "documents") directory in RELEASE")
return iCloudDirectory ?? documentDirectory // When iCloud is disabled
#endif
}()

private var iCloudDirectory: URL? {
let url = fileManager
.url(forUbiquityContainerIdentifier: containerId)

if #available(macOS 13.0, iOS 16.0, *) {
return url?.appending(path: "Documents")
} else {
guard let string = url?.absoluteString else {
return nil
}

if string.hasSuffix("/") {
return URL(string: string + "Documents")
} else {
return URL(string: string + "/Documents")
}
}
}

private var documentDirectory: URL {
fileManager
.urls(for: .documentDirectory, in: .userDomainMask).first!
}
140 changes: 136 additions & 4 deletions VoiceOver Designer.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -510,10 +510,7 @@
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_PREPROCESSOR_DEFINITIONS = "";
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
Expand Down Expand Up @@ -568,6 +565,7 @@
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_PREPROCESSOR_DEFINITIONS = "";
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
Expand Down Expand Up @@ -697,6 +695,136 @@
};
name = Release;
};
1E94697A296835BA00FFAEE7 /* Cloud */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = "";
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 12.3;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Cloud;
};
1E94697B296835BA00FFAEE7 /* Cloud */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = "VoiceOver Designer/VoiceOver DesignerRelease.entitlements";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = P67Q4Q7HA9;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "VoiceOver-Designer-Info.plist";
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.developer-tools";
INFOPLIST_KEY_NSHumanReadableCopyright = "";
INFOPLIST_KEY_NSPrincipalClass = NSApplication;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 12.0;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.akaDuality.VoiceOver-Designer";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
};
name = Cloud;
};
1E94697C296835BA00FFAEE7 /* Cloud */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_ENTITLEMENTS = MacOSPreview/MacOSPreview.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 3;
DEVELOPMENT_TEAM = P67Q4Q7HA9;
ENABLE_HARDENED_RUNTIME = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = MacOSPreview/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = MacOSPreview;
INFOPLIST_KEY_NSHumanReadableCopyright = "";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@executable_path/../../../../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 10.15;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.akaDuality.VoiceOver-Designer.MacOSPreview";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
};
name = Cloud;
};
1E94697D296835BA00FFAEE7 /* Cloud */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = "";
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = com.akaDuality.VoiceOverDesignerUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TEST_TARGET_NAME = "VoiceOver Designer";
};
name = Cloud;
};
1EA7411E28B2683000D6CAA4 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
Expand Down Expand Up @@ -736,6 +864,7 @@
isa = XCConfigurationList;
buildConfigurations = (
1E1D8010281D5CC000B64954 /* Debug */,
1E94697A296835BA00FFAEE7 /* Cloud */,
1E1D8011281D5CC000B64954 /* Release */,
);
defaultConfigurationIsVisible = 0;
Expand All @@ -745,6 +874,7 @@
isa = XCConfigurationList;
buildConfigurations = (
1E1D8013281D5CC000B64954 /* Debug */,
1E94697B296835BA00FFAEE7 /* Cloud */,
1E1D8014281D5CC000B64954 /* Release */,
);
defaultConfigurationIsVisible = 0;
Expand All @@ -754,6 +884,7 @@
isa = XCConfigurationList;
buildConfigurations = (
1E7555CF2895918400024714 /* Debug */,
1E94697C296835BA00FFAEE7 /* Cloud */,
1E7555D02895918400024714 /* Release */,
);
defaultConfigurationIsVisible = 0;
Expand All @@ -763,6 +894,7 @@
isa = XCConfigurationList;
buildConfigurations = (
1EA7411E28B2683000D6CAA4 /* Debug */,
1E94697D296835BA00FFAEE7 /* Cloud */,
1EA7411F28B2683000D6CAA4 /* Release */,
);
defaultConfigurationIsVisible = 0;
Expand Down
19 changes: 10 additions & 9 deletions VoiceOver Designer/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,18 @@ class AppDelegate: NSObject, NSApplicationDelegate {
func applicationDidFinishLaunching(_ aNotification: Notification) {
windowManager.start()
NSApplication.shared.mainMenu = MainMenu.menu()
openFileIfNeeded()
}

private func openFileIfNeeded() {

#if DEBUG
// UI-testing simulation for file openning
guard let path = ProcessInfo.processInfo.environment["DocumentURL"] else { return }
guard !path.isEmpty else { return }
openFileForUITestIfNeeded()

func openFileForUITestIfNeeded() {
// UI-testing simulation for file openning
guard let path = ProcessInfo.processInfo.environment["DocumentURL"] else { return }
guard !path.isEmpty else { return }

let url = URL(fileURLWithPath: path)
openFile(url: url)
let url = URL(fileURLWithPath: path)
openFile(url: url)
}
#endif
}

Expand Down
87 changes: 35 additions & 52 deletions VoiceOver Designer/Documents/WindowManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,32 @@ class WindowManager: NSObject {

static var shared = WindowManager()

var documentWindows: [NSWindow] = []
lazy var projectsWindowController: RecentWindowController = .fromStoryboard(delegate: self)
let recentPresenter = RecentPresenter()
lazy var projectsWindowController: RecentWindowController = {
RecentWindowController.fromStoryboard(delegate: self, presenter: recentPresenter)
}()

private var newDocumentIsCreated = false

func start() {
if documentWindows.isEmpty {
if hasRecentDocuments {
showDocumentSelector()
} else {
showNewDocument()
}
if newDocumentIsCreated {
// Document has been created from [NSDocumentController openUntitledDocumentAndDisplay:error:]
return
}
if recentPresenter.shouldShowThisController {
showDocumentSelector()
} else {
// Do nothing, the user open document directly
// TODO: Do we need it or document will open automatically?
showNewDocument()
}
}

private var hasRecentDocuments: Bool {
!VODocumentController.shared.recentDocumentURLs.isEmpty
}

private func showNewDocument() {
createNewDocumentWindow(document: VODesignDocument())
}

private func showDocumentSelector() {
projectsWindowController.embedProjectsViewControllerInWindow()
projectsWindowController.window?.makeKeyAndOrderFront(self)
}

Expand All @@ -38,54 +40,35 @@ class WindowManager: NSObject {
}
}

extension WindowManager: NSWindowDelegate {
func windowWillClose(_ notification: Notification) {
guard let window = notification.object as? NSWindow else { return }

guard let index = documentWindows.firstIndex(of: window) else {
return // Project windows, for example
}

documentWindows.remove(at: index) // Remove refernce to realase

guard documentWindows.isEmpty else { return }

projectsWindowController.restoreProjectsWindow()
}
}

extension WindowManager: RecentDelegate {
func createNewDocumentWindow(
document: VODesignDocument
) {
presentWindow(for: document)
print("will open \(document.fileURL)")
newDocumentIsCreated = true

hideDocumentSelector()
}

private func presentWindow(for document: VODesignDocument) {
let window = window(for: document)

let windowContorller = RecentWindowController(window: window)
document.addWindowController(windowContorller)

window.makeKeyAndOrderFront(window)
documentWindows.append(window)
}

private func window(for document: VODesignDocument) -> NSWindow {
let split = ProjectController(document: document)

let window = NSWindow(contentViewController: split)
window.delegate = self
let split = ProjectController(document: document, router: self)

let window = projectsWindowController.window!
window.title = document.displayName
window.toolbar = split.toolbar
window.styleMask.formUnion(.fullSizeContentView)

let toolbar: NSToolbar = NSToolbar()
toolbar.delegate = split
window.toolbar = toolbar
window.contentViewController = split

document.addWindowController(projectsWindowController)
}
}

extension WindowManager: ProjectRouterDelegate {
func closeProject(document: NSDocument) {
document.removeWindowController(projectsWindowController)

let window = projectsWindowController.window!
window.title = NSLocalizedString("VoiceOver Designer", comment: "")

window.toolbar = NSToolbar() // Resent toolbar

return window
projectsWindowController.embedProjectsViewControllerInWindow()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -135,10 +135,6 @@ public class CanvasViewController: NSViewController {
self.highlightedControl = control

control.isHiglighted = true




}

func location(from event: NSEvent) -> CGPoint {
Expand Down
Loading