From dab20b5f02baf9afb6a79331ff7fdeeef434a0d3 Mon Sep 17 00:00:00 2001 From: Nobuhiro Ito Date: Sat, 10 Aug 2024 17:18:56 +0900 Subject: [PATCH 1/4] remove ViewController scene --- Ukam/Base.lproj/Main.storyboard | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/Ukam/Base.lproj/Main.storyboard b/Ukam/Base.lproj/Main.storyboard index 9ff8916..22c4b83 100644 --- a/Ukam/Base.lproj/Main.storyboard +++ b/Ukam/Base.lproj/Main.storyboard @@ -2,7 +2,6 @@ - @@ -680,18 +679,5 @@ - - - - - - - - - - - - - From ec25124dbdbdbbdcd87cd8d58c603b2a1288a048 Mon Sep 17 00:00:00 2001 From: Nobuhiro Ito Date: Sat, 10 Aug 2024 17:20:10 +0900 Subject: [PATCH 2/4] add about view --- Ukam.xcodeproj/project.pbxproj | 20 ++++++++ Ukam/Managers/MenuManager.swift | 27 +++++++++++ Ukam/Views/About/AboutView.swift | 45 ++++++++++++++++++ Ukam/Views/About/AboutViewController.swift | 47 +++++++++++++++++++ Ukam/Views/About/AcknowledgementsView.swift | 18 +++++++ .../PermissionsViewController.swift | 2 +- Ukam/en.lproj/Localizable.strings | 5 ++ Ukam/ja.lproj/Localizable.strings | 5 ++ localize/app/0000000_initial.yaml | 16 +++++++ 9 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 Ukam/Views/About/AboutView.swift create mode 100644 Ukam/Views/About/AboutViewController.swift create mode 100644 Ukam/Views/About/AcknowledgementsView.swift diff --git a/Ukam.xcodeproj/project.pbxproj b/Ukam.xcodeproj/project.pbxproj index 9e072db..0e8738c 100644 --- a/Ukam.xcodeproj/project.pbxproj +++ b/Ukam.xcodeproj/project.pbxproj @@ -29,6 +29,9 @@ 822CDF5027D52C1C00C6B331 /* ApplicationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 822CDF4F27D52C1C00C6B331 /* ApplicationServices.framework */; platformFilter = maccatalyst; }; 82302D0F2C669E4300B8BF8C /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 82302D112C669E4300B8BF8C /* Localizable.strings */; }; 82302D1D2C66A52C00B8BF8C /* RswiftLibrary in Frameworks */ = {isa = PBXBuildFile; productRef = 82302D1C2C66A52C00B8BF8C /* RswiftLibrary */; }; + 826008282C67511200ACD8A7 /* AboutViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 826008272C67511200ACD8A7 /* AboutViewController.swift */; }; + 8260082A2C67511A00ACD8A7 /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 826008292C67511A00ACD8A7 /* AboutView.swift */; }; + 8260082D2C6755A500ACD8A7 /* AcknowledgementsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8260082C2C6755A500ACD8A7 /* AcknowledgementsView.swift */; }; 828688F52C6512A80059CAEE /* PermissionsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 828688F42C6512A80059CAEE /* PermissionsManager.swift */; }; 828688F82C65158B0059CAEE /* PermissionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 828688F72C65158B0059CAEE /* PermissionsView.swift */; }; 828688FA2C651B6E0059CAEE /* PermissionsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 828688F92C651B6E0059CAEE /* PermissionsViewController.swift */; }; @@ -56,6 +59,9 @@ 8260081F2C67497900ACD8A7 /* Ukam.Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Ukam.Release.xcconfig; sourceTree = ""; }; 826008202C67499A00ACD8A7 /* Ukam.Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Ukam.Debug.xcconfig; sourceTree = ""; }; 826008212C674A0800ACD8A7 /* Version.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Version.xcconfig; sourceTree = ""; }; + 826008272C67511200ACD8A7 /* AboutViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutViewController.swift; sourceTree = ""; }; + 826008292C67511A00ACD8A7 /* AboutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutView.swift; sourceTree = ""; }; + 8260082C2C6755A500ACD8A7 /* AcknowledgementsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AcknowledgementsView.swift; sourceTree = ""; }; 828688F42C6512A80059CAEE /* PermissionsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionsManager.swift; sourceTree = ""; }; 828688F72C65158B0059CAEE /* PermissionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionsView.swift; sourceTree = ""; }; 828688F92C651B6E0059CAEE /* PermissionsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionsViewController.swift; sourceTree = ""; }; @@ -135,6 +141,16 @@ path = Configurations; sourceTree = ""; }; + 826008262C6750FB00ACD8A7 /* About */ = { + isa = PBXGroup; + children = ( + 826008272C67511200ACD8A7 /* AboutViewController.swift */, + 826008292C67511A00ACD8A7 /* AboutView.swift */, + 8260082C2C6755A500ACD8A7 /* AcknowledgementsView.swift */, + ); + path = About; + sourceTree = ""; + }; 828688F62C65154B0059CAEE /* Permissions */ = { isa = PBXGroup; children = ( @@ -149,6 +165,7 @@ children = ( 828688F62C65154B0059CAEE /* Permissions */, 82B14DFE2C5CDBE7000B08C3 /* Windows */, + 826008262C6750FB00ACD8A7 /* About */, 82B14E072C5CF685000B08C3 /* LayoutConstants.swift */, ); path = Views; @@ -331,11 +348,14 @@ 822CDF3E27D4C6CD00C6B331 /* MenuManager.swift in Sources */, 82B14E022C5CDC0E000B08C3 /* WindowsView.swift in Sources */, 82B14E042C5CE172000B08C3 /* WindowsViewDataSource.swift in Sources */, + 8260082A2C67511A00ACD8A7 /* AboutView.swift in Sources */, 822CDF4127D4C72E00C6B331 /* Window.swift in Sources */, 82B14E062C5CED30000B08C3 /* WindowItemView.swift in Sources */, 828688FA2C651B6E0059CAEE /* PermissionsViewController.swift in Sources */, 828688F82C65158B0059CAEE /* PermissionsView.swift in Sources */, 82C57EFD27D46DB900395627 /* AppDelegate.swift in Sources */, + 8260082D2C6755A500ACD8A7 /* AcknowledgementsView.swift in Sources */, + 826008282C67511200ACD8A7 /* AboutViewController.swift in Sources */, 82B14E002C5CDBF7000B08C3 /* WindowsViewController.swift in Sources */, 822CDF4427D4C79300C6B331 /* WindowManager.swift in Sources */, 82B14E082C5CF685000B08C3 /* LayoutConstants.swift in Sources */, diff --git a/Ukam/Managers/MenuManager.swift b/Ukam/Managers/MenuManager.swift index 36791cb..baf0037 100644 --- a/Ukam/Managers/MenuManager.swift +++ b/Ukam/Managers/MenuManager.swift @@ -21,6 +21,8 @@ class MenuManager: NSObject { popover.behavior = .transient return popover }() + + private var aboutWindow: NSWindow? init(windowManager: WindowManager, permissionsManager: PermissionsManager) { self.windowManager = windowManager @@ -40,6 +42,10 @@ class MenuManager: NSObject { } statusBarMenu.autoenablesItems = true + statusBarMenu.addItem( + withTitle: R.string.localizable.status_menu_about(), + action: #selector(MenuManager.showAbout), + keyEquivalent: "").target = self statusBarMenu.addItem( withTitle: R.string.localizable.status_menu_exit(), action: #selector(MenuManager.exitApp), @@ -47,6 +53,16 @@ class MenuManager: NSObject { windowsViewController.delegate = self } + + @objc func showAbout() { + let aboutWindow = self.aboutWindow ?? { + let newWindow = AboutViewController.createWindow() + newWindow.delegate = self + self.aboutWindow = newWindow + return newWindow + }() + aboutWindow.makeKeyAndOrderFront(nil) + } @objc func exitApp() { NSApplication.shared.terminate(self) @@ -87,3 +103,14 @@ extension MenuManager: WindowsViewControllerDelegate { popover.close() } } + +extension MenuManager: NSWindowDelegate { + func windowWillClose(_ notification: Notification) { + guard let window = notification.object as? NSWindow + else { return } + + if window == aboutWindow { + aboutWindow = nil + } + } +} diff --git a/Ukam/Views/About/AboutView.swift b/Ukam/Views/About/AboutView.swift new file mode 100644 index 0000000..db8902d --- /dev/null +++ b/Ukam/Views/About/AboutView.swift @@ -0,0 +1,45 @@ +// +// AboutView.swift +// Ukam +// +// Created by Nobuhiro Ito on 2024/08/10. +// + +import SwiftUI + +struct AboutView: View { + let versionString = { () -> String in + let marketingVersion = (Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String) ?? "" + let buildNumber = (Bundle.main.infoDictionary?["CFBundleVersion"] as? String) ?? "" + return "\(marketingVersion) (\(buildNumber))" + }() + + @State private var showingSheet = false + + var body: some View { + VStack(spacing: LayoutConstants.padding * 2) { + VStack(alignment: .center) { + Image(.imageIcon) + Text(R.string.localizable.app_name()).font(.title) + Text(versionString).font(.subheadline) + Text(R.string.localizable.about_view_copyright()) + .font(.subheadline) + } + VStack(alignment: .trailing) { + Button(R.string.localizable.about_view_acknowledgements()) { + self.showingSheet.toggle() + } + .sheet(isPresented: $showingSheet) { + AcknowledgementsView() + } + } + .frame(maxWidth: .infinity, alignment: .trailing) + } + .frame(maxWidth: 300) + .padding(LayoutConstants.padding * 2) + } +} + +#Preview { + AboutView() +} diff --git a/Ukam/Views/About/AboutViewController.swift b/Ukam/Views/About/AboutViewController.swift new file mode 100644 index 0000000..b3a7824 --- /dev/null +++ b/Ukam/Views/About/AboutViewController.swift @@ -0,0 +1,47 @@ +// +// AboutViewController.swift +// Ukam +// +// Created by Nobuhiro Ito on 2024/08/10. +// + +import Cocoa +import SwiftUI + +class AboutViewController: NSViewController { + private var containeredView: AboutView! + + static func createWindow() -> NSWindow { + let viewController = AboutViewController() + let window = NSWindow(contentViewController: viewController) + window.title = R.string.localizable.about_view_title() + window.styleMask = [.titled, .closable] + window.center() + return window + } + + init() { + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { + fatalError() + } + + override func viewDidLoad() { + super.viewDidLoad() + + containeredView = AboutView() + + let hostingView = NSHostingView(rootView: containeredView) + hostingView.translatesAutoresizingMaskIntoConstraints = false + view.addSubview(hostingView) + NSLayoutConstraint.activate([ + view.topAnchor.constraint(equalTo: hostingView.topAnchor), + view.leadingAnchor.constraint(equalTo: hostingView.leadingAnchor), + view.bottomAnchor.constraint(equalTo: hostingView.bottomAnchor), + view.trailingAnchor.constraint(equalTo: hostingView.trailingAnchor), + hostingView.heightAnchor.constraint(equalToConstant: hostingView.intrinsicContentSize.height) + ]) + } +} diff --git a/Ukam/Views/About/AcknowledgementsView.swift b/Ukam/Views/About/AcknowledgementsView.swift new file mode 100644 index 0000000..d86d779 --- /dev/null +++ b/Ukam/Views/About/AcknowledgementsView.swift @@ -0,0 +1,18 @@ +// +// AcknowledgementsView.swift +// Ukam +// +// Created by Nobuhiro Ito on 2024/08/10. +// + +import SwiftUI + +struct AcknowledgementsView: View { + var body: some View { + Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) + } +} + +#Preview { + AcknowledgementsView() +} diff --git a/Ukam/Views/Permissions/PermissionsViewController.swift b/Ukam/Views/Permissions/PermissionsViewController.swift index 499659f..4d830c3 100644 --- a/Ukam/Views/Permissions/PermissionsViewController.swift +++ b/Ukam/Views/Permissions/PermissionsViewController.swift @@ -16,7 +16,7 @@ class PermissionsViewController: NSViewController { static func createWindow(permissionsManager: PermissionsManager) -> NSWindow { let viewController = PermissionsViewController(permissionsManager: permissionsManager) let window = NSWindow(contentViewController: viewController) - window.title = "Permissions" + window.title = R.string.localizable.permissions_view_title() window.styleMask = [.titled, .closable] window.center() return window diff --git a/Ukam/en.lproj/Localizable.strings b/Ukam/en.lproj/Localizable.strings index cce0e30..0e678c6 100644 --- a/Ukam/en.lproj/Localizable.strings +++ b/Ukam/en.lproj/Localizable.strings @@ -1,3 +1,6 @@ +"about_view_acknowledgements" = "Acknowledgements"; +"about_view_copyright" = "(C) Nobuhiro Ito."; +"about_view_title" = "About Ukam"; "app_name" = "Ukam"; "permissions_view_accessibility_description" = "Ukam requires accessibility permissions to manipulate windows."; "permissions_view_accessibility_title" = "Accessibility"; @@ -6,4 +9,6 @@ "permissions_view_request_permission_title" = "Required Permissions"; "permissions_view_screen_recording_description" = "Ukam requires screen recording permissions to enumerate windows and create screen capture for window list."; "permissions_view_screen_recording_title" = "Screen Recording"; +"permissions_view_title" = "Ukam"; +"status_menu_about" = "About Ukam"; "status_menu_exit" = "Exit"; \ No newline at end of file diff --git a/Ukam/ja.lproj/Localizable.strings b/Ukam/ja.lproj/Localizable.strings index ac34a34..5040ceb 100644 --- a/Ukam/ja.lproj/Localizable.strings +++ b/Ukam/ja.lproj/Localizable.strings @@ -1,3 +1,6 @@ +"about_view_acknowledgements" = "謝辞"; +"about_view_copyright" = "(C) Nobuhiro Ito."; +"about_view_title" = "Ukamについて"; "app_name" = "Ukam"; "permissions_view_accessibility_description" = "ウィンドウを移動したり、最前面に移動させる操作をします。"; "permissions_view_accessibility_title" = "アクセシビリティ"; @@ -6,4 +9,6 @@ "permissions_view_request_permission_title" = "権限の許可"; "permissions_view_screen_recording_description" = "ウィンドウの一覧を取得し、ウィンドウリストに表示するスクリーンショットを作成します。"; "permissions_view_screen_recording_title" = "画面収録"; +"permissions_view_title" = "Ukam"; +"status_menu_about" = "Ukamについて"; "status_menu_exit" = "終了"; \ No newline at end of file diff --git a/localize/app/0000000_initial.yaml b/localize/app/0000000_initial.yaml index 377949a..d4d61d3 100644 --- a/localize/app/0000000_initial.yaml +++ b/localize/app/0000000_initial.yaml @@ -4,6 +4,9 @@ phrases: $description: Main App Name en: Ukam ja: Ukam + permissions_view_title: + en: Ukam + ja: Ukam permissions_view_request_permission_title: en: Required Permissions ja: 権限の許可 @@ -28,3 +31,16 @@ phrases: status_menu_exit: en: Exit ja: 終了 + status_menu_about: + en: About Ukam + ja: Ukamについて + about_view_title: + en: About Ukam + ja: Ukamについて + about_view_copyright: + en: (C) Nobuhiro Ito. + ja: (C) Nobuhiro Ito. + about_view_acknowledgements: + en: Acknowledgements + ja: 謝辞 + From a49e067818bfbedd2d136572c0208b203a47413f Mon Sep 17 00:00:00 2001 From: Nobuhiro Ito Date: Sat, 10 Aug 2024 17:47:20 +0900 Subject: [PATCH 3/4] add LicensePlist --- Ukam.xcodeproj/project.pbxproj | 39 ++++++++++++ .../xcshareddata/swiftpm/Package.resolved | 63 +++++++++++++++++++ license_plist.yml | 4 ++ 3 files changed, 106 insertions(+) create mode 100644 license_plist.yml diff --git a/Ukam.xcodeproj/project.pbxproj b/Ukam.xcodeproj/project.pbxproj index 0e8738c..c3d6afb 100644 --- a/Ukam.xcodeproj/project.pbxproj +++ b/Ukam.xcodeproj/project.pbxproj @@ -32,6 +32,7 @@ 826008282C67511200ACD8A7 /* AboutViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 826008272C67511200ACD8A7 /* AboutViewController.swift */; }; 8260082A2C67511A00ACD8A7 /* AboutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 826008292C67511A00ACD8A7 /* AboutView.swift */; }; 8260082D2C6755A500ACD8A7 /* AcknowledgementsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8260082C2C6755A500ACD8A7 /* AcknowledgementsView.swift */; }; + 8260083E2C675CA600ACD8A7 /* AcknowledgementsDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8260083D2C675CA600ACD8A7 /* AcknowledgementsDataSource.swift */; }; 828688F52C6512A80059CAEE /* PermissionsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 828688F42C6512A80059CAEE /* PermissionsManager.swift */; }; 828688F82C65158B0059CAEE /* PermissionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 828688F72C65158B0059CAEE /* PermissionsView.swift */; }; 828688FA2C651B6E0059CAEE /* PermissionsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 828688F92C651B6E0059CAEE /* PermissionsViewController.swift */; }; @@ -62,6 +63,7 @@ 826008272C67511200ACD8A7 /* AboutViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutViewController.swift; sourceTree = ""; }; 826008292C67511A00ACD8A7 /* AboutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutView.swift; sourceTree = ""; }; 8260082C2C6755A500ACD8A7 /* AcknowledgementsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AcknowledgementsView.swift; sourceTree = ""; }; + 8260083D2C675CA600ACD8A7 /* AcknowledgementsDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AcknowledgementsDataSource.swift; sourceTree = ""; }; 828688F42C6512A80059CAEE /* PermissionsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionsManager.swift; sourceTree = ""; }; 828688F72C65158B0059CAEE /* PermissionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionsView.swift; sourceTree = ""; }; 828688F92C651B6E0059CAEE /* PermissionsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionsViewController.swift; sourceTree = ""; }; @@ -147,6 +149,7 @@ 826008272C67511200ACD8A7 /* AboutViewController.swift */, 826008292C67511A00ACD8A7 /* AboutView.swift */, 8260082C2C6755A500ACD8A7 /* AcknowledgementsView.swift */, + 8260083D2C675CA600ACD8A7 /* AcknowledgementsDataSource.swift */, ); path = About; sourceTree = ""; @@ -226,11 +229,13 @@ buildPhases = ( 82C57EF527D46DB900395627 /* Sources */, 82C57EF627D46DB900395627 /* Frameworks */, + 82C5D37D2C675B3000395627 /* Copy Acknowledgements */, 82C57EF727D46DB900395627 /* Resources */, ); buildRules = ( ); dependencies = ( + 826008372C675AAB00ACD8A7 /* PBXTargetDependency */, 82302D1F2C66A54300B8BF8C /* PBXTargetDependency */, ); name = Ukam; @@ -272,6 +277,7 @@ mainGroup = 82C57EF027D46DB900395627; packageReferences = ( 82302D1B2C66A4F900B8BF8C /* XCRemoteSwiftPackageReference "R.swift" */, + 826008342C675A9700ACD8A7 /* XCRemoteSwiftPackageReference "LicensePlist" */, ); productRefGroup = 82C57EFA27D46DB900395627 /* Products */; projectDirPath = ""; @@ -337,6 +343,21 @@ shellPath = /bin/sh; shellScript = "hoshi_cli=\"$PROJECT_DIR/.vendor/hoshi.app/Contents/hoshi-cli\"\n\nwork_dir=$(mktemp -d)\nfunction cleanup {\n rm -rf \"$work_dir\"\n}\ntrap cleanup EXIT\n\n$hoshi_cli publish --project \"$PROJECT_DIR/localize\" --outDir \"$work_dir\" app\n\ncp \"$work_dir/app/strings/en.strings\" \"$PROJECT_DIR/Ukam/en.lproj/Localizable.strings\"\ncp \"$work_dir/app/strings/ja.strings\" \"$PROJECT_DIR/Ukam/ja.lproj/Localizable.strings\"\n"; }; + 82C5D37D2C675B3000395627 /* Copy Acknowledgements */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Copy Acknowledgements"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"Will copy acknowledgements\"\n\nACKNOWLEDGEMENTS_DIR=${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}/com.mono0926.LicensePlist.Output\nDESTINATION_PATH=${BUILT_PRODUCTS_DIR}/${CONTENTS_FOLDER_PATH}/Settings.bundle/\n\necho $ACKNOWLEDGEMENTS_DIR\necho $DESTINATION_PATH\n\n\n#cp -r \"${ACKNOWLEDGEMENTS_DIR}\"/* \"${DESTINATION_PATH}\"\n#rm -rf \"${ACKNOWLEDGEMENTS_DIR}\"\n"; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -346,6 +367,7 @@ files = ( 828688F52C6512A80059CAEE /* PermissionsManager.swift in Sources */, 822CDF3E27D4C6CD00C6B331 /* MenuManager.swift in Sources */, + 8260083E2C675CA600ACD8A7 /* AcknowledgementsDataSource.swift in Sources */, 82B14E022C5CDC0E000B08C3 /* WindowsView.swift in Sources */, 82B14E042C5CE172000B08C3 /* WindowsViewDataSource.swift in Sources */, 8260082A2C67511A00ACD8A7 /* AboutView.swift in Sources */, @@ -369,6 +391,10 @@ isa = PBXTargetDependency; productRef = 82302D1E2C66A54300B8BF8C /* RswiftGenerateInternalResources */; }; + 826008372C675AAB00ACD8A7 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + productRef = 826008362C675AAB00ACD8A7 /* LicensePlistBuildTool */; + }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ @@ -625,6 +651,14 @@ minimumVersion = 7.5.0; }; }; + 826008342C675A9700ACD8A7 /* XCRemoteSwiftPackageReference "LicensePlist" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/mono0926/LicensePlist.git"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 3.25.1; + }; + }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ @@ -638,6 +672,11 @@ package = 82302D1B2C66A4F900B8BF8C /* XCRemoteSwiftPackageReference "R.swift" */; productName = "plugin:RswiftGenerateInternalResources"; }; + 826008362C675AAB00ACD8A7 /* LicensePlistBuildTool */ = { + isa = XCSwiftPackageProductDependency; + package = 826008342C675A9700ACD8A7 /* XCRemoteSwiftPackageReference "LicensePlist" */; + productName = "plugin:LicensePlistBuildTool"; + }; /* End XCSwiftPackageProductDependency section */ }; rootObject = 82C57EF127D46DB900395627 /* Project object */; diff --git a/Ukam.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Ukam.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 29e7256..d92d1a7 100644 --- a/Ukam.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Ukam.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,41 @@ { "pins" : [ + { + "identity" : "apikit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/ishkawa/APIKit.git", + "state" : { + "revision" : "b839e53b870104798035b279d2a6168b0a2227b1", + "version" : "5.4.0" + } + }, + { + "identity" : "heliumlogger", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Kitura/HeliumLogger.git", + "state" : { + "revision" : "fc2a71597ae974da5282d751bcc11965964bccce", + "version" : "2.0.0" + } + }, + { + "identity" : "licenseplist", + "kind" : "remoteSourceControl", + "location" : "https://github.com/mono0926/LicensePlist.git", + "state" : { + "revision" : "f3f802009c9f71ad46356adb453fcb57b8931ff9", + "version" : "3.25.1" + } + }, + { + "identity" : "loggerapi", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Kitura/LoggerAPI.git", + "state" : { + "revision" : "4e6b45e850ffa275e8e26a24c6454fd709d5b6ac", + "version" : "2.0.0" + } + }, { "identity" : "r.swift", "kind" : "remoteSourceControl", @@ -18,6 +54,24 @@ "version" : "1.5.0" } }, + { + "identity" : "swift-html-entities", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Kitura/swift-html-entities.git", + "state" : { + "revision" : "d8ca73197f59ce260c71bd6d7f6eb8bbdccf508b", + "version" : "4.0.1" + } + }, + { + "identity" : "swift-log", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-log.git", + "state" : { + "revision" : "9cb486020ebf03bfa5b5df985387a14a98744537", + "version" : "1.6.1" + } + }, { "identity" : "xcodeedit", "kind" : "remoteSourceControl", @@ -26,6 +80,15 @@ "revision" : "b6b67389a0f1a6fdd9c6457a8ab5b02eaab13c5c", "version" : "2.9.2" } + }, + { + "identity" : "yams", + "kind" : "remoteSourceControl", + "location" : "https://github.com/jpsim/Yams.git", + "state" : { + "revision" : "3036ba9d69cf1fd04d433527bc339dc0dc75433d", + "version" : "5.1.3" + } } ], "version" : 2 diff --git a/license_plist.yml b/license_plist.yml new file mode 100644 index 0000000..cf5bee3 --- /dev/null +++ b/license_plist.yml @@ -0,0 +1,4 @@ +options: + xcodeprojPath: Ukam.xcodeproj + prefix: Acknowledgements + singlePage: true From 313fde88dfc28015e920a4a8d55bcc896c99413d Mon Sep 17 00:00:00 2001 From: Nobuhiro Ito Date: Sat, 10 Aug 2024 17:51:15 +0900 Subject: [PATCH 4/4] integrate Acknowledgements --- Ukam/Views/About/AboutView.swift | 4 +- .../About/AcknowledgementsDataSource.swift | 45 +++++++++++++++++++ Ukam/Views/About/AcknowledgementsView.swift | 42 ++++++++++++++++- Ukam/Views/LayoutConstants.swift | 4 ++ Ukam/en.lproj/Localizable.strings | 1 + Ukam/ja.lproj/Localizable.strings | 1 + localize/app/0000000_initial.yaml | 4 +- 7 files changed, 96 insertions(+), 5 deletions(-) create mode 100644 Ukam/Views/About/AcknowledgementsDataSource.swift diff --git a/Ukam/Views/About/AboutView.swift b/Ukam/Views/About/AboutView.swift index db8902d..b8c2ac9 100644 --- a/Ukam/Views/About/AboutView.swift +++ b/Ukam/Views/About/AboutView.swift @@ -30,12 +30,12 @@ struct AboutView: View { self.showingSheet.toggle() } .sheet(isPresented: $showingSheet) { - AcknowledgementsView() + AcknowledgementsView(dataSource: BundleAcknowledgementsDataSource()) } } .frame(maxWidth: .infinity, alignment: .trailing) } - .frame(maxWidth: 300) + .frame(maxWidth: LayoutConstants.aboutViewWidth) .padding(LayoutConstants.padding * 2) } } diff --git a/Ukam/Views/About/AcknowledgementsDataSource.swift b/Ukam/Views/About/AcknowledgementsDataSource.swift new file mode 100644 index 0000000..2b1c39d --- /dev/null +++ b/Ukam/Views/About/AcknowledgementsDataSource.swift @@ -0,0 +1,45 @@ +// +// AcknowledgementsDataSource.swift +// Ukam +// +// Created by Nobuhiro Ito on 2024/08/10. +// + +import Foundation + +struct Acknowledgement: Decodable { + enum CodingKeys: String, CodingKey { + case title = "Title" + case body = "FooterText" + } + + let title: String + let body: String +} + +protocol AcknowledgementsDataSource { + var acknowledgements: [Acknowledgement] { get } +} + +struct BundleAcknowledgementsDataSource: AcknowledgementsDataSource { + struct AcknowledgementsContainer: Decodable { + enum CodingKeys: String, CodingKey { + case acknowledgements = "PreferenceSpecifiers" + } + + let acknowledgements: [Acknowledgement] + } + + let acknowledgements: [Acknowledgement] + + init() { + if let path = Bundle.main.path(forResource: "com.mono0926.LicensePlist.Output/Acknowledgements", ofType: "plist"), + let data = FileManager.default.contents(atPath: path), + let acknowledgements = try? PropertyListDecoder().decode(AcknowledgementsContainer.self, from: data) { + self.acknowledgements = acknowledgements.acknowledgements + } else { + self.acknowledgements = [] + } + + } +} diff --git a/Ukam/Views/About/AcknowledgementsView.swift b/Ukam/Views/About/AcknowledgementsView.swift index d86d779..35288f6 100644 --- a/Ukam/Views/About/AcknowledgementsView.swift +++ b/Ukam/Views/About/AcknowledgementsView.swift @@ -7,12 +7,50 @@ import SwiftUI +struct AcknowledgementsItem: View { + var acknowledgement: Acknowledgement + + var body: some View { + VStack(alignment: .leading) { + Text(acknowledgement.title).font(.headline) + Text(acknowledgement.body).font(.body) + } + } +} + struct AcknowledgementsView: View { + var dataSource: AcknowledgementsDataSource + + @Environment(\.presentationMode) var presentationMode + var body: some View { - Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) + VStack(alignment: .leading) { + ScrollView { + VStack(spacing: LayoutConstants.padding * 2) { + ForEach(dataSource.acknowledgements, id: \.title) { acknowledgement in + AcknowledgementsItem(acknowledgement: acknowledgement) + } + } + } + VStack(alignment: .trailing) { + Button(R.string.localizable.acknowledgements_view_close()) { + self.presentationMode.wrappedValue.dismiss() + } + } + .frame(maxWidth: .infinity, alignment: .trailing) + } + .frame(width: LayoutConstants.acknowledgementsViewWidth, height: LayoutConstants.acknowledgementsViewHeight) + .padding(LayoutConstants.padding * 2) } } +struct PreviewAcknowledgementsDataSource: AcknowledgementsDataSource { + var acknowledgements: [Acknowledgement] = [ + Acknowledgement(title: "Title", body: "Body"), + Acknowledgement(title: "Title", body: "Body") + ] +} + #Preview { - AcknowledgementsView() + AcknowledgementsView(dataSource: PreviewAcknowledgementsDataSource()) } diff --git a/Ukam/Views/LayoutConstants.swift b/Ukam/Views/LayoutConstants.swift index 28e884b..6cb67d0 100644 --- a/Ukam/Views/LayoutConstants.swift +++ b/Ukam/Views/LayoutConstants.swift @@ -12,6 +12,10 @@ struct LayoutConstants { static let cornerRadius: CGFloat = 8 static let permissionViewWidth: CGFloat = 480 + static let aboutViewWidth: CGFloat = 300 + static let acknowledgementsViewWidth: CGFloat = 480 + static let acknowledgementsViewHeight: CGFloat = 480 + static let windowsFrameWidth: CGFloat = 300 static let screenshotWidth: CGFloat = 240 static let screenshotHeight: CGFloat = 100 diff --git a/Ukam/en.lproj/Localizable.strings b/Ukam/en.lproj/Localizable.strings index 0e678c6..06cac1a 100644 --- a/Ukam/en.lproj/Localizable.strings +++ b/Ukam/en.lproj/Localizable.strings @@ -1,6 +1,7 @@ "about_view_acknowledgements" = "Acknowledgements"; "about_view_copyright" = "(C) Nobuhiro Ito."; "about_view_title" = "About Ukam"; +"acknowledgements_view_close" = "Close"; "app_name" = "Ukam"; "permissions_view_accessibility_description" = "Ukam requires accessibility permissions to manipulate windows."; "permissions_view_accessibility_title" = "Accessibility"; diff --git a/Ukam/ja.lproj/Localizable.strings b/Ukam/ja.lproj/Localizable.strings index 5040ceb..d10b80d 100644 --- a/Ukam/ja.lproj/Localizable.strings +++ b/Ukam/ja.lproj/Localizable.strings @@ -1,6 +1,7 @@ "about_view_acknowledgements" = "謝辞"; "about_view_copyright" = "(C) Nobuhiro Ito."; "about_view_title" = "Ukamについて"; +"acknowledgements_view_close" = "閉じる"; "app_name" = "Ukam"; "permissions_view_accessibility_description" = "ウィンドウを移動したり、最前面に移動させる操作をします。"; "permissions_view_accessibility_title" = "アクセシビリティ"; diff --git a/localize/app/0000000_initial.yaml b/localize/app/0000000_initial.yaml index d4d61d3..7c3dcb5 100644 --- a/localize/app/0000000_initial.yaml +++ b/localize/app/0000000_initial.yaml @@ -43,4 +43,6 @@ phrases: about_view_acknowledgements: en: Acknowledgements ja: 謝辞 - + acknowledgements_view_close: + en: Close + ja: 閉じる