diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index cc92e93..0000000 Binary files a/.DS_Store and /dev/null differ diff --git a/iOS/Features/JourneyList/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/iOS/Features/JourneyList/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/iOS/Features/JourneyList/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/iOS/MSUIKit/Package.swift b/iOS/MSUIKit/Package.swift index 7254471..0e5acca 100644 --- a/iOS/MSUIKit/Package.swift +++ b/iOS/MSUIKit/Package.swift @@ -8,8 +8,8 @@ import PackageDescription extension String { static let package = "MSUIKit" static let designSystem = "MSDesignSystem" - static let components = "MSUIComponents" - + static let uiKit = "MSUIKit" + var testTarget: String { return self + "Tests" } @@ -24,15 +24,20 @@ let package = Package( ], products: [ .library(name: .designSystem, + type: .static, targets: [.designSystem]), - .library(name: .components, - targets: [.components]) + .library(name: .uiKit, + targets: [.uiKit]) ], targets: [ // Codes - .target(name: .designSystem), - .target(name: .components, - dependencies: [.target(name: .designSystem)]), + .target(name: .designSystem, + resources: [ + .process("../MSDesignSystem/Resources") + ]), + .target(name: .uiKit, + dependencies: ["MSDesignSystem"]), + // Tests .testTarget(name: .designSystem.testTarget, dependencies: ["MSDesignSystem"]) diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/MSColor.swift b/iOS/MSUIKit/Sources/MSDesignSystem/MSColor.swift new file mode 100644 index 0000000..4a901e4 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/MSColor.swift @@ -0,0 +1,30 @@ +// +// MSColor.swift +// MSUIKit +// +// Created by 이창준 on 11/19/23. +// + +import UIKit + +public enum MSColor: String { + case primaryBackground = "Background Primary" + case secondaryBackground = "Background Secondary" + case primaryButtonBackground = "Button Background Primary" + case secondaryButtonBackground = "Button Background Secondary" + + case primaryTypo = "Typo Primary" + case primaryButtonTypo = "Button Typo Primary" + case secondaryTypo = "Typo Secondary" + case secondaryButtonTypo = "Button Typo Secondary" + + case musicSpot = "MusicSpot" +} + +extension UIColor { + + public static func msColor(_ color: MSColor) -> UIColor { + return UIColor(named: color.rawValue, in: .module, compatibleWith: .current)! + } + +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/MSDesignSystem.swift b/iOS/MSUIKit/Sources/MSDesignSystem/MSDesignSystem.swift deleted file mode 100644 index bbcc51f..0000000 --- a/iOS/MSUIKit/Sources/MSDesignSystem/MSDesignSystem.swift +++ /dev/null @@ -1,8 +0,0 @@ -// -// MSDesignSystem.swift -// MSUIKit -// -// Created by 이창준 on 11/14/23. -// - -import UIKit diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/MSFont.swift b/iOS/MSUIKit/Sources/MSDesignSystem/MSFont.swift new file mode 100644 index 0000000..721bd37 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/MSFont.swift @@ -0,0 +1,73 @@ +// +// MSFont.swift +// MSUIKit +// +// Created by 이창준 on 11/19/23. +// + +import UIKit + +public enum MSFont { + case superTitle + case duperTitle + case headerTitle + case subtitle + case buttonTitle + case paragraph + case caption + + // MARK: - Functions + + private var fontDetails: (fontName: String, size: CGFloat) { + switch self { + case .superTitle: return ("Pretendard-Bold", 34.0) + case .duperTitle: return ("Pretendard-Bold", 28.0) + case .headerTitle: return ("Pretendard-Bold", 22.0) + case .subtitle: return ("Pretendard-Bold", 20.0) + case .buttonTitle: return ("Pretendard-SemiBold", 20.0) + case .paragraph: return ("Pretendard-Regular", 17.0) + case .caption: return ("Pretendard-Regular", 13.0) + } + } + + internal func font() -> UIFont? { + let details = self.fontDetails + return UIFont(name: details.fontName, size: details.size) + } + + fileprivate static func registerFont(bundle: Bundle, fontName: String, fontExtension: String) { + guard let fontURL = bundle.url(forResource: fontName, withExtension: fontExtension), + let fontDataProvider = CGDataProvider(url: fontURL as CFURL), + let font = CGFont(fontDataProvider) else { + print("Couldn't find font \(fontName)") + return + } + + var error: Unmanaged? + CTFontManagerRegisterGraphicsFont(font, &error) + } + + public static func registerFonts() { + [ + "Pretendard-Regular", + "Pretendard-SemiBold", + "Pretendard-Bold" + ].forEach { + registerFont(bundle: .module, fontName: $0, fontExtension: "otf") + } + } + +} + +public extension UIFont { + + static func msFont(_ font: MSFont) -> UIFont? { + if let font = font.font() { + return font + } else { + print("can't find msFont. use default font") + return nil + } + } + +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/MSIcon.swift b/iOS/MSUIKit/Sources/MSDesignSystem/MSIcon.swift new file mode 100644 index 0000000..2fc0a16 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/MSIcon.swift @@ -0,0 +1,42 @@ +// +// MSIcon.swift +// MSUIKit +// +// Created by 이창준 on 11/19/23. +// + +import UIKit + +public enum MSIcon: String { + case check = "Check" + case close = "Close" + + case arrowUp = "Up" + case arrowLeft = "Left" + case arrowDown = "Down" + case arrowRight = "Right" + + case calendar = "Calendar" + case image = "Image" + case location = "Location" + case addLocation = "Location Add" + case lock = "Lock" + case map = "Map" + case message = "Message" + case setting = "Setting" + case userTag = "User Tag" + + case pause = "Pause" + case play = "Play" + case voice = "Voice" + case volumeHigh = "Volume High" + case volumeOff = "Volume Off" +} + +extension UIImage { + + public static func msIcon(_ icon: MSIcon) -> UIImage? { + return UIImage(named: icon.rawValue, in: .module, compatibleWith: .current)?.withRenderingMode(.alwaysTemplate) + } + +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/Fonts/Pretendard-Bold.otf b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/Fonts/Pretendard-Bold.otf new file mode 100644 index 0000000..e6d6ce8 Binary files /dev/null and b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/Fonts/Pretendard-Bold.otf differ diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/Fonts/Pretendard-Regular.otf b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/Fonts/Pretendard-Regular.otf new file mode 100644 index 0000000..858cdd3 Binary files /dev/null and b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/Fonts/Pretendard-Regular.otf differ diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/Fonts/Pretendard-SemiBold.otf b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/Fonts/Pretendard-SemiBold.otf new file mode 100644 index 0000000..fe81db7 Binary files /dev/null and b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/Fonts/Pretendard-SemiBold.otf differ diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Background Primary.colorset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Background Primary.colorset/Contents.json new file mode 100644 index 0000000..37005c7 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Background Primary.colorset/Contents.json @@ -0,0 +1,56 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xF6", + "green" : "0xF6", + "red" : "0xF6" + } + }, + "idiom" : "iphone" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "light" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xF6", + "green" : "0xF6", + "red" : "0xF6" + } + }, + "idiom" : "iphone" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x15", + "green" : "0x15", + "red" : "0x15" + } + }, + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Background Secondary.colorset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Background Secondary.colorset/Contents.json new file mode 100644 index 0000000..ca86825 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Background Secondary.colorset/Contents.json @@ -0,0 +1,56 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xF6", + "green" : "0xF6", + "red" : "0xF6" + } + }, + "idiom" : "iphone" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "light" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "0.980", + "blue" : "0xFA", + "green" : "0xFA", + "red" : "0xFA" + } + }, + "idiom" : "iphone" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "0.980", + "blue" : "0x23", + "green" : "0x23", + "red" : "0x23" + } + }, + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Button Background Primary.colorset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Button Background Primary.colorset/Contents.json new file mode 100644 index 0000000..6b4fcde --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Button Background Primary.colorset/Contents.json @@ -0,0 +1,56 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xF6", + "green" : "0xF6", + "red" : "0xF6" + } + }, + "idiom" : "iphone" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "light" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x23", + "green" : "0x23", + "red" : "0x23" + } + }, + "idiom" : "iphone" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xF6", + "green" : "0xF6", + "red" : "0xF6" + } + }, + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Button Background Secondary.colorset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Button Background Secondary.colorset/Contents.json new file mode 100644 index 0000000..9da726d --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Button Background Secondary.colorset/Contents.json @@ -0,0 +1,56 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xF6", + "green" : "0xF6", + "red" : "0xF6" + } + }, + "idiom" : "iphone" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "light" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xEC", + "green" : "0xEC", + "red" : "0xEC" + } + }, + "idiom" : "iphone" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x35", + "green" : "0x35", + "red" : "0x35" + } + }, + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Button Typo Primary.colorset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Button Typo Primary.colorset/Contents.json new file mode 100644 index 0000000..37005c7 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Button Typo Primary.colorset/Contents.json @@ -0,0 +1,56 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xF6", + "green" : "0xF6", + "red" : "0xF6" + } + }, + "idiom" : "iphone" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "light" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xF6", + "green" : "0xF6", + "red" : "0xF6" + } + }, + "idiom" : "iphone" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x15", + "green" : "0x15", + "red" : "0x15" + } + }, + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Button Typo Secondary.colorset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Button Typo Secondary.colorset/Contents.json new file mode 100644 index 0000000..048e7a5 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Button Typo Secondary.colorset/Contents.json @@ -0,0 +1,56 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xF6", + "green" : "0xF6", + "red" : "0xF6" + } + }, + "idiom" : "iphone" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "light" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x15", + "green" : "0x15", + "red" : "0x15" + } + }, + "idiom" : "iphone" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xF7", + "green" : "0xF7", + "red" : "0xF7" + } + }, + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/MusicSpot.colorset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/MusicSpot.colorset/Contents.json new file mode 100644 index 0000000..a2baa68 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/MusicSpot.colorset/Contents.json @@ -0,0 +1,56 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xF6", + "green" : "0xF6", + "red" : "0xF6" + } + }, + "idiom" : "iphone" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "light" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xAC", + "green" : "0xD2", + "red" : "0x1C" + } + }, + "idiom" : "iphone" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x9B", + "green" : "0xBE", + "red" : "0x19" + } + }, + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Typo Primary.colorset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Typo Primary.colorset/Contents.json new file mode 100644 index 0000000..aac7649 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Typo Primary.colorset/Contents.json @@ -0,0 +1,56 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xF6", + "green" : "0xF6", + "red" : "0xF6" + } + }, + "idiom" : "iphone" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "light" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x15", + "green" : "0x15", + "red" : "0x15" + } + }, + "idiom" : "iphone" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xFB", + "green" : "0xF8", + "red" : "0xFA" + } + }, + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Typo Secondary.colorset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Typo Secondary.colorset/Contents.json new file mode 100644 index 0000000..58656a2 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSColor.xcassets/Typo Secondary.colorset/Contents.json @@ -0,0 +1,56 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xF6", + "green" : "0xF6", + "red" : "0xF6" + } + }, + "idiom" : "iphone" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "light" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x9E", + "green" : "0x9E", + "red" : "0x9E" + } + }, + "idiom" : "iphone" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x9E", + "green" : "0x9E", + "red" : "0x9E" + } + }, + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Calender.imageset/Calender 1.pdf b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Calender.imageset/Calender 1.pdf new file mode 100644 index 0000000..8830486 Binary files /dev/null and b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Calender.imageset/Calender 1.pdf differ diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Calender.imageset/Calender.pdf b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Calender.imageset/Calender.pdf new file mode 100644 index 0000000..8830486 Binary files /dev/null and b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Calender.imageset/Calender.pdf differ diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Calender.imageset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Calender.imageset/Contents.json new file mode 100644 index 0000000..5413f5e --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Calender.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Calender.pdf", + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Check.imageset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Check.imageset/Contents.json new file mode 100644 index 0000000..8e467fb --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Check.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Tick.pdf", + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Check.imageset/Tick.pdf b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Check.imageset/Tick.pdf new file mode 100644 index 0000000..737c935 Binary files /dev/null and b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Check.imageset/Tick.pdf differ diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Close.imageset/Close.pdf b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Close.imageset/Close.pdf new file mode 100644 index 0000000..9a272fd Binary files /dev/null and b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Close.imageset/Close.pdf differ diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Close.imageset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Close.imageset/Contents.json new file mode 100644 index 0000000..f37efb1 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Close.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Close.pdf", + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Down.imageset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Down.imageset/Contents.json new file mode 100644 index 0000000..af5a0b0 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Down.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Down 2.pdf", + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Down.imageset/Down 2.pdf b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Down.imageset/Down 2.pdf new file mode 100644 index 0000000..49cd5c9 Binary files /dev/null and b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Down.imageset/Down 2.pdf differ diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Image.imageset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Image.imageset/Contents.json new file mode 100644 index 0000000..49f937a --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Image.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Image 2.pdf", + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Image.imageset/Image 2.pdf b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Image.imageset/Image 2.pdf new file mode 100644 index 0000000..1849543 Binary files /dev/null and b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Image.imageset/Image 2.pdf differ diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Left.imageset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Left.imageset/Contents.json new file mode 100644 index 0000000..27a55a1 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Left.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Left 2.pdf", + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Left.imageset/Left 2.pdf b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Left.imageset/Left 2.pdf new file mode 100644 index 0000000..76f3470 Binary files /dev/null and b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Left.imageset/Left 2.pdf differ diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Location Add.imageset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Location Add.imageset/Contents.json new file mode 100644 index 0000000..63ce9c3 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Location Add.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Location Add.pdf", + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Location Add.imageset/Location Add.pdf b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Location Add.imageset/Location Add.pdf new file mode 100644 index 0000000..379d9d9 Binary files /dev/null and b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Location Add.imageset/Location Add.pdf differ diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Location.imageset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Location.imageset/Contents.json new file mode 100644 index 0000000..f66a3bf --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Location.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Location.pdf", + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Location.imageset/Location.pdf b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Location.imageset/Location.pdf new file mode 100644 index 0000000..40621ce Binary files /dev/null and b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Location.imageset/Location.pdf differ diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Lock.imageset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Lock.imageset/Contents.json new file mode 100644 index 0000000..b6835c4 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Lock.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Lock 2.pdf", + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Lock.imageset/Lock 2.pdf b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Lock.imageset/Lock 2.pdf new file mode 100644 index 0000000..33b860a Binary files /dev/null and b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Lock.imageset/Lock 2.pdf differ diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Map.imageset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Map.imageset/Contents.json new file mode 100644 index 0000000..eeb84de --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Map.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Map.pdf", + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Map.imageset/Map.pdf b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Map.imageset/Map.pdf new file mode 100644 index 0000000..2456c29 Binary files /dev/null and b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Map.imageset/Map.pdf differ diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Message.imageset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Message.imageset/Contents.json new file mode 100644 index 0000000..d72df9e --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Message.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Message 15.pdf", + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Message.imageset/Message 15.pdf b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Message.imageset/Message 15.pdf new file mode 100644 index 0000000..e42fd45 Binary files /dev/null and b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Message.imageset/Message 15.pdf differ diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Pause.imageset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Pause.imageset/Contents.json new file mode 100644 index 0000000..bc8c287 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Pause.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Pause.pdf", + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Pause.imageset/Pause.pdf b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Pause.imageset/Pause.pdf new file mode 100644 index 0000000..0fc0dd0 Binary files /dev/null and b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Pause.imageset/Pause.pdf differ diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Play.imageset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Play.imageset/Contents.json new file mode 100644 index 0000000..994eac5 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Play.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Play.pdf", + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Play.imageset/Play.pdf b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Play.imageset/Play.pdf new file mode 100644 index 0000000..0a2c8a2 Binary files /dev/null and b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Play.imageset/Play.pdf differ diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Right.imageset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Right.imageset/Contents.json new file mode 100644 index 0000000..a96cd3c --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Right.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Right 2.pdf", + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Right.imageset/Right 2.pdf b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Right.imageset/Right 2.pdf new file mode 100644 index 0000000..9eaf133 Binary files /dev/null and b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Right.imageset/Right 2.pdf differ diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Setting.imageset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Setting.imageset/Contents.json new file mode 100644 index 0000000..855d6fb --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Setting.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Setting.pdf", + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Setting.imageset/Setting.pdf b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Setting.imageset/Setting.pdf new file mode 100644 index 0000000..122a73a Binary files /dev/null and b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Setting.imageset/Setting.pdf differ diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Up.imageset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Up.imageset/Contents.json new file mode 100644 index 0000000..45d843a --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Up.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Up 3.pdf", + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Up.imageset/Up 3.pdf b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Up.imageset/Up 3.pdf new file mode 100644 index 0000000..65d89dc Binary files /dev/null and b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Up.imageset/Up 3.pdf differ diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/User Tag.imageset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/User Tag.imageset/Contents.json new file mode 100644 index 0000000..edf9901 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/User Tag.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "User Tag 2.pdf", + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/User Tag.imageset/User Tag 2.pdf b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/User Tag.imageset/User Tag 2.pdf new file mode 100644 index 0000000..b5c3491 Binary files /dev/null and b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/User Tag.imageset/User Tag 2.pdf differ diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Voice.imageset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Voice.imageset/Contents.json new file mode 100644 index 0000000..95f462f --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Voice.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Voice.pdf", + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Voice.imageset/Voice.pdf b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Voice.imageset/Voice.pdf new file mode 100644 index 0000000..b7f434f Binary files /dev/null and b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Voice.imageset/Voice.pdf differ diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Volume High.imageset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Volume High.imageset/Contents.json new file mode 100644 index 0000000..8eb05ae --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Volume High.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Volume High.pdf", + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Volume High.imageset/Volume High.pdf b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Volume High.imageset/Volume High.pdf new file mode 100644 index 0000000..696c6fa Binary files /dev/null and b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Volume High.imageset/Volume High.pdf differ diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Volume Off.imageset/Contents.json b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Volume Off.imageset/Contents.json new file mode 100644 index 0000000..1ed65fa --- /dev/null +++ b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Volume Off.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "Volume Off.pdf", + "idiom" : "iphone" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Volume Off.imageset/Volume Off.pdf b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Volume Off.imageset/Volume Off.pdf new file mode 100644 index 0000000..b3aee0b Binary files /dev/null and b/iOS/MSUIKit/Sources/MSDesignSystem/Resources/MSIcon.xcassets/Volume Off.imageset/Volume Off.pdf differ diff --git a/iOS/MSUIKit/Sources/MSUIComponents/MSUIComponents.swift b/iOS/MSUIKit/Sources/MSUIComponents/MSUIComponents.swift deleted file mode 100644 index dc701bb..0000000 --- a/iOS/MSUIKit/Sources/MSUIComponents/MSUIComponents.swift +++ /dev/null @@ -1,8 +0,0 @@ -// -// MSUIComponents.swift -// MSUIKit -// -// Created by 이창준 on 11/14/23. -// - -import UIKit diff --git a/iOS/MSUIKit/Sources/MSUIKit/BaseViewController.swift b/iOS/MSUIKit/Sources/MSUIKit/BaseViewController.swift new file mode 100644 index 0000000..aabfba3 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSUIKit/BaseViewController.swift @@ -0,0 +1,37 @@ +// +// BaseViewController.swift +// MSUIKit +// +// Created by 이창준 on 11/23/23. +// + +import UIKit + +import MSDesignSystem + +open class BaseViewController: UIViewController { + + open override func viewDidLoad() { + super.viewDidLoad() + self.configureSafeArea() + self.configureStyle() + self.configureLayout() + } + + /// CornerRadius, 색상 등의 변경을 포함합니다. + open func configureStyle() { + self.view.backgroundColor = .msColor(.primaryBackground) + } + + /// addSubView, Auto Layout 등의 레이아웃 설정을 포함합니다. + open func configureLayout() { } + + private func configureSafeArea() { + let safeAreaInsets = UIEdgeInsets(top: 24.0, + left: 16.0, + bottom: 24.0, + right: 16.0) + self.additionalSafeAreaInsets = safeAreaInsets + } + +} diff --git a/iOS/MSUIKit/Sources/MSUIKit/MSBottomSheetViewController.swift b/iOS/MSUIKit/Sources/MSUIKit/MSBottomSheetViewController.swift new file mode 100644 index 0000000..5662940 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSUIKit/MSBottomSheetViewController.swift @@ -0,0 +1,277 @@ +// +// MSUIComponents.swift +// MSUIKit +// +// Created by 이창준 on 11/14/23. +// + +import UIKit + +import MSDesignSystem + +open class MSBottomSheetViewController +: UIViewController, UIGestureRecognizerDelegate { + + // MARK: - Configuration + + public struct BottomSheetConfiguration { + let fullHeight: CGFloat + let detentHeight: CGFloat + let minimizedHeight: CGFloat + + var fullDetentDiff: CGFloat { + return self.fullHeight - self.detentHeight + } + + var detentMinimizedDiff: CGFloat { + return self.detentHeight - self.minimizedHeight + } + + public init(fullHeight: CGFloat, + detentHeight: CGFloat, + minimizedHeight: CGFloat) { + self.fullHeight = fullHeight + self.detentHeight = detentHeight + self.minimizedHeight = minimizedHeight + } + } + + // MARK: - State + + public enum State { + case full + case detented + case minimized + } + + // MARK: - UI Components + + let contentViewController: Content + let bottomSheetViewController: BottomSheet + + private var topConstraints: NSLayoutConstraint? + + private lazy var panGesture: UIPanGestureRecognizer = { + let panGesture = UIPanGestureRecognizer() + panGesture.delegate = self + panGesture.addTarget(self, action: #selector(self.handlePanGesture(_:))) + return panGesture + }() + + // MARK: - Properties + + private let configuration: BottomSheetConfiguration + var state: State = .minimized + private let gestureVelocity: CGFloat = 750.0 + + // MARK: - Initializer + + public init(contentViewController: Content, + bottomSheetViewController: BottomSheet, + configuration: BottomSheetConfiguration) { + self.contentViewController = contentViewController + self.bottomSheetViewController = bottomSheetViewController + self.configuration = configuration + super.init(nibName: nil, bundle: nil) + self.configureLayout() + self.configureStyle() + self.configureGesture() + } + + public required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + // MARK: - Functions + + public func presentFullBottomSheet(animated: Bool = true) { + self.topConstraints?.constant = -self.configuration.fullHeight + + if animated { + UIView.animate(withDuration: 0.3) { + self.view.layoutIfNeeded() + } completion: { _ in + self.state = .full + } + } else { + self.view.layoutIfNeeded() + self.state = .full + } + } + + public func presentDetentedBottomSheet(animated: Bool = true) { + self.topConstraints?.constant = -self.configuration.detentHeight + + if animated { + UIView.animate(withDuration: 0.5, + delay: .zero, + usingSpringWithDamping: 0.8, + initialSpringVelocity: 0.5, + options: [.curveEaseInOut]) { + self.view.layoutIfNeeded() + } completion: { _ in + self.state = .detented + } + } else { + self.view.layoutIfNeeded() + self.state = .detented + } + } + + public func dismissBottomSheet(animated: Bool = true) { + self.topConstraints?.constant = -self.configuration.minimizedHeight + + if animated { + UIView.animate(withDuration: 0.5, + delay: .zero, + usingSpringWithDamping: 0.8, + initialSpringVelocity: 0.5, + options: [.curveEaseInOut]) { + self.view.layoutIfNeeded() + } completion: { _ in + self.state = .minimized + } + } else { + self.view.layoutIfNeeded() + self.state = .minimized + } + } + + // MARK: - Pan Gesture + + @objc + private func handlePanGesture(_ sender: UIPanGestureRecognizer) { + let translation = sender.translation(in: self.bottomSheetViewController.view) + let velocity = sender.velocity(in: self.bottomSheetViewController.view) + + switch sender.state { + case .began, .changed: + self.handlePanChanged(translation: translation) + case .ended: + self.handlePanEnded(translation: translation, velocity: velocity) + case .failed: + self.handlePanFailed() + default: break + } + } + + private func handlePanChanged(translation: CGPoint) { + switch self.state { + case .full: + guard translation.y > 0 else { return } + + self.topConstraints?.constant = -(self.configuration.fullHeight - translation.y.magnitude) + self.view.layoutIfNeeded() + case .detented: + if translation.y >= 0 { // 아래로 Pan + self.topConstraints?.constant = -(self.configuration.detentHeight - translation.y.magnitude) + } else if translation.y < 0 { // 위로 Pan + self.topConstraints?.constant = -(self.configuration.detentHeight + translation.y.magnitude) + } + self.view.layoutIfNeeded() + case .minimized: + guard translation.y < 0 else { return } + + let newConstant = -(self.configuration.minimizedHeight + translation.y.magnitude) + self.topConstraints?.constant = newConstant + self.view.layoutIfNeeded() + } + } + + private func handlePanEnded(translation: CGPoint, velocity: CGPoint) { + let yTransMagnitude = translation.y.magnitude + switch self.state { + case .full: + if velocity.y < 0 { + self.presentFullBottomSheet() + } else if yTransMagnitude >= self.configuration.fullDetentDiff / 2 || velocity.y > self.gestureVelocity { + self.presentDetentedBottomSheet() + } else { + self.presentFullBottomSheet() + } + case .detented: + if yTransMagnitude >= self.configuration.fullDetentDiff / 2 || velocity.y < -self.gestureVelocity { + self.presentFullBottomSheet() + } else if translation.y >= self.configuration.detentMinimizedDiff / 2 || velocity.y > self.gestureVelocity { + self.dismissBottomSheet() + } else { + self.presentDetentedBottomSheet() + } + case .minimized: + if yTransMagnitude >= self.configuration.detentHeight / 2 || velocity.y < -self.gestureVelocity { + self.presentDetentedBottomSheet() + } else { + self.dismissBottomSheet() + } + } + } + + private func handlePanFailed() { + switch self.state { + case .full: + self.presentFullBottomSheet() + case .detented: + self.presentDetentedBottomSheet() + case .minimized: + self.dismissBottomSheet() + } + } + + public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, + shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer + ) -> Bool { + return true + } + +} + +// MARK: - UI Configuration + +private extension MSBottomSheetViewController { + + func configureStyle() { + self.bottomSheetViewController.view.layer.cornerRadius = 12.0 + self.bottomSheetViewController.view.clipsToBounds = true + } + + func configureLayout() { + self.addChild(self.contentViewController) + self.addChild(self.bottomSheetViewController) + + self.view.addSubview(self.contentViewController.view) + self.view.addSubview(self.bottomSheetViewController.view) + + self.contentViewController.view.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + self.contentViewController.view.leftAnchor + .constraint(equalTo: self.view.leftAnchor), + self.contentViewController.view.rightAnchor + .constraint(equalTo: self.view.rightAnchor), + self.contentViewController.view.topAnchor + .constraint(equalTo: self.view.topAnchor), + self.contentViewController.view.bottomAnchor + .constraint(equalTo: self.view.bottomAnchor) + ]) + self.contentViewController.didMove(toParent: self) + + self.bottomSheetViewController.view.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + self.bottomSheetViewController.view.heightAnchor + .constraint(equalToConstant: self.configuration.fullHeight), + self.bottomSheetViewController.view.leftAnchor + .constraint(equalTo: self.view.leftAnchor), + self.bottomSheetViewController.view.rightAnchor + .constraint(equalTo: self.view.rightAnchor) + ]) + self.topConstraints = self.bottomSheetViewController.view.topAnchor + .constraint(equalTo: self.view.bottomAnchor, + constant: -self.configuration.minimizedHeight) + self.topConstraints?.isActive = true + self.bottomSheetViewController.didMove(toParent: self) + } + + func configureGesture() { + self.bottomSheetViewController.view.addGestureRecognizer(self.panGesture) + } + +} diff --git a/iOS/MSUIKit/Sources/MSUIKit/MSButton/MSButton+Primary.swift b/iOS/MSUIKit/Sources/MSUIKit/MSButton/MSButton+Primary.swift new file mode 100644 index 0000000..cd57907 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSUIKit/MSButton/MSButton+Primary.swift @@ -0,0 +1,23 @@ +// +// MSButton+Primary.swift +// MSUIKit +// +// Created by 이창준 on 11/19/23. +// + +import UIKit + +import MSDesignSystem + +extension MSButton { + + public static func primary(isBrandColored: Bool = true) -> MSButton { + let button = MSButton() + button.configuration?.baseForegroundColor = .msColor(.primaryButtonTypo) + button.configuration?.baseBackgroundColor = isBrandColored + ? .msColor(.musicSpot) + : .msColor(.primaryButtonBackground) + return button + } + +} diff --git a/iOS/MSUIKit/Sources/MSUIKit/MSButton/MSButton+Secondary.swift b/iOS/MSUIKit/Sources/MSUIKit/MSButton/MSButton+Secondary.swift new file mode 100644 index 0000000..3ed6eb0 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSUIKit/MSButton/MSButton+Secondary.swift @@ -0,0 +1,21 @@ +// +// MSButton+Secondary.swift +// MSUIKit +// +// Created by 이창준 on 11/19/23. +// + +import UIKit + +import MSDesignSystem + +extension MSButton { + + public static func secondary() -> MSButton { + let button = MSButton() + button.configuration?.baseForegroundColor = .msColor(.secondaryButtonTypo) + button.configuration?.baseBackgroundColor = .msColor(.secondaryButtonBackground) + return button + } + +} diff --git a/iOS/MSUIKit/Sources/MSUIKit/MSButton/MSButton.swift b/iOS/MSUIKit/Sources/MSUIKit/MSButton/MSButton.swift new file mode 100644 index 0000000..26ddb72 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSUIKit/MSButton/MSButton.swift @@ -0,0 +1,106 @@ +// +// MSButton.swift +// MSUIKit +// +// Created by 이창준 on 11/19/23. +// + +import UIKit + +import MSDesignSystem + +public class MSButton: UIButton { + + public enum CornerStyle { + case squared + case rounded + case custom(CGFloat) + + var cornerRadius: CGFloat { + switch self { + case .squared: return 8.0 + case .rounded: return 25.0 + case .custom(let cornerRadius): return cornerRadius + } + } + + } + + // MARK: - Constants + + private enum Metric { + static let height: CGFloat = 60.0 + static let horizontalEdgeInsets: CGFloat = 58.0 + static let verticalEdgeInsets: CGFloat = 10.0 + static let imagePadding: CGFloat = 8.0 + } + + // MARK: - Properties + + public var title: String? { + didSet { self.configureTitle(self.title) } + } + + public var image: UIImage? { + didSet { self.configureIcon(self.image) } + } + + public var cornerStyle: CornerStyle = .squared { + didSet { self.configureCornerStyle(self.cornerStyle) } + } + + // MARK: - Initializer + + private override init(frame: CGRect) { + super.init(frame: frame) + self.configureStyles() + self.configureLayout() + } + + required init?(coder: NSCoder) { + fatalError("MusicSpot은 code-based로만 작업 중입니다.") + } + + // MARK: - UI Configuration + + private func configureStyles() { + var configuration = UIButton.Configuration.filled() + configuration.contentInsets = NSDirectionalEdgeInsets(top: Metric.verticalEdgeInsets, + leading: Metric.horizontalEdgeInsets, + bottom: Metric.verticalEdgeInsets, + trailing: Metric.horizontalEdgeInsets) + configuration.imagePlacement = .leading + configuration.imagePadding = Metric.imagePadding + configuration.titleAlignment = .center + self.configuration = configuration + } + + private func configureLayout() { + self.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + self.heightAnchor.constraint(equalToConstant: Metric.height) + ]) + } + +} + +// MARK: - Private Configuration Functions + +private extension MSButton { + + private func configureTitle(_ title: String?) { + var container = AttributeContainer() + container.font = .msFont(.buttonTitle) + self.configuration?.attributedTitle = AttributedString(title ?? "", attributes: container) + } + + private func configureIcon(_ icon: UIImage?) { + self.configuration?.image = icon + } + + private func configureCornerStyle(_ cornerStyle: CornerStyle) { + self.layer.cornerRadius = cornerStyle.cornerRadius + self.clipsToBounds = true + } + +} diff --git a/iOS/MSUIKit/Sources/MSUIKit/MSButton/MSRectButton+Large.swift b/iOS/MSUIKit/Sources/MSUIKit/MSButton/MSRectButton+Large.swift new file mode 100644 index 0000000..29ff40b --- /dev/null +++ b/iOS/MSUIKit/Sources/MSUIKit/MSButton/MSRectButton+Large.swift @@ -0,0 +1,21 @@ +// +// MSRectButton+Large.swift +// MSUIKit +// +// Created by 이창준 on 11/20/23. +// + +import MSDesignSystem + +extension MSRectButton { + + public static func large(isBrandColored: Bool = true) -> MSRectButton { + let button = MSRectButton() + button.style = .large + button.configuration?.baseBackgroundColor = isBrandColored + ? .msColor(.musicSpot) + : .msColor(.secondaryButtonBackground).withAlphaComponent(0.8) + return button + } + +} diff --git a/iOS/MSUIKit/Sources/MSUIKit/MSButton/MSRectButton+Small.swift b/iOS/MSUIKit/Sources/MSUIKit/MSButton/MSRectButton+Small.swift new file mode 100644 index 0000000..9147a38 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSUIKit/MSButton/MSRectButton+Small.swift @@ -0,0 +1,21 @@ +// +// MSRectButton+Small.swift +// MSUIKit +// +// Created by 이창준 on 11/20/23. +// + +import MSDesignSystem + +extension MSRectButton { + + public static func small(isBrandColored: Bool = false) -> MSRectButton { + let button = MSRectButton() + button.style = .small + button.configuration?.baseBackgroundColor = isBrandColored + ? .msColor(.musicSpot) + : .msColor(.secondaryButtonBackground).withAlphaComponent(0.8) + return button + } + +} diff --git a/iOS/MSUIKit/Sources/MSUIKit/MSButton/MSRectButton.swift b/iOS/MSUIKit/Sources/MSUIKit/MSButton/MSRectButton.swift new file mode 100644 index 0000000..15121fa --- /dev/null +++ b/iOS/MSUIKit/Sources/MSUIKit/MSButton/MSRectButton.swift @@ -0,0 +1,117 @@ +// +// MSRectButton.swift +// MSUIKit +// +// Created by 이창준 on 11/19/23. +// + +import UIKit + +import MSDesignSystem + +public final class MSRectButton: UIButton { + + internal enum Style { + case small + case large + + var size: CGSize { + switch self { + case .small: return CGSize(width: 52.0, height: 56.0) + case .large: return CGSize(width: 120.0, height: 120.0) + } + } + + var cornerRadius: CGFloat { + switch self { + case .small: return 8.0 + case .large: return 30.0 + } + } + + } + + // MARK: - Constants + + private enum Metric { + static let edgeInsets: CGFloat = 10.0 + } + + // MARK: - Properties + + public var title: String? { + didSet { self.configureTitle(self.title) } + } + + public var image: UIImage? { + didSet { self.configureIcon(self.image) } + } + + internal var style: Style = .small { + didSet { + self.configureSize(by: self.style) + self.configureCornerStyle(by: self.style) + } + } + + // MARK: - Initializer + + private override init(frame: CGRect) { + super.init(frame: frame) + self.configureStyles() + self.configureLayout() + } + + required init?(coder: NSCoder) { + fatalError("MusicSpot은 code-based로만 작업 중입니다.") + } + + // MARK: - UI Configuration + + private func configureStyles() { + var configuration = UIButton.Configuration.filled() + configuration.baseForegroundColor = .msColor(.primaryTypo) + configuration.contentInsets = NSDirectionalEdgeInsets(top: Metric.edgeInsets, + leading: Metric.edgeInsets, + bottom: Metric.edgeInsets, + trailing: Metric.edgeInsets) + configuration.imagePlacement = .leading + configuration.titleAlignment = .center + self.configuration = configuration + } + + private func configureLayout() { + self.translatesAutoresizingMaskIntoConstraints = false + } + +} + +// MARK: - Private Configuration Functions + +private extension MSRectButton { + + private func configureTitle(_ title: String?) { + self.configuration?.image = nil + var container = AttributeContainer() + container.font = self.style == .large ? .msFont(.duperTitle) : .msFont(.buttonTitle) + self.configuration?.attributedTitle = AttributedString(title ?? "", attributes: container) + } + + private func configureIcon(_ icon: UIImage?) { + self.configuration?.attributedTitle = nil + self.configuration?.image = icon + } + + private func configureSize(by style: Style) { + NSLayoutConstraint.activate([ + self.widthAnchor.constraint(equalToConstant: style.size.width), + self.heightAnchor.constraint(equalToConstant: style.size.height) + ]) + } + + private func configureCornerStyle(by style: Style) { + self.layer.cornerRadius = style.cornerRadius + self.clipsToBounds = true + } + +} diff --git a/iOS/MSUIKit/Sources/MSUIKit/MSTextField/MSTextField.swift b/iOS/MSUIKit/Sources/MSUIKit/MSTextField/MSTextField.swift new file mode 100644 index 0000000..aa9d5b2 --- /dev/null +++ b/iOS/MSUIKit/Sources/MSUIKit/MSTextField/MSTextField.swift @@ -0,0 +1,205 @@ +// +// MSTextField.swift +// MSUIKit +// +// Created by 전민건 on 11/14/23. +// + +import UIKit + +import MSDesignSystem + +public class MSTextField: UITextField { + + // MARK: - Constants + + private enum Metric { + + static let height: CGFloat = 50.0 + static let leftInset: CGFloat = 22.0 + static let rightInset: CGFloat = 12.0 + static let verticalEdgeInsets: CGFloat = 10.0 + static let imageWidth: CGFloat = 20.0 + static let imageHeight: CGFloat = 20.0 + static let imageInset: CGFloat = 12.0 + static let cornerRadius: CGFloat = 8.0 + + } + + private enum ImageBox { + + static let magnifyingglass = UIImage(systemName: "magnifyingglass") + static let close = UIImage(systemName: "multiply.circle.fill") + + } + + public enum ImageStyle { + + case none + case search + case pin + case calender + case lock + + var leftImage: UIImage? { + switch self { + case .none: + return nil + case .search: + return ImageBox.magnifyingglass + case .pin: + return .msIcon(.location) + case .calender: + return .msIcon(.calendar) + case .lock: + return .msIcon(.lock) + } + } + var rightImage: UIImage? { + switch self { + case .none: + return nil + default: + return .msIcon(.arrowRight) + } + } + + } + + // MARK: - Properties + + private var leftImage = UIImageView() + private var rightImage = UIImageView() + public var imageStyle: ImageStyle = .none { + didSet { + self.configureImageStyle() + self.configureLayout() + } + } + public override var text: String? { + didSet { + self.convertMode() + } + } + + // MARK: - Initializer + + private override init(frame: CGRect) { + super.init(frame: frame) + self.configureStyles() + self.configureLayout() + } + + required init?(coder: NSCoder) { + fatalError("MusicSpot은 code-based로만 작업 중입니다.") + } + + // MARK: - UI Configuration + + private func configureStyles() { + MSFont.registerFonts() + self.font = .msFont(.caption) + + self.layer.cornerRadius = Metric.cornerRadius + self.backgroundColor = .msColor(.primaryBackground) + + self.configureImageStyle() + } + + private func configureLayout() { + self.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + self.heightAnchor.constraint(equalToConstant: Metric.height) + ]) + self.configurePlaceholderLayout() + + self.addSubview(self.leftImage) + self.addSubview(self.rightImage) + + self.configureLeftImageLayout() + self.configureRightImageLayout() + } + + private func configurePlaceholderLayout() { + self.configureLeftPlaceholderLayout() + self.configureRightPlaceholderLayout() + } + + private func configureLeftPlaceholderLayout() { + let extraInset: CGFloat = self.imageStyle == .none ? 0.0 : Metric.imageWidth + Metric.imageInset + self.leftView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: Metric.leftInset + extraInset, height: 0.0)) + self.leftViewMode = .always + } + + private func configureRightPlaceholderLayout() { + let extraInset: CGFloat = self.hasText ? Metric.imageWidth + Metric.imageInset : 0.0 + self.rightView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: Metric.rightInset + extraInset, height: 0.0)) + self.rightViewMode = .always + } + + private func configureLeftImageLayout() { + self.leftImage.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + self.leftImage.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: Metric.leftInset), + self.leftImage.heightAnchor.constraint(equalToConstant: Metric.imageHeight), + self.leftImage.widthAnchor.constraint(equalToConstant: Metric.imageWidth), + self.leftImage.centerYAnchor.constraint(equalTo: self.centerYAnchor) + ]) + } + + private func configureRightImageLayout() { + self.rightImage.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + self.rightImage.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -Metric.imageInset), + self.rightImage.heightAnchor.constraint(equalToConstant: Metric.imageHeight), + self.rightImage.widthAnchor.constraint(equalToConstant: Metric.imageWidth), + self.rightImage.centerYAnchor.constraint(equalTo: self.centerYAnchor) + ]) + } + +} + +// MARK: - Edit/Non-Edit Mode Functions + +public extension MSTextField { + + func convertMode() { + self.configureRightImageStyle() + self.configureRightImageLayout() + } + +} + +// MARK: - Private Configuration Functions + +private extension MSTextField { + + private func configureImageStyle() { + self.configureLeftImageStyle() + self.configureRightImageStyle() + } + + private func configureLeftImageStyle() { + if let leftImage = self.imageStyle.leftImage { + self.leftImage.image = leftImage + } + self.leftImage.tintColor = .msColor(.secondaryTypo) + } + + private func configureRightImageStyle() { + if let rightImage = self.imageStyle.rightImage { + self.rightImage.image = rightImage + } + + if self.hasText { + self.rightImage.image = ImageBox.close + } + self.rightImage.tintColor = .msColor(.secondaryTypo) + } + + private func configureImages(color: UIColor) { + self.leftImage.tintColor = color + self.rightImage.tintColor = color + } + +} diff --git a/iOS/MSUIKit/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/iOS/MusicSpot.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist~HEAD similarity index 100% rename from iOS/MSUIKit/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to iOS/MusicSpot.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist~HEAD diff --git a/iOS/MusicSpot.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist~release b/iOS/MusicSpot.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist~release new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/iOS/MusicSpot.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist~release @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/iOS/MusicSpot/MusicSpot/SceneDelegate.swift b/iOS/MusicSpot/MusicSpot/SceneDelegate.swift index 61bf718..b01638c 100644 --- a/iOS/MusicSpot/MusicSpot/SceneDelegate.swift +++ b/iOS/MusicSpot/MusicSpot/SceneDelegate.swift @@ -8,11 +8,18 @@ import UIKit class SceneDelegate: UIResponder, UIWindowSceneDelegate { + var window: UIWindow? func scene(_ scene: UIScene, willConnectTo _: UISceneSession, options _: UIScene.ConnectionOptions) { - guard (scene as? UIWindowScene) != nil else { return } + guard let windowScene = (scene as? UIWindowScene) else { return } + let window = UIWindow(windowScene: windowScene) + defer { self.window = window } + + let testViewController = UIViewController() + window.rootViewController = testViewController + window.makeKeyAndVisible() } }