feat: add welcome view;

feat: modify window.rootViewController logic when app launches;
feat: enable ViewController-based status bar
This commit is contained in:
jk234ert 2021-02-20 20:23:29 +08:00
parent 8970231381
commit 9fefdccef2
10 changed files with 152 additions and 62 deletions

View File

@ -8,7 +8,9 @@
/* Begin PBXBuildFile section */
0FAA0FDF25E0B57E0017CCDE /* WelcomeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FAA0FDE25E0B57E0017CCDE /* WelcomeViewController.swift */; };
0FAA0FE625E0C7700017CCDE /* FontStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FAA0FE525E0C7700017CCDE /* FontStyle.swift */; };
0FAA101225E105390017CCDE /* MasActionButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FAA101125E105390017CCDE /* MasActionButton.swift */; };
0FAA101C25E10E760017CCDE /* UIFont.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FAA101B25E10E760017CCDE /* UIFont.swift */; };
0FAA102725E1126A0017CCDE /* PickServerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FAA102625E1126A0017CCDE /* PickServerViewController.swift */; };
18BC7629F65E6DB12CB8416D /* Pods_Mastodon_MastodonUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C030226D3C73DCC23D67452 /* Pods_Mastodon_MastodonUITests.framework */; };
2D04F42525C255B9003F936F /* APIService+PublicTimeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D04F42425C255B9003F936F /* APIService+PublicTimeline.swift */; };
2D152A8C25C295CC009AA50C /* TimelinePostView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D152A8B25C295CC009AA50C /* TimelinePostView.swift */; };
@ -184,7 +186,9 @@
/* Begin PBXFileReference section */
0FAA0FDE25E0B57E0017CCDE /* WelcomeViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeViewController.swift; sourceTree = "<group>"; };
0FAA0FE525E0C7700017CCDE /* FontStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FontStyle.swift; sourceTree = "<group>"; };
0FAA101125E105390017CCDE /* MasActionButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MasActionButton.swift; sourceTree = "<group>"; };
0FAA101B25E10E760017CCDE /* UIFont.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIFont.swift; sourceTree = "<group>"; };
0FAA102625E1126A0017CCDE /* PickServerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PickServerViewController.swift; sourceTree = "<group>"; };
2D04F42425C255B9003F936F /* APIService+PublicTimeline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+PublicTimeline.swift"; sourceTree = "<group>"; };
2D152A8B25C295CC009AA50C /* TimelinePostView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelinePostView.swift; sourceTree = "<group>"; };
2D152A9125C2980C009AA50C /* UIFont.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIFont.swift; sourceTree = "<group>"; };
@ -377,12 +381,12 @@
path = Welcome;
sourceTree = "<group>";
};
0FAA0FE425E0C7610017CCDE /* stylesheet */ = {
0FAA102525E1125D0017CCDE /* PickServer */ = {
isa = PBXGroup;
children = (
0FAA0FE525E0C7700017CCDE /* FontStyle.swift */,
0FAA102625E1126A0017CCDE /* PickServerViewController.swift */,
);
path = stylesheet;
path = PickServer;
sourceTree = "<group>";
};
1EBA4F56E920856A3FC84ACB /* Pods */ = {
@ -445,6 +449,7 @@
DB5086A425CC0B7000C2C187 /* AvatarBarButtonItem.swift */,
2D42FF8425C8224F004A627A /* HitTestExpandedButton.swift */,
2D5A3D1025CF87AA002347D6 /* AvatarBarButtonItem.swift */,
0FAA101125E105390017CCDE /* MasActionButton.swift */,
);
path = Button;
sourceTree = "<group>";
@ -657,7 +662,6 @@
DB427DD425BAA00100D1B89D /* Mastodon */ = {
isa = PBXGroup;
children = (
0FAA0FE425E0C7610017CCDE /* stylesheet */,
DB427DE325BAA00100D1B89D /* Info.plist */,
DB89BA1025C10FF5008580ED /* Mastodon.entitlements */,
2D5A3D0125CF8640002347D6 /* Vender */,
@ -821,6 +825,7 @@
DB8AF55525C1379F002E6C99 /* Scene */ = {
isa = PBXGroup;
children = (
0FAA102525E1125D0017CCDE /* PickServer */,
0FAA0FDD25E0B5700017CCDE /* Welcome */,
2D38F1D325CD463600561493 /* HomeTimeline */,
2D7631A425C1532200929FB9 /* Share */,
@ -846,6 +851,7 @@
2D42FF8E25C8228A004A627A /* UIButton.swift */,
DB45FAD625CA6C76005A8AC7 /* UIBarButtonItem.swift */,
2D32EAB925CB9B0500C9ED86 /* UIView.swift */,
0FAA101B25E10E760017CCDE /* UIFont.swift */,
);
path = Extension;
sourceTree = "<group>";
@ -1238,16 +1244,19 @@
2D61335E25C1894B00CAE157 /* APIService.swift in Sources */,
2D38F1F725CD47AC00561493 /* HomeTimelineViewModel+LoadOldestState.swift in Sources */,
2D5A3D3825CF8D9F002347D6 /* ScrollViewContainer.swift in Sources */,
0FAA101225E105390017CCDE /* MasActionButton.swift in Sources */,
DB8AF53025C13561002E6C99 /* AppContext.swift in Sources */,
2D38F1F125CD477D00561493 /* HomeTimelineViewModel+LoadMiddleState.swift in Sources */,
DB45FAD725CA6C76005A8AC7 /* UIBarButtonItem.swift in Sources */,
2D152A8C25C295CC009AA50C /* TimelinePostView.swift in Sources */,
2D42FF8525C8224F004A627A /* HitTestExpandedButton.swift in Sources */,
2D42FF8F25C8228A004A627A /* UIButton.swift in Sources */,
0FAA102725E1126A0017CCDE /* PickServerViewController.swift in Sources */,
2D61335825C188A000CAE157 /* APIService+Persist+Timeline.swift in Sources */,
DB45FAE325CA7181005A8AC7 /* MastodonUser.swift in Sources */,
DB0AC6FC25CD02E600D75117 /* APIService+Instance.swift in Sources */,
2D69D00A25CAA00300C3A1B2 /* APIService+CoreData+Toot.swift in Sources */,
0FAA101C25E10E760017CCDE /* UIFont.swift in Sources */,
2D38F1D525CD465300561493 /* HomeTimelineViewController.swift in Sources */,
DB98338825C945ED00AD9700 /* Assets.swift in Sources */,
2DA7D04425CA52B200804E11 /* TimelineLoaderTableViewCell.swift in Sources */,
@ -1305,7 +1314,6 @@
DB01409625C40B6700F9F3CF /* AuthenticationViewController.swift in Sources */,
DB427DD825BAA00100D1B89D /* SceneDelegate.swift in Sources */,
DB5086AB25CC0BBB00C2C187 /* AvatarConfigurableView.swift in Sources */,
0FAA0FE625E0C7700017CCDE /* FontStyle.swift in Sources */,
DB0140AE25C40C7300F9F3CF /* MastodonPinBasedAuthenticationViewModel.swift in Sources */,
2D32EAAC25CB96DC00C9ED86 /* TimelineMiddleLoaderTableViewCell.swift in Sources */,
2D5A3D6225CFD9CB002347D6 /* HomeTimelineViewController+DebugAction.swift in Sources */,

View File

@ -0,0 +1,23 @@
//
// UIFont.swift
// Mastodon
//
// Created by on 2021/2/20.
//
import UIKit
extension UIFont {
private func withTraits(traits: UIFontDescriptor.SymbolicTraits) -> UIFont {
let descriptor = fontDescriptor.withSymbolicTraits(traits)
return UIFont(descriptor: descriptor!, size: 0) //size 0 means keep the size as it is
}
func bold() -> UIFont {
return withTraits(traits: .traitBold)
}
func italic() -> UIFont {
return withTraits(traits: .traitItalic)
}
}

View File

@ -7,6 +7,7 @@
import UIKit
// MARK: -Convinience view creation method
extension UIView {
static var separatorLine: UIView {
@ -24,3 +25,14 @@ extension UIView {
}
}
// MARK: -Convinience view appearance modification method
extension UIView {
@discardableResult
func applyCornerRadius(radius: CGFloat) -> Self {
layer.masksToBounds = true
layer.cornerRadius = radius
layer.cornerCurve = .continuous
return self
}
}

View File

@ -11,6 +11,13 @@ import Foundation
// swiftlint:disable nesting type_body_length type_name vertical_whitespace_opening_braces
internal enum L10n {
internal enum Button {
/// Sign In
internal static let signIn = L10n.tr("Localizable", "Button.SignIn")
/// Sign Up
internal static let signUp = L10n.tr("Localizable", "Button.SignUp")
}
internal enum Common {
internal enum Controls {
internal enum Timeline {

View File

@ -2,8 +2,6 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>UIUserInterfaceStyle</key>
<string>Dark</string>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
@ -64,5 +62,9 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIUserInterfaceStyle</key>
<string>Dark</string>
<key>UIViewControllerBasedStatusBarAppearance</key>
<true/>
</dict>
</plist>

View File

@ -7,3 +7,7 @@
*/
"Common.Controls.Timeline.LoadMore" = "Load More";
"Common.Label.Slogon" = "Social networking\nback in your hands.";
"Common.Label.PickAServer" = "Pick a server,\nany server.";
"Button.SignUp" = "Sign Up";
"Button.SignIn" = "Sign In";

View File

@ -0,0 +1,21 @@
//
// PickServerViewController.swift
// Mastodon
//
// Created by on 2021/2/20.
//
import UIKit
class PickServerViewController: UIViewController {
let titleLabel: UILabel = {
let label = UILabel()
label.font = .boldSystemFont(ofSize: 34)
label.textColor = Asset.Colors.Label.black.color
label.text = L10n.Common.Label.slogon
label.adjustsFontForContentSizeCategory = true
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 0
return label
}()
}

View File

@ -0,0 +1,30 @@
//
// MasActionButton.swift
// Mastodon
//
// Created by on 2021/2/20.
//
import UIKit
class MasActionButton: UIButton {
override init(frame: CGRect) {
super.init(frame: frame)
_init()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
_init()
}
}
extension MasActionButton {
private func _init() {
titleLabel?.font = .preferredFont(forTextStyle: .headline)
setTitleColor(Asset.Colors.lightWhite.color, for: .normal)
backgroundColor = Asset.Colors.lightBrandBlue.color
applyCornerRadius(radius: 10)
setInsets(forContentPadding: UIEdgeInsets(top: 12, left: 0, bottom: 12, right: 0), imageTitlePadding: 0)
}
}

View File

@ -16,22 +16,43 @@ final class WelcomeViewController: UIViewController {
let sloganLabel: UILabel = {
let label = UILabel()
label.font = .preferredFont(forTextStyle: .largeTitle)
label.textColor = .black
label.font = .boldSystemFont(ofSize: 34)
label.textColor = Asset.Colors.Label.black.color
label.text = L10n.Common.Label.slogon
label.adjustsFontForContentSizeCategory = true
label.translatesAutoresizingMaskIntoConstraints = false
label.numberOfLines = 0
return label
}()
let signUpButton: MasActionButton = {
let button = MasActionButton(type: .system)
button.setTitle(L10n.Button.signUp, for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
let signInButton: UIButton = {
let button = UIButton(type: .system)
button.setTitle(L10n.Button.signIn, for: .normal)
button.setTitleColor(Asset.Colors.lightBrandBlue.color, for: .normal)
button.titleLabel?.font = .preferredFont(forTextStyle: .subheadline)
button.setInsets(forContentPadding: UIEdgeInsets(top: 12, left: 0, bottom: 12, right: 0), imageTitlePadding: 0)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
}
extension WelcomeViewController {
override var preferredStatusBarStyle: UIStatusBarStyle {
return .darkContent
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
view.backgroundColor = Asset.Colors.Background.signUpSystemBackground.color
view.addSubview(logoImageView)
NSLayoutConstraint.activate([
@ -47,6 +68,18 @@ extension WelcomeViewController {
sloganLabel.trailingAnchor.constraint(equalTo: view.readableContentGuide.trailingAnchor, constant: -16),
sloganLabel.topAnchor.constraint(equalTo: logoImageView.bottomAnchor, constant: 168),
])
view.addSubview(signInButton)
view.addSubview(signUpButton)
NSLayoutConstraint.activate([
signInButton.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor, constant: 12),
signInButton.trailingAnchor.constraint(equalTo: view.readableContentGuide.trailingAnchor, constant: -12),
signInButton.bottomAnchor.constraint(equalTo: view.readableContentGuide.bottomAnchor, constant: -11),
signUpButton.leadingAnchor.constraint(equalTo: view.readableContentGuide.leadingAnchor, constant: 12),
signUpButton.trailingAnchor.constraint(equalTo: view.readableContentGuide.trailingAnchor, constant: -12),
signUpButton.bottomAnchor.constraint(equalTo: signInButton.topAnchor, constant: -5)
])
}
override func viewWillAppear(_ animated: Bool) {

View File

@ -1,50 +0,0 @@
//
// FontStyle.swift
// Mastodon
//
// Created by on 2021/2/20.
//
import UIKit
fileprivate extension UIFont.TextStyle {
var masFont: UIFont {
switch self {
case .headline:
return UIFont(descriptor: UIFont.CustomFontDescriptor.SFProText, size: 34).bolded
default:
return UIFont(descriptor: UIFont.CustomFontDescriptor.SFProText, size: 16)
}
}
}
extension UIFont {
fileprivate struct CustomFontDescriptor {
static var fontFamily = "Avenir"
static var SFProText = UIFontDescriptor(name: "SFProText", size: 0)
}
/// Returns a bold version of `self`
public var bolded: UIFont {
return fontDescriptor.withSymbolicTraits(.traitBold)
.map { UIFont(descriptor: $0, size: 0) } ?? self
}
/// Returns an italic version of `self`
public var italicized: UIFont {
return fontDescriptor.withSymbolicTraits(.traitItalic)
.map { UIFont(descriptor: $0, size: 0) } ?? self
}
/// Returns a scaled version of `self`
func scaled(scaleFactor: CGFloat) -> UIFont {
let newDescriptor = fontDescriptor.withSize(fontDescriptor.pointSize * scaleFactor)
return UIFont(descriptor: newDescriptor, size: 0)
}
class func preferredFont(forTextStyle textStyle: UIFont.TextStyle) -> UIFont {
let masFontMetrics = UIFontMetrics(forTextStyle: textStyle)
return masFontMetrics.scaledFont(for: textStyle.masFont)
}
}