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
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
{
"images" : [
{
"filename" : "Frame 1321318482.png",
"filename" : "imgLoginBanner4.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Frame 1321318482@2x.png",
"filename" : "imgLoginBanner4@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Frame 1321318482@3x.png",
"filename" : "imgLoginBanner4@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
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.
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "icAttractiveWritingSkill.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 0 additions & 21 deletions WSSiOS/Resource/Assets.xcassets/testImage.imageset/Contents.json

This file was deleted.

Binary file not shown.
24 changes: 24 additions & 0 deletions WSSiOS/Resource/Extensions/UILabel+.swift
Original file line number Diff line number Diff line change
Expand Up @@ -181,3 +181,27 @@ extension TextAttributeSet {
self.label.attributedText = self.attributedString
}
}

// NSAttributedString에 적용하는 확장 함수
extension TextAttributeSet {
func build() -> NSAttributedString {
return attributedString
}
}

extension UILabel {
func makeWSSAttributed(_ font: WSSFont, text: String, underline: Bool) -> NSAttributedString {
self.font = font.font

let attr = NSMutableAttributedString(string: text)
var set = TextAttributeSet(label: self, attributeString: attr)
.lineHeight(font.lineHeightMultiple)
.kerning(kerningPixel: font.kerningPixel)

if underline {
set = set.underlineStyle(.single)
}

return set.build()
}
}
9 changes: 7 additions & 2 deletions WSSiOS/Resource/Extensions/UIViewController+.swift
Original file line number Diff line number Diff line change
Expand Up @@ -332,8 +332,13 @@ extension UIViewController {
self.dismiss(animated: false)
}

func pushToNormalSearchViewController() {
let normalSearchViewController = NormalSearchViewController(viewModel: NormalSearchViewModel(searchRepository: DefaultSearchRepository(searchService: DefaultSearchService())))
func pushToNormalSearchViewController(searchText: String? = nil) {
let normalSearchViewController = NormalSearchViewController(
viewModel: NormalSearchViewModel(
searchRepository: DefaultSearchRepository(searchService: DefaultSearchService()),
initialSearchText: searchText
)
)
normalSearchViewController.navigationController?.isNavigationBarHidden = false
normalSearchViewController.hidesBottomBarWhenPushed = true
self.navigationController?.pushViewController(normalSearchViewController, animated: true)
Expand Down
3 changes: 3 additions & 0 deletions WSSiOS/Source/Data/Base/AttractivePoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import UIKit
enum AttractivePoint: String, CaseIterable, Codable {
case worldview = "worldview"
case material = "material"
case writingSkill = "writingskill"
case character = "character"
case relationship = "relationship"
case vibe = "vibe"
Expand All @@ -18,6 +19,7 @@ enum AttractivePoint: String, CaseIterable, Codable {
switch self {
case .worldview: "세계관"
case .material: "소재"
case .writingSkill: "필력"
case .character: "캐릭터"
case .relationship: "관계"
case .vibe: "분위기"
Expand All @@ -28,6 +30,7 @@ enum AttractivePoint: String, CaseIterable, Codable {
switch self {
case .worldview: .icAttractiveWorldview
case .material: .icAttractiveMaterial
case .writingSkill: .icAttractiveWritingSkill
case .character: .icAttractiveCharacter
case .relationship: .icAttractiveRelationship
case .vibe: .icAttractiveVibe
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ struct NovelDetailHeaderEntity {
let novelGenre: String
let novelGenreImage: String
let isNovelCompleted: Bool
let novelAuthor: String
let novelAuthor: [String]
let interestCount: Int
let novelRating: Float
let novelRatingCount: Int
Expand All @@ -30,14 +30,18 @@ struct NovelDetailHeaderEntity {

extension NovelDetailHeaderResponse {
func toEntity() -> NovelDetailHeaderEntity {
let authors = self.author
.components(separatedBy: ",")
.map { $0.trimmingCharacters(in: .whitespaces) }

return NovelDetailHeaderEntity(
userNovelID: self.userNovelID,
novelTitle: self.novelTitle,
novelImage: self.novelImage,
novelGenre: self.novelGenres,
novelGenreImage: self.novelGenreImage,
isNovelCompleted: self.isNovelCompleted,
novelAuthor: self.author,
novelAuthor: authors,
interestCount: self.interestCount,
novelRating: round(self.novelRating * 10) / 10,
novelRatingCount: self.novelRatingCount,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,24 @@ import Then
final class NovelDetailHeaderNovelInfoView: UIView {

//MARK: - Properties

private let titleLineLimit = 3

private var currentAuthors: [String] = []

//MARK: - Callbacks

var onAuthorTapped: ((String) -> Void)?

//MARK: - Components

private let stackView = UIStackView()

private let titleLabel = UILabel()

private let infoStack = UIStackView()
private let infoLabel = UILabel()
private let authorStackView = UIStackView()

private let reviewStack = UIStackView()

private let interestCount = NovelDetailHeaderReviewSummaryElementView()
Expand All @@ -45,6 +54,18 @@ final class NovelDetailHeaderNovelInfoView: UIView {
//MARK: - UI

private func setUI() {
authorStackView.do {
$0.axis = .horizontal
$0.spacing = 0
$0.alignment = .center
}

infoStack.do {
$0.axis = .horizontal
$0.spacing = 0
$0.alignment = .center
}

stackView.do {
$0.axis = .vertical
$0.spacing = 6
Expand Down Expand Up @@ -79,8 +100,10 @@ final class NovelDetailHeaderNovelInfoView: UIView {

private func setHierarchy() {
self.addSubview(stackView)
infoStack.addArrangedSubviews(infoLabel,
authorStackView)
stackView.addArrangedSubviews(titleLabel,
infoLabel,
infoStack,
reviewStack)
reviewStack.addArrangedSubviews(interestCount,
rating,
Expand All @@ -91,6 +114,10 @@ final class NovelDetailHeaderNovelInfoView: UIView {
stackView.snp.makeConstraints {
$0.edges.equalToSuperview()
}

infoStack.snp.makeConstraints {
$0.center.equalToSuperview()
}
}

//MARK: - Data
Expand All @@ -100,7 +127,8 @@ final class NovelDetailHeaderNovelInfoView: UIView {
let novelRatingText = "\(data.novelRating) (\(data.novelRatingCount))"

setTitleLabelText(with: data.novelTitle)
setInfoLabelText(with: "\(data.novelGenre) · \(novelCompletionText) · \(data.novelAuthor)")
setInfoLabelText(with: "\(data.novelGenre) · \(novelCompletionText) · ")
setNovelAuthorText(with: data.novelAuthor)
interestCount.setText(with: "\(data.interestCount)")
rating.setText(with: novelRatingText)
feedCount.setText(with: "\(data.feedCount)")
Expand Down Expand Up @@ -128,4 +156,32 @@ final class NovelDetailHeaderNovelInfoView: UIView {
$0.numberOfLines = 1
}
}

private func setNovelAuthorText(with authors: [String]) {
currentAuthors = authors
authorStackView.arrangedSubviews.forEach { $0.removeFromSuperview() }

for (index, author) in authors.enumerated() {
let label = UILabel()
label.attributedText = label.makeWSSAttributed(.body3, text: author, underline: true)
label.textColor = .wssGray200
label.isUserInteractionEnabled = true
label.tag = index
label.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(authorLabelTapped(_:))))
authorStackView.addArrangedSubview(label)

if index < authors.count - 1 {
let separator = UILabel()
separator.attributedText = separator.makeWSSAttributed(.body3, text: ", ", underline: false)
separator.textColor = .wssGray200
authorStackView.addArrangedSubview(separator)
}
}
}

@objc private func authorLabelTapped(_ sender: UITapGestureRecognizer) {
guard let label = sender.view as? UILabel,
label.tag < currentAuthors.count else { return }
onAuthorTapped?(currentAuthors[label.tag])
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ final class NovelDetailHeaderView: UIView {

//MARK: - Data

func setAuthorTapHandler(_ handler: @escaping (String) -> Void) {
novelInfoView.onAuthorTapped = handler
}

func bindData(_ data: NovelDetailHeaderEntity) {
novelInfoView.bindData(data)
interestReviewButton.updateInterestButtonState(data.isUserNovelInterest)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ final class NovelDetailViewController: UIViewController {
$0.timeZone = TimeZone(identifier: StringLiterals.Register.Normal.DatePicker.KoreaTimeZone)
}

// NovelDetailHeader
private let authorLabelDidTap = PublishRelay<String>()

// NovelDetailFeed
private let novelDetailFeedProfileViewDidTap = PublishRelay<Int>()
private let novelDetailFeedDropdownButtonDidTap = PublishRelay<(Int, Bool)>()
Expand Down Expand Up @@ -223,6 +226,13 @@ final class NovelDetailViewController: UIViewController {
})
.disposed(by: disposeBag)

output.pushToAuthorSearchResultViewController
.observe(on: MainScheduler.instance)
.subscribe(with: self, onNext: { owner, authorName in
owner.pushToNormalSearchViewController(searchText: authorName)
})
.disposed(by: disposeBag)

//MARK: - Bind/Tab

output.selectedTab
Expand Down Expand Up @@ -467,6 +477,10 @@ final class NovelDetailViewController: UIViewController {
//MARK: - Actions

private func bindAction() {
rootView.headerView.setAuthorTapHandler { [weak self] author in
self?.authorLabelDidTap.accept(author)
}

rootView.scrollView.rx.contentOffset
.observe(on: MainScheduler.asyncInstance)
.subscribe(with: self, onNext: { owner, offset in
Expand Down Expand Up @@ -528,6 +542,7 @@ final class NovelDetailViewController: UIViewController {
novelCoverImageButtonDidTap: rootView.headerView.coverImageButton.rx.tap,
largeNovelCoverImageDismissButtonDidTap: rootView.largeNovelCoverImageButton.dismissButton.rx.tap,
largeNovelCoverImageBackgroundDidTap: rootView.largeNovelCoverImageButton.rx.tap,
authorLabelDidTap: authorLabelDidTap.asObservable(),
reviewResultButtonDidTap: reviewResultButtonDidTap,
interestButtonDidTap: rootView.headerView.interestReviewButton.interestButton.rx.tap,
feedWriteButtonDidTap: rootView.headerView.interestReviewButton.feedWriteButton.rx.tap,
Expand All @@ -549,7 +564,7 @@ final class NovelDetailViewController: UIViewController {
}

//MARK: - Custom Method

private func showLargeNovelCoverImageView(_ isShow: Bool) {
rootView.largeNovelCoverImageButton.isHidden = !isShow
self.navigationController?.setNavigationBarHidden(isShow, animated: false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ final class NovelDetailViewModel: ViewModelType {
private let isUserNovelInterested = BehaviorRelay<Bool>(value: false)
private let readStatus = BehaviorRelay<ReadStatus?>(value: nil)
private let novelGenre = BehaviorRelay<[NewNovelGenre]>(value: [])

private let pushToAuthorSearchResultViewController = PublishRelay<String>()

// Tab
private let selectedTab = BehaviorRelay<Tab>(value: Tab.info)

Expand Down Expand Up @@ -92,6 +93,7 @@ final class NovelDetailViewModel: ViewModelType {
let novelCoverImageButtonDidTap: ControlEvent<Void>
let largeNovelCoverImageDismissButtonDidTap: ControlEvent<Void>
let largeNovelCoverImageBackgroundDidTap: ControlEvent<Void>
let authorLabelDidTap: Observable<String>
let reviewResultButtonDidTap: Observable<ReadStatus?>
let interestButtonDidTap: ControlEvent<Void>
let feedWriteButtonDidTap: ControlEvent<Void>
Expand Down Expand Up @@ -135,6 +137,7 @@ final class NovelDetailViewModel: ViewModelType {
let isUserNovelInterested: Driver<Bool>
let pushTofeedWriteViewController: Observable<(genre: [NewNovelGenre], novelId: Int, novelTitle: String)>
let pushToReviewViewController: Observable<(isInterest: Bool, readStatus: ReadStatus, novelId: Int, novelTitle: String)>
let pushToAuthorSearchResultViewController: Observable<String>

// Tab
let selectedTab: Driver<Tab>
Expand Down Expand Up @@ -272,7 +275,13 @@ final class NovelDetailViewModel: ViewModelType {
}
.throttle(.seconds(1), latest: false, scheduler: MainScheduler.instance)
.asObservable()


input.authorLabelDidTap
.subscribe(with: self, onNext: { owner, authorName in
owner.pushToAuthorSearchResultViewController.accept(authorName)
})
.disposed(by: disposeBag)

input.interestButtonDidTap
.throttle(.seconds(1), latest: false, scheduler: MainScheduler.instance)
.do(onNext: { _ in
Expand Down Expand Up @@ -523,6 +532,7 @@ final class NovelDetailViewModel: ViewModelType {
isUserNovelInterested: isUserNovelInterested.asDriver(),
pushTofeedWriteViewController: pushToFeedWriteViewController,
pushToReviewViewController: pushToReviewViewController,
pushToAuthorSearchResultViewController: pushToAuthorSearchResultViewController.asObservable(),
selectedTab: selectedTab.asDriver(),
isInfoDescriptionExpended: isInfoDescriptionExpended.asDriver(),
platformList: platformList.asDriver(),
Expand Down
Loading