diff --git a/Xcodes.xcodeproj/project.pbxproj b/Xcodes.xcodeproj/project.pbxproj index e45b976..701b465 100644 --- a/Xcodes.xcodeproj/project.pbxproj +++ b/Xcodes.xcodeproj/project.pbxproj @@ -13,6 +13,7 @@ 536CFDD4263C9A8000026CE0 /* XcodesSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 536CFDD3263C9A8000026CE0 /* XcodesSheet.swift */; }; 53CBAB2C263DCC9100410495 /* XcodesAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53CBAB2B263DCC9100410495 /* XcodesAlert.swift */; }; 63EAA4EB259944450046AB8F /* ProgressButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 63EAA4EA259944450046AB8F /* ProgressButton.swift */; }; + B0403CF02AD92D7B00137C09 /* ReleaseNotesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0403CEF2AD92D7B00137C09 /* ReleaseNotesView.swift */; }; B0C6AD042AD6E65700E64698 /* ReleaseDateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0C6AD032AD6E65700E64698 /* ReleaseDateView.swift */; }; B0C6AD0B2AD9178E00E64698 /* IdenticalBuildView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0C6AD0A2AD9178E00E64698 /* IdenticalBuildView.swift */; }; B0C6AD0D2AD91D7900E64698 /* IconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0C6AD0C2AD91D7900E64698 /* IconView.swift */; }; @@ -195,6 +196,7 @@ A0187D39285792D1002F46F9 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; AAB037D32839BD4700017680 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/Localizable.strings; sourceTree = ""; }; AB4EB0DE28541FA000FF3B1D /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/Localizable.strings; sourceTree = ""; }; + B0403CEF2AD92D7B00137C09 /* ReleaseNotesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReleaseNotesView.swift; sourceTree = ""; }; B0C6AD032AD6E65700E64698 /* ReleaseDateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReleaseDateView.swift; sourceTree = ""; }; B0C6AD0A2AD9178E00E64698 /* IdenticalBuildView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdenticalBuildView.swift; sourceTree = ""; }; B0C6AD0C2AD91D7900E64698 /* IconView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IconView.swift; sourceTree = ""; }; @@ -621,6 +623,7 @@ E8E98A9425D863B100EC89A0 /* InfoPane */ = { isa = PBXGroup; children = ( + B0403CEF2AD92D7B00137C09 /* ReleaseNotesView.swift */, CAFBDC67259A308B003DCC5A /* InfoPane.swift */, E8E98A9525D863D700EC89A0 /* InstallationStepDetailView.swift */, B0C6AD032AD6E65700E64698 /* ReleaseDateView.swift */, @@ -877,6 +880,7 @@ CA61A6E0259835580008926E /* Xcode.swift in Sources */, CAE4247F259A666100B8B246 /* MainWindow.swift in Sources */, CA452BB0259FD9770072DFA4 /* ProgressIndicator.swift in Sources */, + B0403CF02AD92D7B00137C09 /* ReleaseNotesView.swift in Sources */, CAFE4AB425B7D3AF0064FE51 /* AdvancedPreferencePane.swift in Sources */, CA9FF84E2595079F00E47BAF /* ScrollingTextView.swift in Sources */, CABFA9C12592EEEA00380FEE /* Version+.swift in Sources */, diff --git a/Xcodes/Backend/AppState.swift b/Xcodes/Backend/AppState.swift index 49e22de..1c92951 100644 --- a/Xcodes/Backend/AppState.swift +++ b/Xcodes/Backend/AppState.swift @@ -630,8 +630,8 @@ class AppState: ObservableObject { NSPasteboard.general.setString(installedXcodePath.string, forType: .string) } - func copyReleaseNote(xcode: Xcode) { - guard let url = xcode.releaseNotesURL else { return } + func copyReleaseNote(from url: URL?) { + guard let url = url else { return } NSPasteboard.general.declareTypes([.URL, .string], owner: nil) NSPasteboard.general.writeObjects([url as NSURL]) NSPasteboard.general.setString(url.absoluteString, forType: .string) diff --git a/Xcodes/Backend/XcodeCommands.swift b/Xcodes/Backend/XcodeCommands.swift index 76e9924..196e25d 100644 --- a/Xcodes/Backend/XcodeCommands.swift +++ b/Xcodes/Backend/XcodeCommands.swift @@ -173,8 +173,9 @@ struct CopyPathButton: View { } struct CopyReleaseNoteButton: View { + let url: URL? + @EnvironmentObject var appState: AppState - let xcode: Xcode? var body: some View { Button(action: copyReleaseNote) { @@ -184,8 +185,8 @@ struct CopyReleaseNoteButton: View { } private func copyReleaseNote() { - guard let xcode = xcode else { return } - appState.copyReleaseNote(xcode: xcode) + guard let url = url else { return } + appState.copyReleaseNote(from: url) } } diff --git a/Xcodes/Frontend/InfoPane/InfoPane.swift b/Xcodes/Frontend/InfoPane/InfoPane.swift index ed91d6d..293d804 100644 --- a/Xcodes/Frontend/InfoPane/InfoPane.swift +++ b/Xcodes/Frontend/InfoPane/InfoPane.swift @@ -54,7 +54,7 @@ struct InfoPane: View { Divider() Group{ - releaseNotes(for: xcode) + ReleaseNotesView(url: xcode.releaseNotesURL) ReleaseDateView(date: xcode.releaseDate) .frame(maxWidth: .infinity, alignment: .leading) IdenticalBuildsView(builds: xcode.identicalBuilds) @@ -74,28 +74,6 @@ struct InfoPane: View { } } - @ViewBuilder - private func releaseNotes(for xcode: Xcode) -> some View { - if let releaseNotesURL = xcode.releaseNotesURL { - Button(action: { openURL(releaseNotesURL) }) { - Label("ReleaseNotes", systemImage: "link") - } - .buttonStyle(LinkButtonStyle()) - .contextMenu(menuItems: { - releaseNotesMenu(for: xcode) - }) - .frame(maxWidth: .infinity, alignment: .leading) - .help("ReleaseNotes.help") - } else { - EmptyView() - } - } - - @ViewBuilder - private func releaseNotesMenu(for xcode: Xcode) -> some View { - CopyReleaseNoteButton(xcode: xcode) - } - @ViewBuilder private func compatibility(for xcode: Xcode) -> some View { if let requiredMacOSVersion = xcode.requiredMacOSVersion { diff --git a/Xcodes/Frontend/InfoPane/ReleaseNotesView.swift b/Xcodes/Frontend/InfoPane/ReleaseNotesView.swift new file mode 100644 index 0000000..a9aa3c1 --- /dev/null +++ b/Xcodes/Frontend/InfoPane/ReleaseNotesView.swift @@ -0,0 +1,62 @@ +// +// ReleaseNotesView.swift +// Xcodes +// +// Created by Duong Thai on 13/10/2023. +// Copyright © 2023 Robots and Pencils. All rights reserved. +// + +import SwiftUI + +struct ReleaseNotesView: View { + let url: URL? + + @SwiftUI.Environment(\.openURL) var openURL: OpenURLAction + + var body: some View { + if let url = url { + Button(action: { openURL(url) }) { + Label("ReleaseNotes", systemImage: "link") + } + .buttonStyle(LinkButtonStyle()) + .contextMenu(menuItems: { + CopyReleaseNoteButton(url: url) + }) + .frame(maxWidth: .infinity, alignment: .leading) + .help("ReleaseNotes.help") + } else { + EmptyView() + } + } +} + +struct ReleaseNotesView_Preview: PreviewProvider { + static var previews: some View { + WrapperView() + } +} + +private struct WrapperView: View { + @State var hasURL = false + var url: URL? { + hasURL + ? nil + : URL(string: "https://developer.apple.com/documentation/xcode-release-notes/xcode-12_3-release-notes/")! + } + + var body: some View { + VStack { + HStack { + ReleaseNotesView(url: url) + .border(.red) + } + Spacer() + Toggle(isOn: $hasURL) { + Text("Has URL?") + } + } + .animation(.default) + .frame(width: 300, height: 100) + .padding() + } +}