Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions Wable-iOS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@
DD29687E2D6DC70700143851 /* OAuthCredential.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD29687D2D6DC70100143851 /* OAuthCredential.swift */; };
DD547AB92D7E43A600B8BA5A /* GhostButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD547AB82D7E439E00B8BA5A /* GhostButton.swift */; };
DD69C5902D71A3BE000A3349 /* OAuthTokenProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD69C58F2D71A3B6000A3349 /* OAuthTokenProvider.swift */; };
DD765D9A2D8746E30029A317 /* LoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD765D992D8746DD0029A317 /* LoginViewController.swift */; };
DD765D9D2D8747950029A317 /* SplashViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD765D9C2D8747900029A317 /* SplashViewController.swift */; };
DD87931C2D7044E7001212AE /* OAuthErrorMonitor.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD87931B2D7044E0001212AE /* OAuthErrorMonitor.swift */; };
DD9980DB2D834CA900EBBFBC /* CommentInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9980DA2D834CA900EBBFBC /* CommentInfo.swift */; };
DD9980DF2D834F4E00EBBFBC /* CommentCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DD9980DC2D834F4E00EBBFBC /* CommentCollectionViewCell.swift */; };
Expand Down Expand Up @@ -338,6 +340,8 @@
DD29687D2D6DC70100143851 /* OAuthCredential.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuthCredential.swift; sourceTree = "<group>"; };
DD547AB82D7E439E00B8BA5A /* GhostButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GhostButton.swift; sourceTree = "<group>"; };
DD69C58F2D71A3B6000A3349 /* OAuthTokenProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuthTokenProvider.swift; sourceTree = "<group>"; };
DD765D992D8746DD0029A317 /* LoginViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewController.swift; sourceTree = "<group>"; };
DD765D9C2D8747900029A317 /* SplashViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashViewController.swift; sourceTree = "<group>"; };
DD87931B2D7044E0001212AE /* OAuthErrorMonitor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OAuthErrorMonitor.swift; sourceTree = "<group>"; };
DD8CEF3D2D6A007900DBE580 /* Share.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Share.xcconfig; sourceTree = "<group>"; };
DD8CEF3E2D6A007900DBE580 /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = "<group>"; };
Expand Down Expand Up @@ -916,6 +920,22 @@
path = Domain;
sourceTree = "<group>";
};
DD765D982D8746D30029A317 /* Login */ = {
isa = PBXGroup;
children = (
DD765D992D8746DD0029A317 /* LoginViewController.swift */,
);
path = Login;
sourceTree = "<group>";
};
DD765D9B2D8747890029A317 /* Splash */ = {
isa = PBXGroup;
children = (
DD765D9C2D8747900029A317 /* SplashViewController.swift */,
);
path = Splash;
sourceTree = "<group>";
};
DD87931D2D70452B001212AE /* OAuth */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -1139,6 +1159,8 @@
isa = PBXGroup;
children = (
DDCA70982D8879C600A988B8 /* Enum */,
DD765D9B2D8747890029A317 /* Splash */,
DD765D982D8746D30029A317 /* Login */,
DDCD66DB2D7C8A1600EF4C28 /* WableComponent */,
DE7C530A2D761DBF00076E5D /* Interface */,
DE7C53092D761DB900076E5D /* UIHelper */,
Expand Down Expand Up @@ -1378,6 +1400,7 @@
DD2968342D6DAD1700143851 /* InformationRepositoryImpl.swift in Sources */,
DD2968352D6DAD1700143851 /* GhostRepositoryImpl.swift in Sources */,
DD2968362D6DAD1700143851 /* ContentLikedRepositoryImpl.swift in Sources */,
DD765D9A2D8746E30029A317 /* LoginViewController.swift in Sources */,
DEDC29142D7208A00073D512 /* GameStatus.swift in Sources */,
DD2968372D6DAD1700143851 /* ProfileRepositoryImpl.swift in Sources */,
DD2968382D6DAD1700143851 /* ReportRepositoryImpl.swift in Sources */,
Expand Down Expand Up @@ -1431,6 +1454,7 @@
DD2968192D6DAD0200143851 /* ReportRepository.swift in Sources */,
DD29681A2D6DAD0200143851 /* ViewitRepository.swift in Sources */,
DE67A9EB2D7211070021BDE1 /* Like.swift in Sources */,
DD765D9D2D8747950029A317 /* SplashViewController.swift in Sources */,
DD29681B2D6DAD0200143851 /* ProfileRepository.swift in Sources */,
DD29681C2D6DAD0200143851 /* InformationRepository.swift in Sources */,
DD69C5902D71A3BE000A3349 /* OAuthTokenProvider.swift in Sources */,
Expand Down
53 changes: 36 additions & 17 deletions Wable-iOS/App/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ import Combine
import UIKit

class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?

// MARK: - Property

private let cancelBag = CancelBag()
private let userSessionRepository: UserSessionRepository = UserSessionRepositoryImpl(
userDefaults: UserDefaultsStorage(
Expand All @@ -18,37 +20,47 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
jsonDecoder: JSONDecoder()
)
)

// MARK: - UIComponent

var window: UIWindow?

// MARK: - WillConnentTo

func scene(
_ scene: UIScene,
willConnectTo session: UISceneSession,
options connectionOptions: UIScene.ConnectionOptions
) {
guard let windowScene = (scene as? UIWindowScene) else { return }
self.window = UIWindow(windowScene: windowScene)
self.window?.rootViewController = SplashViewController()
self.window?.makeKeyAndVisible()

userSessionRepository.checkAutoLogin()
.sink { completion in
switch completion {
case .finished:
break
case .failure(_):
self.configureLoginScreen()
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2.0) {
self.userSessionRepository.checkAutoLogin()
.sink { completion in
switch completion {
case .finished:
break
case .failure(_):
self.configureLoginScreen()
}
} receiveValue: { isAutoLoginEnabled in
isAutoLoginEnabled ? self.configureMainScreen() : self.configureLoginScreen()
self.window?.makeKeyAndVisible()
self.updateVersionIfNeeded()
}
} receiveValue: { isAutoLoginEnabled in
isAutoLoginEnabled ? self.configureMainScreen() : self.configureLoginScreen()
}
.store(in: cancelBag)
.store(in: self.cancelBag)
}
}
}

// MARK: - Extension
// MARK: - Configure Extension

private extension SceneDelegate {
// TODO: 로그인 화면으로 이동하는 로직 구현 필요
func configureLoginScreen() {
self.window?.rootViewController = ViewController()
self.window?.makeKeyAndVisible()
self.window?.rootViewController = LoginViewController()
}

func configureMainScreen() {
Expand All @@ -59,6 +71,13 @@ private extension SceneDelegate {
type: .home(hasNewNotification: condition)
)
)
self.window?.makeKeyAndVisible()
}
}

// MARK: - Private Extension

private extension SceneDelegate {
func updateVersionIfNeeded() {
// TODO: 강제 업데이트 로직 구현 필요
}
}
120 changes: 120 additions & 0 deletions Wable-iOS/Presentation/Login/LoginViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
//
// LoginViewController.swift
// Wable-iOS
//
// Created by YOUJIM on 3/17/25.
//


import AuthenticationServices
import UIKit

final class LoginViewController: UIViewController {

// MARK: UIComponent

private let backgroundImageView: UIImageView = UIImageView(image: .imgLoginBackground)

private let logoImageView: UIImageView = UIImageView(image: .logoType)

private let loginImageView: UIImageView = UIImageView(image: .imgLogin)

private let titleLabel: UILabel = UILabel().then {
$0.attributedText = "클린 LCK 팬 커뮤니티\n와블에서 함께 해요".pretendardString(with: .head0)
$0.textAlignment = .center
$0.numberOfLines = 0
$0.textColor = .black
}

private lazy var kakaoButton: UIButton = UIButton(configuration: UIButton.Configuration.plain()).then {
$0.configuration?.image = .btnKakao
$0.configuration?.contentInsets = .init(top: 0, leading: 0, bottom: 0, trailing: 0)
}

private lazy var appleButton: ASAuthorizationAppleIDButton = ASAuthorizationAppleIDButton(
type: .continue,
style: .black
)

// MARK: - LifeCycle

override func viewDidLoad() {
super.viewDidLoad()

setupView()
setupConstraint()
setupAction()
}
}

// MARK: - Private Extension

private extension LoginViewController {

// MARK: - Setup

func setupView() {
view.backgroundColor = UIColor(patternImage: .imgLoginBackground)

view.addSubviews(logoImageView, loginImageView, titleLabel, kakaoButton, appleButton)
}

func setupConstraint() {
logoImageView.snp.makeConstraints {
$0.top.equalTo(view.safeAreaLayoutGuide).offset(44)
$0.centerX.equalToSuperview()
$0.width.equalTo(104)
$0.height.equalTo(34)
}

titleLabel.snp.makeConstraints {
$0.top.equalTo(logoImageView.snp.bottom).offset(26)
$0.centerX.equalToSuperview()
}

loginImageView.snp.makeConstraints {
$0.top.equalTo(titleLabel.snp.bottom).offset(42)
$0.leading.trailing.equalToSuperview()
}

kakaoButton.snp.makeConstraints {
$0.bottom.equalTo(appleButton.snp.top).offset(-18)
$0.leading.trailing.equalToSuperview().inset(16)
$0.height.equalTo(50)
}

appleButton.snp.makeConstraints {
$0.bottom.equalTo(view.safeAreaLayoutGuide).inset(56)
$0.leading.trailing.equalToSuperview().inset(16)
$0.height.equalTo(50)
}
}

func setupAction() {
kakaoButton.addTarget(self, action: #selector(kakaoButtonDidTap), for: .touchUpInside)
appleButton.addTarget(self, action: #selector(appleButtonDidTap), for: .touchUpInside)
}

// MARK: - @objc Method

@objc func kakaoButtonDidTap() {
// TODO: 카카오 로그인 기능 구현 필요
}

@objc func appleButtonDidTap() {
// TODO: 애플 로그인 기능 구현 필요

let noticeViewController = WableActionSheetViewController(
configuraton: .init(
title: "앗 잠깐!",
message: "와블은 온화하면서도 유쾌한 LCK 팬들이 모여 함께 즐기는 공간이에요.\n더 건강하고 즐거운 커뮤니티를 만들어 나가는데 함께 노력해주실거죠?",
confirmButtonTitle: "확인",
confirmAction: { completion in
// TODO: 온보딩 화면으로 전환 필요
}
)
)

self.present(noticeViewController, animated: true)
}
}
54 changes: 54 additions & 0 deletions Wable-iOS/Presentation/Splash/SplashViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
//
// SplashViewController.swift
// Wable-iOS
//
// Created by YOUJIM on 3/17/25.
//


import UIKit

import Lottie

final class SplashViewController: UIViewController {

// MARK: - UIComponent

private lazy var animationView: LottieAnimationView = LottieAnimationView(name: "wable_splash").then { view in
view.contentMode = .scaleAspectFill
view.loopMode = .playOnce
view.play(fromProgress: 0, toProgress: 1, loopMode: .playOnce, completion: {
$0 ? DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
view.stop()
} : nil
})
}

// MARK: - LifeCycle

override func viewDidLoad() {
super.viewDidLoad()

setupView()
setupConstraint()
}
}

// MARK: - Private Extension

private extension SplashViewController {

// MARK: - Setup

func setupView() {
view.backgroundColor = .white

view.addSubview(animationView)
}

func setupConstraint() {
animationView.snp.makeConstraints {
$0.center.equalToSuperview()
}
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
{
"images" : [
{
"filename" : "img_login_background.png",
"filename" : "iPhone 13 mini - 347.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "img_login_background@2x.png",
"filename" : "iPhone 13 mini - 347@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "img_login_background@3x.png",
"filename" : "iPhone 13 mini - 347@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file not shown.
Binary file not shown.