diff --git a/Passepartout-iOS/Cells/SettingTableViewCell.swift b/Passepartout-iOS/Cells/SettingTableViewCell.swift index 3ac550e0..d4108c6e 100644 --- a/Passepartout-iOS/Cells/SettingTableViewCell.swift +++ b/Passepartout-iOS/Cells/SettingTableViewCell.swift @@ -80,6 +80,7 @@ extension SettingTableViewCell { func dequeue(from tableView: UITableView, for indexPath: IndexPath) -> SettingTableViewCell { let cell = tableView.dequeue(T.self, identifier: Provider.identifier, for: indexPath) cell.apply(Theme.current) + cell.imageView?.image = nil cell.rightText = nil cell.isTappable = true cell.accessoryType = .disclosureIndicator diff --git a/Passepartout-iOS/Global/SwiftGen+Assets.swift b/Passepartout-iOS/Global/SwiftGen+Assets.swift new file mode 100644 index 00000000..f63d553a --- /dev/null +++ b/Passepartout-iOS/Global/SwiftGen+Assets.swift @@ -0,0 +1,112 @@ +// swiftlint:disable all +// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen + +#if os(OSX) + import AppKit.NSImage + internal typealias AssetColorTypeAlias = NSColor + internal typealias AssetImageTypeAlias = NSImage +#elseif os(iOS) || os(tvOS) || os(watchOS) + import UIKit.UIImage + internal typealias AssetColorTypeAlias = UIColor + internal typealias AssetImageTypeAlias = UIImage +#endif + +// swiftlint:disable superfluous_disable_command +// swiftlint:disable file_length + +// MARK: - Asset Catalogs + +// swiftlint:disable identifier_name line_length nesting type_body_length type_name +internal enum Asset { + internal static let logo = ImageAsset(name: "logo") + internal static let mullvad = ImageAsset(name: "mullvad") + internal static let pia = ImageAsset(name: "pia") + internal static let tunnelbear = ImageAsset(name: "tunnelbear") + internal static let windscribe = ImageAsset(name: "windscribe") +} +// swiftlint:enable identifier_name line_length nesting type_body_length type_name + +// MARK: - Implementation Details + +internal struct ColorAsset { + internal fileprivate(set) var name: String + + @available(iOS 11.0, tvOS 11.0, watchOS 4.0, OSX 10.13, *) + internal var color: AssetColorTypeAlias { + return AssetColorTypeAlias(asset: self) + } +} + +internal extension AssetColorTypeAlias { + @available(iOS 11.0, tvOS 11.0, watchOS 4.0, OSX 10.13, *) + convenience init!(asset: ColorAsset) { + let bundle = Bundle(for: BundleToken.self) + #if os(iOS) || os(tvOS) + self.init(named: asset.name, in: bundle, compatibleWith: nil) + #elseif os(OSX) + self.init(named: NSColor.Name(asset.name), bundle: bundle) + #elseif os(watchOS) + self.init(named: asset.name) + #endif + } +} + +internal struct DataAsset { + internal fileprivate(set) var name: String + + #if os(iOS) || os(tvOS) || os(OSX) + @available(iOS 9.0, tvOS 9.0, OSX 10.11, *) + internal var data: NSDataAsset { + return NSDataAsset(asset: self) + } + #endif +} + +#if os(iOS) || os(tvOS) || os(OSX) +@available(iOS 9.0, tvOS 9.0, OSX 10.11, *) +internal extension NSDataAsset { + convenience init!(asset: DataAsset) { + let bundle = Bundle(for: BundleToken.self) + #if os(iOS) || os(tvOS) + self.init(name: asset.name, bundle: bundle) + #elseif os(OSX) + self.init(name: NSDataAsset.Name(asset.name), bundle: bundle) + #endif + } +} +#endif + +internal struct ImageAsset { + internal fileprivate(set) var name: String + + internal var image: AssetImageTypeAlias { + let bundle = Bundle(for: BundleToken.self) + #if os(iOS) || os(tvOS) + let image = AssetImageTypeAlias(named: name, in: bundle, compatibleWith: nil) + #elseif os(OSX) + let image = bundle.image(forResource: NSImage.Name(name)) + #elseif os(watchOS) + let image = AssetImageTypeAlias(named: name) + #endif + guard let result = image else { fatalError("Unable to load image named \(name).") } + return result + } +} + +internal extension AssetImageTypeAlias { + @available(iOS 1.0, tvOS 1.0, watchOS 1.0, *) + @available(OSX, deprecated, + message: "This initializer is unsafe on macOS, please use the ImageAsset.image property") + convenience init!(asset: ImageAsset) { + #if os(iOS) || os(tvOS) + let bundle = Bundle(for: BundleToken.self) + self.init(named: asset.name, in: bundle, compatibleWith: nil) + #elseif os(OSX) + self.init(named: NSImage.Name(asset.name)) + #elseif os(watchOS) + self.init(named: asset.name) + #endif + } +} + +private final class BundleToken {} diff --git a/Passepartout-iOS/Global/Theme.swift b/Passepartout-iOS/Global/Theme.swift index de173668..607706d5 100644 --- a/Passepartout-iOS/Global/Theme.swift +++ b/Passepartout-iOS/Global/Theme.swift @@ -153,3 +153,18 @@ extension MFMailComposeViewController { bar.largeTitleTextAttributes = bar.titleTextAttributes } } + +extension Infrastructure.Name { + private static let allLogos: [Infrastructure.Name: ImageAsset] = { + var logos: [Infrastructure.Name: ImageAsset] = [:] + logos[.mullvad] = Asset.mullvad + logos[.pia] = Asset.pia + logos[.tunnelBear] = Asset.tunnelbear + logos[.windscribe] = Asset.windscribe + return logos + }() + + var logo: UIImage? { + return Infrastructure.Name.allLogos[self]?.image + } +} diff --git a/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift b/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift index 66d2f3f9..1a28a907 100644 --- a/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift +++ b/Passepartout-iOS/Scenes/Organizer/OrganizerViewController.swift @@ -347,6 +347,11 @@ extension OrganizerViewController { case .profile: let cell = Cells.setting.dequeue(from: tableView, for: indexPath) let rowProfile = profileKey(at: indexPath) + if rowProfile.context == .provider, let providerName = Infrastructure.Name(rawValue: rowProfile.id) { + cell.imageView?.image = providerName.logo + } else { + cell.imageView?.image = nil + } cell.leftText = rowProfile.id cell.rightText = service.isActiveProfile(rowProfile) ? L10n.Organizer.Cells.Profile.Value.current : nil return cell diff --git a/Passepartout-iOS/Scenes/Organizer/WizardProviderViewController.swift b/Passepartout-iOS/Scenes/Organizer/WizardProviderViewController.swift index 537bee7c..097e24f7 100644 --- a/Passepartout-iOS/Scenes/Organizer/WizardProviderViewController.swift +++ b/Passepartout-iOS/Scenes/Organizer/WizardProviderViewController.swift @@ -74,6 +74,7 @@ extension WizardProviderViewController { override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let name = availableNames[indexPath.row] let cell = Cells.setting.dequeue(from: tableView, for: indexPath) + cell.imageView?.image = name.logo cell.leftText = name.rawValue return cell } diff --git a/Passepartout.xcodeproj/project.pbxproj b/Passepartout.xcodeproj/project.pbxproj index e5003f79..89013bf3 100644 --- a/Passepartout.xcodeproj/project.pbxproj +++ b/Passepartout.xcodeproj/project.pbxproj @@ -82,6 +82,7 @@ 0EB60FDA2111136E00AD27F3 /* UITextView+Search.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB60FD92111136E00AD27F3 /* UITextView+Search.swift */; }; 0EB67D6B2184581E00BA6200 /* ImportedHostsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EB67D6A2184581E00BA6200 /* ImportedHostsViewController.swift */; }; 0EBE3A79213C4E5500BFA2F5 /* OrganizerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EBE3A78213C4E5400BFA2F5 /* OrganizerViewController.swift */; }; + 0ECC60DE2256B68A0020BEAC /* SwiftGen+Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ECC60DD2256B6890020BEAC /* SwiftGen+Assets.swift */; }; 0ECEB10A224FECEA00E9E551 /* DataUnit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ECEB109224FECEA00E9E551 /* DataUnit.swift */; }; 0ECEB10C224FEF9B00E9E551 /* UtilsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ECEB10B224FEF9B00E9E551 /* UtilsTests.swift */; }; 0ECEE44E20E1122200A6BB43 /* TableModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ECEE44D20E1122200A6BB43 /* TableModel.swift */; }; @@ -223,6 +224,7 @@ 0EBE3AA3213DC1B000BFA2F5 /* HostConnectionProfile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HostConnectionProfile.swift; sourceTree = ""; }; 0EBE3AA4213DC1B000BFA2F5 /* ProviderConnectionProfile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProviderConnectionProfile.swift; sourceTree = ""; }; 0EC7F20420E24308004EA58E /* DebugLog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugLog.swift; sourceTree = ""; }; + 0ECC60DD2256B6890020BEAC /* SwiftGen+Assets.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SwiftGen+Assets.swift"; sourceTree = ""; }; 0ECEB104224FE51400E9E551 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; name = Base; path = Base.lproj/Intents.intentdefinition; sourceTree = ""; }; 0ECEB105224FE51400E9E551 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 0ECEB106224FE51400E9E551 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Organizer.storyboard; sourceTree = ""; }; @@ -513,6 +515,7 @@ 0E4FD7F020D58618002221FF /* Macros.swift */, 0ED38AE9214054A50004D387 /* OptionViewController.swift */, 0EA068F3218475F800C320AD /* ConfigurationParserResult+Alerts.swift */, + 0ECC60DD2256B6890020BEAC /* SwiftGen+Assets.swift */, 0EDE8DE320C89028004C739C /* SwiftGen+Scenes.swift */, 0EF56BBA2185AC8500B0C8AB /* SwiftGen+Segues.swift */, 0E05C61C20D27C82006EE732 /* Theme.swift */, @@ -1012,6 +1015,7 @@ 0E05C5D420D1645F006EE732 /* FieldTableViewCell.swift in Sources */, 0E36D25C224034AD006AF062 /* ShortcutsConnectToViewController.swift in Sources */, 0E05C61D20D27C82006EE732 /* Theme.swift in Sources */, + 0ECC60DE2256B68A0020BEAC /* SwiftGen+Assets.swift in Sources */, 0ED38AEC2141260D0004D387 /* ConfigurationModificationDelegate.swift in Sources */, 0ECEE45020E1182E00A6BB43 /* Theme+Cells.swift in Sources */, 0E1066C920E0F84A004F98B7 /* Cells.swift in Sources */, diff --git a/swiftgen.yml b/swiftgen.yml index 7d27814e..d7835c16 100644 --- a/swiftgen.yml +++ b/swiftgen.yml @@ -17,3 +17,10 @@ ib: output: Passepartout-iOS/Global/SwiftGen+Scenes.swift - templateName: segues-swift4 output: Passepartout-iOS/Global/SwiftGen+Segues.swift + +xcassets: + inputs: + - Passepartout-iOS/Assets.xcassets + outputs: + - templateName: swift4 + output: Passepartout-iOS/Global/SwiftGen+Assets.swift