Skip to content

Commit 495dfed

Browse files
authored
Merge branch 'main' into fix/missing-ja-localization
2 parents cb11206 + 0b6ae5d commit 495dfed

33 files changed

Lines changed: 926 additions & 197 deletions

.github/workflows/appcast.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
persist-credentials: false
1616

1717
- name: Cache 📦
18-
uses: actions/cache@v3.0.8
18+
uses: actions/cache@v3.0.11
1919
with:
2020
path: AppCast/vendor/bundle
2121
key: ${{ runner.os }}-gems-v1.0-${{ hashFiles('AppCast/Gemfile') }}

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ Product/*
3636
timeline.xctimeline
3737
playground.xcworkspace
3838

39+
# Jetbrains IDEA
40+
.idea
41+
3942
# Swift Package Manager
4043
#
4144
# Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.

CONTRIBUTING.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Contributing to Xcodes
2+
We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's:
3+
4+
- Reporting a bug
5+
- Discussing the current state of the code
6+
- Submitting a fix
7+
- Proposing new features
8+
- Becoming a maintainer
9+
10+
## We Develop with Github
11+
We use github to host code, to track issues and feature requests, as well as accept pull requests.
12+
13+
## All Code Changes Happen Through Pull Requests
14+
Pull requests are the best way to propose changes to the codebase We actively welcome your pull requests:
15+
16+
1. Fork the repo and create your branch from `main`.
17+
2. If you've added code that should be tested, add tests.
18+
3. If you've added new functionality, add documentation
19+
4. Ensure the test suite passes.
20+
5. Make sure your code lints.
21+
6. Issue that pull request!
22+
23+
## Any contributions you make will be under the MIT Software License
24+
In short, when you submit code changes, your submissions are understood to be under the same [MIT License](http://choosealicense.com/licenses/mit/) that covers the project. Feel free to contact the maintainers if that's a concern.
25+
26+
## Report bugs using Github's [issues](https://github.com/robotsandpencils/xcodesapp/issues)
27+
We use GitHub issues to track public bugs. Report a bug by [opening a new issue](); it's that easy!
28+
29+
## Write bug reports with detail, background, and sample code
30+
31+
**Great Bug Reports** tend to have:
32+
33+
- A quick summary and/or background
34+
- Steps to reproduce
35+
- Be specific!
36+
- What you expected would happen
37+
- What actually happens
38+
- Notes (possibly including why you think this might be happening, or stuff you tried that didn't work)
39+
40+
People *love* thorough bug reports.
41+
42+
## License
43+
By contributing, you agree that your contributions will be licensed under its MIT License.

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ The following languages are supported because of the following community users!
4040
|Hindi 🇮🇳 |[@KGurpreet](https://github.com/KGurpreet)|Chinese-Simplified 🇨🇳|[@megabitsenmzq](https://github.com/megabitsenmzq)|
4141
|Finnish 🇫🇮 |[@marcusziade](https://github.com/marcusziade)|Chinese-Traditional 🇹🇼|[@itszero](https://github.com/itszero)|
4242
|Ukranian 🇺🇦 |[@gelosi](https://github.com/gelosi)|Japanese 🇯🇵|[@tatsuz0u](https://github.com/tatsuz0u)|
43-
|German 🇩🇪|[@drct](https://github.com/drct)||
43+
|German 🇩🇪|[@drct](https://github.com/drct)|Dutch 🇳🇱|[@jfversluis](https://github/com/jfversluis)|
44+
|Brazilian Portuguese 🇧🇷|[@brunomunizaf](https://github.com/brunomunizaf)||
4445

4546
Want to add more languages? Simply create a PR with the updated strings file.
4647
## Installation

Xcodes.xcodeproj/project.pbxproj

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
36741BFD291E4FDB00A85AAE /* DownloadPreferencePane.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36741BFC291E4FDB00A85AAE /* DownloadPreferencePane.swift */; };
11+
36741BFF291E50F500A85AAE /* FileError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 36741BFE291E50F500A85AAE /* FileError.swift */; };
1012
536CFDD2263C94DE00026CE0 /* SignedInView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 536CFDD1263C94DE00026CE0 /* SignedInView.swift */; };
1113
536CFDD4263C9A8000026CE0 /* XcodesSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 536CFDD3263C9A8000026CE0 /* XcodesSheet.swift */; };
1214
53CBAB2C263DCC9100410495 /* XcodesAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 53CBAB2B263DCC9100410495 /* XcodesAlert.swift */; };
@@ -102,6 +104,7 @@
102104
CAFFFED8259CDA5000903F81 /* XcodeListViewRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAFFFED7259CDA5000903F81 /* XcodeListViewRow.swift */; };
103105
E81D7EA02805250100A205FC /* Collection+.swift in Sources */ = {isa = PBXBuildFile; fileRef = E81D7E9F2805250100A205FC /* Collection+.swift */; };
104106
E872EE4E2808D4F100D3DD8B /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = E872EE502808D4F100D3DD8B /* Localizable.strings */; };
107+
E87AB3C52939B65E00D72F43 /* Hardware.swift in Sources */ = {isa = PBXBuildFile; fileRef = E87AB3C42939B65E00D72F43 /* Hardware.swift */; };
105108
E87DD6EB25D053FA00D86808 /* Progress+.swift in Sources */ = {isa = PBXBuildFile; fileRef = E87DD6EA25D053FA00D86808 /* Progress+.swift */; };
106109
E89342FA25EDCC17007CF557 /* NotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E89342F925EDCC17007CF557 /* NotificationManager.swift */; };
107110
E8977EA325C11E1500835F80 /* PreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8977EA225C11E1500835F80 /* PreferencesView.swift */; };
@@ -170,6 +173,9 @@
170173
/* Begin PBXFileReference section */
171174
15FAD1652811D15600B63259 /* hi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hi; path = hi.lproj/Localizable.strings; sourceTree = "<group>"; };
172175
25E2FA26284769A00014A318 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/Localizable.strings; sourceTree = "<group>"; };
176+
327DF109286ABE6B00D694D5 /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Localizable.strings"; sourceTree = "<group>"; };
177+
36741BFC291E4FDB00A85AAE /* DownloadPreferencePane.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DownloadPreferencePane.swift; sourceTree = "<group>"; };
178+
36741BFE291E50F500A85AAE /* FileError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FileError.swift; sourceTree = "<group>"; };
173179
4A5AAA1D28118FAD00528958 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; };
174180
536CFDD1263C94DE00026CE0 /* SignedInView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignedInView.swift; sourceTree = "<group>"; };
175181
536CFDD3263C9A8000026CE0 /* XcodesSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XcodesSheet.swift; sourceTree = "<group>"; };
@@ -289,8 +295,10 @@
289295
CAFE4ABB25B7D54B0064FE51 /* UpdatesPreferencePane.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UpdatesPreferencePane.swift; sourceTree = "<group>"; };
290296
CAFFFED7259CDA5000903F81 /* XcodeListViewRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XcodeListViewRow.swift; sourceTree = "<group>"; };
291297
CAFFFEEE259CEAC400903F81 /* RingProgressViewStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RingProgressViewStyle.swift; sourceTree = "<group>"; };
298+
E2AFDCCA28F024D000864ADD /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; };
292299
E81D7E9F2805250100A205FC /* Collection+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Collection+.swift"; sourceTree = "<group>"; };
293300
E872EE4F2808D4F100D3DD8B /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
301+
E87AB3C42939B65E00D72F43 /* Hardware.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Hardware.swift; sourceTree = "<group>"; };
294302
E87DD6EA25D053FA00D86808 /* Progress+.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Progress+.swift"; sourceTree = "<group>"; };
295303
E89342F925EDCC17007CF557 /* NotificationManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationManager.swift; sourceTree = "<group>"; };
296304
E8977EA225C11E1500835F80 /* PreferencesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreferencesView.swift; sourceTree = "<group>"; };
@@ -456,6 +464,7 @@
456464
CAA858C325A2BE4E00ACF8C0 /* Downloader.swift */,
457465
CABFA9B22592EEEA00380FEE /* Entry+.swift */,
458466
CABFA9A92592EEE900380FEE /* Environment.swift */,
467+
36741BFE291E50F500A85AAE /* FileError.swift */,
459468
CABFA9B82592EEEA00380FEE /* FileManager+.swift */,
460469
CAFBDB942598FE96003DCC5A /* FocusedValues.swift */,
461470
CABFA9AC2592EEE900380FEE /* Foundation.swift */,
@@ -482,6 +491,7 @@
482491
E87DD6EA25D053FA00D86808 /* Progress+.swift */,
483492
E81D7E9F2805250100A205FC /* Collection+.swift */,
484493
E8D655BF288DD04700A139C2 /* SelectedActionType.swift */,
494+
E87AB3C42939B65E00D72F43 /* Hardware.swift */,
485495
);
486496
path = Backend;
487497
sourceTree = "<group>";
@@ -588,6 +598,7 @@
588598
isa = PBXGroup;
589599
children = (
590600
CAFE4AB325B7D3AF0064FE51 /* AdvancedPreferencePane.swift */,
601+
36741BFC291E4FDB00A85AAE /* DownloadPreferencePane.swift */,
591602
CAFE4AAB25B7D2C70064FE51 /* GeneralPreferencePane.swift */,
592603
CAFE4ABB25B7D54B0064FE51 /* UpdatesPreferencePane.swift */,
593604
E8977EA225C11E1500835F80 /* PreferencesView.swift */,
@@ -721,6 +732,8 @@
721732
de,
722733
uk,
723734
fi,
735+
"pt-BR",
736+
nl,
724737
);
725738
mainGroup = CAD2E7952449574E00113D76;
726739
packageReferences = (
@@ -838,6 +851,7 @@
838851
CAA1CB45255A5B60003FD669 /* SignIn2FAView.swift in Sources */,
839852
CABFA9C52592EEEA00380FEE /* FileManager+.swift in Sources */,
840853
CABFA9CD2592EEEA00380FEE /* Foundation.swift in Sources */,
854+
36741BFF291E50F500A85AAE /* FileError.swift in Sources */,
841855
CA9FF8872595607900E47BAF /* InstalledXcode.swift in Sources */,
842856
53CBAB2C263DCC9100410495 /* XcodesAlert.swift in Sources */,
843857
CA42DD6E25AEA8B200BC0B0C /* Logger.swift in Sources */,
@@ -848,6 +862,7 @@
848862
CA9FF84E2595079F00E47BAF /* ScrollingTextView.swift in Sources */,
849863
CABFA9C12592EEEA00380FEE /* Version+.swift in Sources */,
850864
E8D655C0288DD04700A139C2 /* SelectedActionType.swift in Sources */,
865+
36741BFD291E4FDB00A85AAE /* DownloadPreferencePane.swift in Sources */,
851866
CA9FF8522595080100E47BAF /* AcknowledgementsView.swift in Sources */,
852867
CABFA9CE2592EEEA00380FEE /* Version+Xcode.swift in Sources */,
853868
CAFBDB912598FE80003DCC5A /* SelectedXcode.swift in Sources */,
@@ -865,6 +880,7 @@
865880
CAC281CD259F97FA00B8AB0B /* ObservingProgressIndicator.swift in Sources */,
866881
CABFA9C22592EEEA00380FEE /* Publisher+Resumable.swift in Sources */,
867882
CAFBDC68259A308B003DCC5A /* InfoPane.swift in Sources */,
883+
E87AB3C52939B65E00D72F43 /* Hardware.swift in Sources */,
868884
CAA1CB4D255A5CFD003FD669 /* SignInPhoneListView.swift in Sources */,
869885
CAFBDC6C259A3098003DCC5A /* View+Conditional.swift in Sources */,
870886
CABFA9CF2592EEEA00380FEE /* Process.swift in Sources */,
@@ -934,6 +950,8 @@
934950
A0187D39285792D1002F46F9 /* de */,
935951
7CBF284E28606D2C001AA66B /* uk */,
936952
5AA8A6102877EDAD009ECDB0 /* fi */,
953+
327DF109286ABE6B00D694D5 /* pt-BR */,
954+
E2AFDCCA28F024D000864ADD /* nl */,
937955
);
938956
name = Localizable.strings;
939957
sourceTree = "<group>";
@@ -1012,7 +1030,7 @@
10121030
CODE_SIGN_IDENTITY = "-";
10131031
CODE_SIGN_STYLE = Manual;
10141032
COMBINE_HIDPI_IMAGES = YES;
1015-
CURRENT_PROJECT_VERSION = 16;
1033+
CURRENT_PROJECT_VERSION = 17;
10161034
DEVELOPMENT_ASSET_PATHS = "\"Xcodes/Preview Content\"";
10171035
DEVELOPMENT_TEAM = "";
10181036
ENABLE_HARDENED_RUNTIME = NO;
@@ -1022,7 +1040,7 @@
10221040
"$(inherited)",
10231041
"@executable_path/../Frameworks",
10241042
);
1025-
MARKETING_VERSION = 1.8.0;
1043+
MARKETING_VERSION = 1.9.0;
10261044
PRODUCT_BUNDLE_IDENTIFIER = com.robotsandpencils.XcodesApp;
10271045
PRODUCT_NAME = Xcodes;
10281046
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1253,7 +1271,7 @@
12531271
CODE_SIGN_ENTITLEMENTS = Xcodes/Resources/Xcodes.entitlements;
12541272
CODE_SIGN_STYLE = Automatic;
12551273
COMBINE_HIDPI_IMAGES = YES;
1256-
CURRENT_PROJECT_VERSION = 16;
1274+
CURRENT_PROJECT_VERSION = 17;
12571275
DEVELOPMENT_ASSET_PATHS = "\"Xcodes/Preview Content\"";
12581276
DEVELOPMENT_TEAM = PBH8V487HB;
12591277
ENABLE_HARDENED_RUNTIME = YES;
@@ -1263,7 +1281,7 @@
12631281
"$(inherited)",
12641282
"@executable_path/../Frameworks",
12651283
);
1266-
MARKETING_VERSION = 1.8.0;
1284+
MARKETING_VERSION = 1.9.0;
12671285
PRODUCT_BUNDLE_IDENTIFIER = com.robotsandpencils.XcodesApp;
12681286
PRODUCT_NAME = Xcodes;
12691287
SWIFT_VERSION = 5.0;
@@ -1277,7 +1295,7 @@
12771295
CODE_SIGN_ENTITLEMENTS = Xcodes/Resources/Xcodes.entitlements;
12781296
CODE_SIGN_STYLE = Automatic;
12791297
COMBINE_HIDPI_IMAGES = YES;
1280-
CURRENT_PROJECT_VERSION = 16;
1298+
CURRENT_PROJECT_VERSION = 17;
12811299
DEVELOPMENT_ASSET_PATHS = "\"Xcodes/Preview Content\"";
12821300
DEVELOPMENT_TEAM = PBH8V487HB;
12831301
ENABLE_HARDENED_RUNTIME = YES;
@@ -1287,7 +1305,7 @@
12871305
"$(inherited)",
12881306
"@executable_path/../Frameworks",
12891307
);
1290-
MARKETING_VERSION = 1.8.0;
1308+
MARKETING_VERSION = 1.9.0;
12911309
PRODUCT_BUNDLE_IDENTIFIER = com.robotsandpencils.XcodesApp;
12921310
PRODUCT_NAME = Xcodes;
12931311
SWIFT_VERSION = 5.0;

Xcodes/Backend/AppState+Install.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ extension AppState {
4343

4444
Logger.appState.info("Using \(downloader) downloader")
4545

46-
return self.getXcodeArchive(installationType, downloader: downloader)
46+
return validateSession()
47+
.flatMap { _ in
48+
self.getXcodeArchive(installationType, downloader: downloader)
49+
}
4750
.flatMap { xcode, url -> AnyPublisher<InstalledXcode, Swift.Error> in
4851
self.installArchivedXcode(xcode, at: url)
4952
}
@@ -93,15 +96,12 @@ extension AppState {
9396
}
9497

9598
private func downloadXcode(availableXcode: AvailableXcode, downloader: Downloader) -> AnyPublisher<(AvailableXcode, URL), Error> {
96-
return validateADCSession(path: availableXcode.downloadPath)
97-
.flatMap { _ in
98-
return self.downloadOrUseExistingArchive(for: availableXcode, downloader: downloader, progressChanged: { [unowned self] progress in
99-
DispatchQueue.main.async {
100-
self.setInstallationStep(of: availableXcode.version, to: .downloading(progress: progress))
101-
}
102-
})
103-
.map { return (availableXcode, $0) }
104-
}
99+
self.downloadOrUseExistingArchive(for: availableXcode, downloader: downloader, progressChanged: { [unowned self] progress in
100+
DispatchQueue.main.async {
101+
self.setInstallationStep(of: availableXcode.version, to: .downloading(progress: progress))
102+
}
103+
})
104+
.map { return (availableXcode, $0) }
105105
.eraseToAnyPublisher()
106106
}
107107

@@ -513,7 +513,7 @@ public enum InstallationError: LocalizedError, Equatable {
513513
case .unexpectedCodeSigningIdentity(let identity, let certificateAuthority):
514514
return String(format: localizeString("InstallationError.UnexpectedCodeSigningIdentity"), identity, certificateAuthority, XcodeTeamIdentifier, XcodeCertificateAuthority)
515515
case .unsupportedFileFormat(let fileExtension):
516-
return String(format: localizeString("InstallationError.UnsuppoawwrtedFileFormat"), fileExtension)
516+
return String(format: localizeString("InstallationError.UnsupportedFileFormat"), fileExtension)
517517
case .missingSudoerPassword:
518518
return localizeString("InstallationError.MissingSudoerPassword")
519519
case let .unavailableVersion(version):

Xcodes/Backend/AppState.swift

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,12 @@ class AppState: ObservableObject {
9393
}
9494
}
9595
}
96-
96+
97+
@Published var showOpenInRosettaOption = false {
98+
didSet {
99+
Current.defaults.set(showOpenInRosettaOption, forKey: "showOpenInRosettaOption")
100+
}
101+
}
97102
// MARK: - Publisher Cancellables
98103

99104
var cancellables = Set<AnyCancellable>()
@@ -142,6 +147,7 @@ class AppState: ObservableObject {
142147
createSymLinkOnSelect = Current.defaults.bool(forKey: "createSymLinkOnSelect") ?? false
143148
onSelectActionType = SelectedActionType(rawValue: Current.defaults.string(forKey: "onSelectActionType") ?? "none") ?? .none
144149
installPath = Current.defaults.string(forKey: "installPath") ?? Path.defaultInstallDirectory.string
150+
showOpenInRosettaOption = Current.defaults.bool(forKey: "showOpenInRosettaOption") ?? false
145151
}
146152

147153
// MARK: Timer
@@ -381,7 +387,7 @@ class AppState: ObservableObject {
381387
case .apple:
382388
install(id: id)
383389
case .xcodeReleases:
384-
installWithoutLogin(id: id)
390+
install(id: id)
385391
}
386392
}
387393

@@ -454,6 +460,7 @@ class AppState: ObservableObject {
454460
}
455461

456462
/// Skips using the username/password to log in to Apple, and simply gets a Auth Cookie used in downloading
463+
/// As of Nov 2022 this was returning a 403 forbidden
457464
func installWithoutLogin(id: Xcode.ID) {
458465
guard let availableXcode = availableXcodes.first(where: { $0.version == id }) else { return }
459466

@@ -584,13 +591,18 @@ class AppState: ObservableObject {
584591
)
585592
}
586593

587-
func open(xcode: Xcode) {
594+
func open(xcode: Xcode, openInRosetta: Bool? = false) {
588595
switch xcode.installState {
589-
case let .installed(path):
590-
NSWorkspace.shared.openApplication(at: path.url, configuration: .init())
591-
default:
592-
Logger.appState.error("\(xcode.id) is not installed")
593-
return
596+
case let .installed(path):
597+
let config = NSWorkspace.OpenConfiguration.init()
598+
if (openInRosetta ?? false) {
599+
config.architecture = CPU_TYPE_X86_64
600+
}
601+
config.allowsRunningApplicationSubstitution = false
602+
NSWorkspace.shared.openApplication(at: path.url, configuration: config)
603+
default:
604+
Logger.appState.error("\(xcode.id) is not installed")
605+
return
594606
}
595607
}
596608

@@ -609,10 +621,10 @@ class AppState: ObservableObject {
609621
NSPasteboard.general.setString(url.absoluteString, forType: .string)
610622
}
611623

612-
func createSymbolicLink(xcode: Xcode) {
624+
func createSymbolicLink(xcode: Xcode, isBeta: Bool = false) {
613625
guard let installedXcodePath = xcode.installedPath else { return }
614626

615-
let destinationPath: Path = Path.installDirectory/"Xcode.app"
627+
let destinationPath: Path = Path.installDirectory/"Xcode\(isBeta ? "-Beta" : "").app"
616628

617629
// does an Xcode.app file exist?
618630
if FileManager.default.fileExists(atPath: destinationPath.string) {
@@ -634,7 +646,7 @@ class AppState: ObservableObject {
634646

635647
do {
636648
try FileManager.default.createSymbolicLink(atPath: destinationPath.string, withDestinationPath: installedXcodePath.string)
637-
Logger.appState.info("Successfully created symbolic link with Xcode.app")
649+
Logger.appState.info("Successfully created symbolic link with Xcode\(isBeta ? "-Beta": "").app")
638650
} catch {
639651
Logger.appState.error("Unable to create symbolic Link")
640652
self.error = error

Xcodes/Backend/FileError.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//
2+
// FileError.swift
3+
// Xcodes
4+
//
5+
// Created by Leon Wolf on 06.10.22.
6+
// Copyright © 2022 Robots and Pencils. All rights reserved.
7+
//
8+
9+
import Foundation
10+
import LegibleError
11+
12+
enum FileError: LocalizedError{
13+
case fileNotFound(_ fileName: String)
14+
}
15+
16+
extension FileError {
17+
var errorDescription: String? {
18+
switch self {
19+
case .fileNotFound(let fileName):
20+
return String(format: localizeString("Alert.Uninstall.Error.Message.FileNotFound"), fileName)
21+
}
22+
}
23+
}

0 commit comments

Comments
 (0)