diff --git a/MemorialHouse/MHPresentation/MHPresentation/Source/Book/BookViewController.swift b/MemorialHouse/MHPresentation/MHPresentation/Source/Book/BookViewController.swift new file mode 100644 index 00000000..5126b324 --- /dev/null +++ b/MemorialHouse/MHPresentation/MHPresentation/Source/Book/BookViewController.swift @@ -0,0 +1,130 @@ +import UIKit + +final class BookViewController: UIViewController { + // MARK: - UI Components + private let pageViewController = UIPageViewController( + transitionStyle: .pageCurl, + navigationOrientation: .horizontal + ) + + // MARK: - Property + private let viewModel: BookViewModel + + // MARK: - Initialize + init(bookTitle: String, viewModel: BookViewModel) { + self.viewModel = viewModel + super.init(nibName: nil, bundle: nil) + + title = bookTitle + } + + required init?(coder: NSCoder) { + self.viewModel = BookViewModel() + super.init(nibName: nil, bundle: nil) + + title = "책 이름" + } + + // MARK: - View Life Cycle + override func viewDidLoad() { + super.viewDidLoad() + + setup() + configureNavigationBar() + configureConstraints() + configurePageViewController() + } + + // MARK: - Setup & Configure + private func setup() { + view.backgroundColor = .baseBackground + addChild(pageViewController) + pageViewController.delegate = self + pageViewController.dataSource = self + } + + private func configureNavigationBar() { + navigationController?.navigationBar.isHidden = false + navigationController?.navigationBar.titleTextAttributes = [ + .font: UIFont.ownglyphBerry(size: 17), + .foregroundColor: UIColor.mhTitle + ] + + // 공통 스타일 정의 + let normalAttributes: [NSAttributedString.Key: Any] = [ + .font: UIFont.ownglyphBerry(size: 17), + .foregroundColor: UIColor.mhTitle + ] + let selectedAttributes: [NSAttributedString.Key: Any] = [ + .font: UIFont.ownglyphBerry(size: 17), + .foregroundColor: UIColor.mhTitle + ] + + // 왼쪽 닫기 버튼 + navigationItem.leftBarButtonItem = UIBarButtonItem( + title: "닫기", + normal: normalAttributes, + selected: selectedAttributes + ) { [weak self] in + self?.navigationController?.popViewController(animated: true) + } + + // 오른쪽 책 속지 수정 버튼 + navigationItem.rightBarButtonItem = UIBarButtonItem( + title: "수정", + normal: normalAttributes, + selected: selectedAttributes + ) { [weak self] in + // TODO: - 추후 책 속지 수정 페이지로 넘어가는 로직 필요 + } + } + + private func configureConstraints() { + view.addSubview(pageViewController.view) + pageViewController.view.fillSuperview() + } + + // MARK: - Set PageviewController + private func configurePageViewController() { + guard let startViewController = makeNewPageViewController(index: 0) else { return } + let viewControllers = [startViewController] + pageViewController.setViewControllers(viewControllers, direction: .forward, animated: true, completion: nil) + } + + private func makeNewPageViewController(index: Int) -> ReadPageViewController? { + // TODO: - 로직 수정 필요 + return ReadPageViewController(viewModel: ReadPageViewModel(index: index)) + } +} + +// MARK: - UIPageViewControllerDelegate +extension BookViewController: UIPageViewControllerDelegate { + // TODO: - Page transition 감지 +} + +// MARK: - UIPageViewControllerDataSource +extension BookViewController: UIPageViewControllerDataSource { + func pageViewController( + _ pageViewController: UIPageViewController, + viewControllerBefore viewController: UIViewController + ) -> UIViewController? { + guard let targetViewController = viewController as? ReadPageViewController else { return nil } + let pageIndex = targetViewController.getPageIndex() + + return pageIndex == 0 + ? nil + : makeNewPageViewController(index: pageIndex - 1) + } + + func pageViewController( + _ pageViewController: UIPageViewController, + viewControllerAfter viewController: UIViewController + ) -> UIViewController? { + guard let targetViewController = viewController as? ReadPageViewController else { return nil } + let pageIndex = targetViewController.getPageIndex() + + return pageIndex == viewModel.pageList.count - 1 + ? nil + : makeNewPageViewController(index: pageIndex + 1) + } +} diff --git a/MemorialHouse/MHPresentation/MHPresentation/Source/Book/BookViewModel.swift b/MemorialHouse/MHPresentation/MHPresentation/Source/Book/BookViewModel.swift new file mode 100644 index 00000000..7922cfd7 --- /dev/null +++ b/MemorialHouse/MHPresentation/MHPresentation/Source/Book/BookViewModel.swift @@ -0,0 +1,27 @@ +import Foundation +import Combine + +final class BookViewModel: ViewModelType { + enum Input { + + } + + enum Output { + + } + + private let output = PassthroughSubject() + private var cancellables = Set() + private(set) var pageList = ["one", "two", "three"] + + func transform(input: AnyPublisher) -> AnyPublisher { + input.sink { event in + switch event { + + } + } + .store(in: &cancellables) + + return output.eraseToAnyPublisher() + } +} diff --git a/MemorialHouse/MHPresentation/MHPresentation/Source/ReadPage/ReadPageViewController.swift b/MemorialHouse/MHPresentation/MHPresentation/Source/ReadPage/ReadPageViewController.swift new file mode 100644 index 00000000..f5f4c778 --- /dev/null +++ b/MemorialHouse/MHPresentation/MHPresentation/Source/ReadPage/ReadPageViewController.swift @@ -0,0 +1,65 @@ +import UIKit + +final class ReadPageViewController: UIViewController { + // MARK: - UI Components + private let textView: UITextView = { + let textView = UITextView() + textView.font = .ownglyphBerry(size: 20) + textView.textColor = .mhTitle + textView.backgroundColor = .clear + textView.textContainerInset = UIEdgeInsets(top: 20, left: 32, bottom: 20, right: 32) + textView.layer.borderWidth = 3 + textView.layer.borderColor = UIColor.mhTitle.cgColor + textView.isScrollEnabled = false + textView.isEditable = false + + return textView + }() + private var textLayoutManager: NSTextLayoutManager? + private var textStorage: NSTextStorage? + private var textContainer: NSTextContainer? + + // MARK: - Property + private let viewModel: ReadPageViewModel + + // MARK: - Initialize + init(viewModel: ReadPageViewModel) { + self.viewModel = viewModel + + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { + self.viewModel = ReadPageViewModel(index: 0) + + super.init(nibName: nil, bundle: nil) + } + + // MARK: - View Life Cycle + override func viewDidLoad() { + super.viewDidLoad() + + setup() + configureConstraints() + } + + // MARK: - Setup & Configure + private func setup() { + view.backgroundColor = .baseBackground + textView.text = String(viewModel.index) + } + + private func configureConstraints() { + view.addSubview(textView) + textView.setAnchor( + top: view.topAnchor, constantTop: 10, + leading: view.leadingAnchor, constantLeading: 10, + bottom: view.bottomAnchor, constantBottom: 10, + trailing: view.trailingAnchor, constantTrailing: 10 + ) + } + + func getPageIndex() -> Int { + return viewModel.index + } +} diff --git a/MemorialHouse/MHPresentation/MHPresentation/Source/ReadPage/ReadPageViewModel.swift b/MemorialHouse/MHPresentation/MHPresentation/Source/ReadPage/ReadPageViewModel.swift new file mode 100644 index 00000000..77410117 --- /dev/null +++ b/MemorialHouse/MHPresentation/MHPresentation/Source/ReadPage/ReadPageViewModel.swift @@ -0,0 +1,31 @@ +import Foundation +import Combine + +final class ReadPageViewModel: ViewModelType { + enum Input { + + } + + enum Output { + + } + + private let output = PassthroughSubject() + private var cancellables = Set() + let index: Int + + init(index: Int) { + self.index = index + } + + func transform(input: AnyPublisher) -> AnyPublisher { + input.sink { event in + switch event { + + } + } + .store(in: &cancellables) + + return output.eraseToAnyPublisher() + } +}