diff --git a/ElementX.xcodeproj/project.pbxproj b/ElementX.xcodeproj/project.pbxproj index aa0c8cb02..b73cf8833 100644 --- a/ElementX.xcodeproj/project.pbxproj +++ b/ElementX.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 52; objects = { /* Begin PBXBuildFile section */ @@ -80,13 +80,13 @@ 7C72B61B30B41D76953237A8 /* ActivityRequest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9525FEE63EBF02C97161BF7D /* ActivityRequest.swift */; }; 7C9121245B11CA48307CB462 /* LoginScreenViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8FD25EB4DF66625B74E4505 /* LoginScreenViewModel.swift */; }; 7D1DAAA364A9A29D554BD24E /* PlaceholderAvatarImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0950733DD4BA83EEE752E259 /* PlaceholderAvatarImage.swift */; }; - 7D6B663407C8C73EEC100E35 /* Colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 93D5B393E3450F26C015FEFE /* Colors.swift */; }; 7DE5EB4CB2401C672257283C /* WeakKeyDictionary.swift in Sources */ = {isa = PBXBuildFile; fileRef = B12969CEC0051BC750DA5068 /* WeakKeyDictionary.swift */; }; 7F19E97E7985F518C9018B83 /* RootRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = CF47564C584F614B7287F3EB /* RootRouter.swift */; }; 8810A2A30A68252EBB54EE05 /* HomeScreenModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71BC7CA1BC1041E93077BBA1 /* HomeScreenModels.swift */; }; 8BBD3AA589DEE02A1B0923B2 /* NoticeRoomTimelineItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F49CDE349C490D617332770 /* NoticeRoomTimelineItem.swift */; }; 8CC12086CBF91A7E10CDC205 /* HomeScreenCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D653265D006E708E4E51AD64 /* HomeScreenCoordinator.swift */; }; 90DF83A6A347F7EE7EDE89EE /* AttributedStringBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF25E364AE85090A70AE4644 /* AttributedStringBuilderTests.swift */; }; + 90EB25D13AE6EEF034BDE9D2 /* Assets.swift in Sources */ = {isa = PBXBuildFile; fileRef = 71D52BAA5BADB06E5E8C295D /* Assets.swift */; }; 93BA4A81B6D893271101F9F0 /* SwiftyBeaver in Frameworks */ = {isa = PBXBuildFile; productRef = FD43A50D9B75C9D6D30F006B /* SwiftyBeaver */; }; 964B9D2EC38C488C360CE0C9 /* HomeScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = B902EA6CD3296B0E10EE432B /* HomeScreen.swift */; }; 9B8DE1D424E37581C7D99CCC /* RoomTimelineControllerProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = CC7CCC6DE5FA623E31BA8546 /* RoomTimelineControllerProtocol.swift */; }; @@ -215,6 +215,7 @@ 6EA1D2CBAEA5D0BD00B90D1B /* BindableState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BindableState.swift; sourceTree = ""; }; 6F3DFE5B444F131648066F05 /* StateStoreViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StateStoreViewModel.swift; sourceTree = ""; }; 71BC7CA1BC1041E93077BBA1 /* HomeScreenModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreenModels.swift; sourceTree = ""; }; + 71D52BAA5BADB06E5E8C295D /* Assets.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Assets.swift; sourceTree = ""; }; 72F37B5DA798C9AE436F2C2C /* AttributedStringBuilderProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedStringBuilderProtocol.swift; sourceTree = ""; }; 752DEC02D93AFF46BC13313A /* NavigationRouterType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationRouterType.swift; sourceTree = ""; }; 7D0CBC76C80E04345E11F2DB /* Application.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Application.swift; sourceTree = ""; }; @@ -232,7 +233,6 @@ 90733775209F4D4D366A268F /* RootRouterType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootRouterType.swift; sourceTree = ""; }; 92B61C243325DC76D3086494 /* EventBriefFactoryProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventBriefFactoryProtocol.swift; sourceTree = ""; }; 93CF7B19FFCF8EFBE0A8696A /* RoomScreenViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomScreenViewModelTests.swift; sourceTree = ""; }; - 93D5B393E3450F26C015FEFE /* Colors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Colors.swift; sourceTree = ""; }; 9525FEE63EBF02C97161BF7D /* ActivityRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityRequest.swift; sourceTree = ""; }; 956BDA4AE16429AD015661A8 /* KeychainControllerProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainControllerProtocol.swift; sourceTree = ""; }; 95CC95CD75B688E946438165 /* Coordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Coordinator.swift; sourceTree = ""; }; @@ -366,6 +366,14 @@ path = SupportingFiles; sourceTree = ""; }; + 337015ADFBA3AB96660DB3A6 /* Generated */ = { + isa = PBXGroup; + children = ( + 71D52BAA5BADB06E5E8C295D /* Assets.swift */, + ); + path = Generated; + sourceTree = ""; + }; 33996F58948B54839D653EC1 /* Members */ = { isa = PBXGroup; children = ( @@ -675,7 +683,6 @@ children = ( 49EAD710A2C16EFF7C3EA16F /* Benchmark.swift */, E5272BC4A60B6AD7553BACA1 /* BlurHashDecode.swift */, - 93D5B393E3450F26C015FEFE /* Colors.swift */, 95CC95CD75B688E946438165 /* Coordinator.swift */, F7B81C8227BBEA95CCE86037 /* MatrixEntitityRegex.swift */, 64839516BD56D1C81D84C5E0 /* MXLog.swift */, @@ -713,6 +720,7 @@ children = ( CF3EDF23226895776553F04A /* AppCoordinator.swift */, EFFA5FD06AAAC4AF544B594E /* AppDelegate.swift */, + 337015ADFBA3AB96660DB3A6 /* Generated */, C0937E3B06A8F0E2DB7C8241 /* Other */, E59565F441830B19DBAE567C /* Screens */, 0787F81684E503024BD0C051 /* Services */, @@ -793,6 +801,7 @@ 215E1D91B98672C856F559D0 /* Resources */, EE878EAA342710DB973E0A87 /* Frameworks */, 98CA896D84BFD53B2554E891 /* ⚠️ SwiftLint */, + A7130911BCB2DF3D249A1836 /* 🛠 SwiftGen */, ); buildRules = ( ); @@ -905,6 +914,24 @@ shellPath = /bin/sh; shellScript = "export PATH=\"$PATH:/opt/homebrew/bin\"\nif which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; }; + A7130911BCB2DF3D249A1836 /* 🛠 SwiftGen */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "🛠 SwiftGen"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "export PATH=\"$PATH:/opt/homebrew/bin\"\nif which swiftgen >/dev/null; then\n swiftgen config run --config Tools/SwiftGen/swiftgen-config.yml\nelse\n echo \"warning: SwiftGen not installed, download from https://github.com/SwiftGen/SwiftGen\"\nfi\n"; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -931,13 +958,13 @@ 7C72B61B30B41D76953237A8 /* ActivityRequest.swift in Sources */, A636D4900E0D98ED91536482 /* AppCoordinator.swift in Sources */, 2FE4EEF780553B25A446BBFB /* AppDelegate.swift in Sources */, + 90EB25D13AE6EEF034BDE9D2 /* Assets.swift in Sources */, 3ED2725734568F6B8CC87544 /* AttributedStringBuilder.swift in Sources */, A6DEC1ADEC8FEEC206A0FA37 /* AttributedStringBuilderProtocol.swift in Sources */, A69B7B421C28C6CDEBBD0613 /* AuthenticationCoordinator.swift in Sources */, CB326BAB54E9B68658909E36 /* Benchmark.swift in Sources */, 38546A6010A2CF240EC9AF73 /* BindableState.swift in Sources */, B6DF6B6FA8734B70F9BF261E /* BlurHashDecode.swift in Sources */, - 7D6B663407C8C73EEC100E35 /* Colors.swift in Sources */, DCB781BD227CA958809AFADF /* Coordinator.swift in Sources */, C4F69156C31A447FEFF2A47C /* DTHTMLElement+AttributedStringBuilder.swift in Sources */, EE8491AD81F47DF3C192497B /* DecorationTimelineItemProtocol.swift in Sources */, diff --git a/ElementX/Sources/Generated/Assets.swift b/ElementX/Sources/Generated/Assets.swift new file mode 100644 index 000000000..566827f6b --- /dev/null +++ b/ElementX/Sources/Generated/Assets.swift @@ -0,0 +1,147 @@ +// swiftlint:disable all +// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen + +#if os(macOS) + import AppKit +#elseif os(iOS) + import UIKit +#elseif os(tvOS) || os(watchOS) + import UIKit +#endif + +// Deprecated typealiases +@available(*, deprecated, renamed: "ColorAsset.Color", message: "This typealias will be removed in SwiftGen 7.0") +internal typealias AssetColorTypeAlias = ColorAsset.Color +@available(*, deprecated, renamed: "ImageAsset.Image", message: "This typealias will be removed in SwiftGen 7.0") +internal typealias AssetImageTypeAlias = ImageAsset.Image + +// swiftlint:disable superfluous_disable_command file_length implicit_return + +// MARK: - Asset Catalogs + +// swiftlint:disable identifier_name line_length nesting type_body_length type_name +internal enum Asset { + internal enum Colors { + internal static let codeBlockBackground = ColorAsset(name: "Colors/CodeBlockBackground") + internal static let elementGreen = ColorAsset(name: "Colors/ElementGreen") + } + internal enum Images { + internal static let appLogo = ImageAsset(name: "Images/app-logo") + } +} +// swiftlint:enable identifier_name line_length nesting type_body_length type_name + +// MARK: - Implementation Details + +internal final class ColorAsset { + internal fileprivate(set) var name: String + + #if os(macOS) + internal typealias Color = NSColor + #elseif os(iOS) || os(tvOS) || os(watchOS) + internal typealias Color = UIColor + #endif + + @available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, *) + internal private(set) lazy var color: Color = { + guard let color = Color(asset: self) else { + fatalError("Unable to load color asset named \(name).") + } + return color + }() + + #if os(iOS) || os(tvOS) + @available(iOS 11.0, tvOS 11.0, *) + internal func color(compatibleWith traitCollection: UITraitCollection) -> Color { + let bundle = BundleToken.bundle + guard let color = Color(named: name, in: bundle, compatibleWith: traitCollection) else { + fatalError("Unable to load color asset named \(name).") + } + return color + } + #endif + + fileprivate init(name: String) { + self.name = name + } +} + +internal extension ColorAsset.Color { + @available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, *) + convenience init?(asset: ColorAsset) { + let bundle = BundleToken.bundle + #if os(iOS) || os(tvOS) + self.init(named: asset.name, in: bundle, compatibleWith: nil) + #elseif os(macOS) + self.init(named: NSColor.Name(asset.name), bundle: bundle) + #elseif os(watchOS) + self.init(named: asset.name) + #endif + } +} + +internal struct ImageAsset { + internal fileprivate(set) var name: String + + #if os(macOS) + internal typealias Image = NSImage + #elseif os(iOS) || os(tvOS) || os(watchOS) + internal typealias Image = UIImage + #endif + + @available(iOS 8.0, tvOS 9.0, watchOS 2.0, macOS 10.7, *) + internal var image: Image { + let bundle = BundleToken.bundle + #if os(iOS) || os(tvOS) + let image = Image(named: name, in: bundle, compatibleWith: nil) + #elseif os(macOS) + let name = NSImage.Name(self.name) + let image = (bundle == .main) ? NSImage(named: name) : bundle.image(forResource: name) + #elseif os(watchOS) + let image = Image(named: name) + #endif + guard let result = image else { + fatalError("Unable to load image asset named \(name).") + } + return result + } + + #if os(iOS) || os(tvOS) + @available(iOS 8.0, tvOS 9.0, *) + internal func image(compatibleWith traitCollection: UITraitCollection) -> Image { + let bundle = BundleToken.bundle + guard let result = Image(named: name, in: bundle, compatibleWith: traitCollection) else { + fatalError("Unable to load image asset named \(name).") + } + return result + } + #endif +} + +internal extension ImageAsset.Image { + @available(iOS 8.0, tvOS 9.0, watchOS 2.0, *) + @available(macOS, 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 = BundleToken.bundle + self.init(named: asset.name, in: bundle, compatibleWith: nil) + #elseif os(macOS) + self.init(named: NSImage.Name(asset.name)) + #elseif os(watchOS) + self.init(named: asset.name) + #endif + } +} + +// swiftlint:disable convenience_type +private final class BundleToken { + static let bundle: Bundle = { + #if SWIFT_PACKAGE + return Bundle.module + #else + return Bundle(for: BundleToken.self) + #endif + }() +} +// swiftlint:enable convenience_type diff --git a/ElementX/Sources/Other/Colors.swift b/ElementX/Sources/Other/Colors.swift deleted file mode 100644 index b72aeec3a..000000000 --- a/ElementX/Sources/Other/Colors.swift +++ /dev/null @@ -1,37 +0,0 @@ -// -// Colors.swift -// ElementX -// -// Created by Stefan Ceriu on 29/03/2022. -// Copyright © 2022 Element. All rights reserved. -// - -import Foundation -import UIKit -import SwiftUI - -// TODO: Switch this to SwiftGen - -extension Color { - static let elementGreen = Color(ColorNames.elementGreen.rawValue) - static let codeBlockBackgroundColor = Color(ColorNames.codeBlockBackgroundColor.rawValue) -} - -extension UIColor { - static let elementGreen = UIColor(named: ColorNames.elementGreen.rawValue) - static let codeBlockBackgroundColor = UIColor(named: ColorNames.codeBlockBackgroundColor.rawValue) -} - -private enum ColorNames: String { - case elementGreen - case codeBlockBackgroundColor - - var rawValue: String { - switch self { - case .elementGreen: - return "ElementGreen" - case .codeBlockBackgroundColor: - return "CodeBlockBackgroundColor" - } - } -} diff --git a/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilder.swift b/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilder.swift index 5543a4cd7..1578a4f92 100644 --- a/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilder.swift +++ b/ElementX/Sources/Other/HTMLParsing/AttributedStringBuilder.swift @@ -140,7 +140,7 @@ struct AttributedStringBuilder: AttributedStringBuilderProtocol { attributedString.enumerateAttribute(.backgroundColor, in: .init(location: 0, length: attributedString.length), options: []) { value, range, _ in if let value = value as? UIColor, value == temporaryCodeBlockMarkingColor { - attributedString.addAttribute(.backgroundColor, value: UIColor.codeBlockBackgroundColor as Any, range: range) + attributedString.addAttribute(.backgroundColor, value: Asset.Colors.codeBlockBackground.color as Any, range: range) } } } diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/EventBasedTimelineView.swift b/ElementX/Sources/Screens/RoomScreen/View/Timeline/EventBasedTimelineView.swift index 46a7c39f3..5d31f7ddb 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/EventBasedTimelineView.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/Timeline/EventBasedTimelineView.swift @@ -31,7 +31,7 @@ struct EventBasedTimelineView: View { Image(uiImage: avatar) .resizable() .scaledToFill() - .overlay(Circle().stroke(Color.elementGreen)) + .overlay(Circle().stroke(Color(uiColor: Asset.Colors.elementGreen.color))) } else { PlaceholderAvatarImage(firstCharacter: String(firstLetter)) } diff --git a/ElementX/Sources/Screens/RoomScreen/View/Timeline/FormattedBodyText.swift b/ElementX/Sources/Screens/RoomScreen/View/Timeline/FormattedBodyText.swift index 3051c7bf6..ce8676b96 100644 --- a/ElementX/Sources/Screens/RoomScreen/View/Timeline/FormattedBodyText.swift +++ b/ElementX/Sources/Screens/RoomScreen/View/Timeline/FormattedBodyText.swift @@ -29,7 +29,7 @@ struct FormattedBodyText: View { } } } - .tint(.elementGreen) + .tint(Color(uiColor: Asset.Colors.elementGreen.color)) } } diff --git a/ElementX/SupportingFiles/Assets.xcassets/Colors/CodeBlockBackgroundColor.colorset/Contents.json b/ElementX/SupportingFiles/Assets.xcassets/Colors/CodeBlockBackground.colorset/Contents.json similarity index 100% rename from ElementX/SupportingFiles/Assets.xcassets/Colors/CodeBlockBackgroundColor.colorset/Contents.json rename to ElementX/SupportingFiles/Assets.xcassets/Colors/CodeBlockBackground.colorset/Contents.json diff --git a/ElementX/SupportingFiles/Assets.xcassets/Colors/Contents.json b/ElementX/SupportingFiles/Assets.xcassets/Colors/Contents.json index 73c00596a..6e965652d 100644 --- a/ElementX/SupportingFiles/Assets.xcassets/Colors/Contents.json +++ b/ElementX/SupportingFiles/Assets.xcassets/Colors/Contents.json @@ -2,5 +2,8 @@ "info" : { "author" : "xcode", "version" : 1 + }, + "properties" : { + "provides-namespace" : true } } diff --git a/ElementX/SupportingFiles/Assets.xcassets/Images/Contents.json b/ElementX/SupportingFiles/Assets.xcassets/Images/Contents.json new file mode 100644 index 000000000..6e965652d --- /dev/null +++ b/ElementX/SupportingFiles/Assets.xcassets/Images/Contents.json @@ -0,0 +1,9 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "provides-namespace" : true + } +} diff --git a/ElementX/SupportingFiles/Assets.xcassets/app-logo.imageset/Contents.json b/ElementX/SupportingFiles/Assets.xcassets/Images/app-logo.imageset/Contents.json similarity index 100% rename from ElementX/SupportingFiles/Assets.xcassets/app-logo.imageset/Contents.json rename to ElementX/SupportingFiles/Assets.xcassets/Images/app-logo.imageset/Contents.json diff --git a/ElementX/SupportingFiles/Assets.xcassets/app-logo.imageset/launch_screen_logo.png b/ElementX/SupportingFiles/Assets.xcassets/Images/app-logo.imageset/launch_screen_logo.png similarity index 100% rename from ElementX/SupportingFiles/Assets.xcassets/app-logo.imageset/launch_screen_logo.png rename to ElementX/SupportingFiles/Assets.xcassets/Images/app-logo.imageset/launch_screen_logo.png diff --git a/ElementX/SupportingFiles/Assets.xcassets/app-logo.imageset/launch_screen_logo@2x.png b/ElementX/SupportingFiles/Assets.xcassets/Images/app-logo.imageset/launch_screen_logo@2x.png similarity index 100% rename from ElementX/SupportingFiles/Assets.xcassets/app-logo.imageset/launch_screen_logo@2x.png rename to ElementX/SupportingFiles/Assets.xcassets/Images/app-logo.imageset/launch_screen_logo@2x.png diff --git a/ElementX/SupportingFiles/Assets.xcassets/app-logo.imageset/launch_screen_logo@3x.png b/ElementX/SupportingFiles/Assets.xcassets/Images/app-logo.imageset/launch_screen_logo@3x.png similarity index 100% rename from ElementX/SupportingFiles/Assets.xcassets/app-logo.imageset/launch_screen_logo@3x.png rename to ElementX/SupportingFiles/Assets.xcassets/Images/app-logo.imageset/launch_screen_logo@3x.png diff --git a/ElementX/SupportingFiles/target.yml b/ElementX/SupportingFiles/target.yml index ce1f2df62..cff948207 100644 --- a/ElementX/SupportingFiles/target.yml +++ b/ElementX/SupportingFiles/target.yml @@ -60,6 +60,16 @@ targets: else echo "warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint" fi + - name: 🛠 SwiftGen + runOnlyWhenInstalling: false + shell: /bin/sh + script: | + export PATH="$PATH:/opt/homebrew/bin" + if which swiftgen >/dev/null; then + swiftgen config run --config Tools/SwiftGen/swiftgen-config.yml + else + echo "warning: SwiftGen not installed, download from https://github.com/SwiftGen/SwiftGen" + fi dependencies: - package: MatrixRustSDK diff --git a/Tools/SwiftGen/swiftgen-config.yml b/Tools/SwiftGen/swiftgen-config.yml new file mode 100755 index 000000000..bd18fdcda --- /dev/null +++ b/Tools/SwiftGen/swiftgen-config.yml @@ -0,0 +1,8 @@ +input_dir: ../../ElementX/ +output_dir: ../../ElementX/Sources/Generated/ +xcassets: + inputs: + - SupportingFiles/Assets.xcassets + outputs: + templateName: swift5 + output: Assets.swift