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
1 change: 1 addition & 0 deletions iBox/Sources/BoxList/BoxListViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ extension BoxListViewController: BoxListViewDelegate {
} else {
// μΊμ‹œμ— μ—†λŠ” 경우, μƒˆλ‘œμš΄ viewController μΈμŠ€ν„΄μŠ€λ₯Ό μƒμ„±ν•˜κ³  μΊμ‹œμ— μΆ”κ°€ν•©λ‹ˆλ‹€.
let viewController = WebViewController()
viewController.delegate = self
viewController.selectedWebsite = url
viewController.title = name
WebCacheManager.shared.cacheData(forKey: id, viewController: viewController)
Expand Down
2 changes: 1 addition & 1 deletion iBox/Sources/Extension/UIColor+Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ extension UIColor {
static let box = UIColor(hex: 0xFF7F29)
static let box2 = UIColor(hex: 0xFF9548)
static let box3 = UIColor(hex: 0xFFDC6E)
static let tableViewBackgroundColor = color(light: .systemGroupedBackground, dark: .systemGray5)
static let tableViewBackgroundColor = color(light: .systemGroupedBackground, dark: .systemGray4)
static let folderGray = color(light: .systemGray3, dark: .systemGray2)
static let webIconColor = color(light: .black, dark: .systemGray)
static let dimmedViewColor = UIColor.black.withAlphaComponent(0.75)
Expand Down
1 change: 1 addition & 0 deletions iBox/Sources/Extension/UIFont+Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ extension UIFont {
static let cellTitleFont = UIFont.systemFont(ofSize: 16.0)
static let cellDescriptionFont = UIFont.systemFont(ofSize: 13.0, weight: .regular)
static let descriptionFont = UIFont.systemFont(ofSize: 14.0)
static let refreshControlFont = UIFont.boldSystemFont(ofSize: 12.0)

}
119 changes: 119 additions & 0 deletions iBox/Sources/Web/RefreshControl.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
//
// RefreshControl.swift
// iBox
//
// Created by jiyeon on 4/4/24.
//

import UIKit

import SnapKit

enum RefreshControlType {
case addBookmark
case refresh
case back
}

class RefreshControl: UIView {

var currentType: RefreshControlType?

// MARK: - UI Components

let addBookmarkButton = UIButton().then {
$0.configuration = .plain()
$0.tintColor = .label
$0.configuration?.image = UIImage(systemName: "bookmark.circle")
$0.configuration?.imagePadding = 10
$0.configuration?.imagePlacement = .top
$0.configuration?.preferredSymbolConfigurationForImage = .init(pointSize: 20.0)
$0.configuration?.attributedTitle = AttributedString("뢁마크 μΆ”κ°€", attributes: AttributeContainer([NSAttributedString.Key.font: UIFont.refreshControlFont]))
$0.layer.cornerRadius = 15
}

let refreshButton = UIButton().then {
$0.configuration = .plain()
$0.tintColor = .label
$0.configuration?.image = UIImage(systemName: "arrow.clockwise.circle")
$0.configuration?.imagePadding = 10
$0.configuration?.imagePlacement = .top
$0.configuration?.preferredSymbolConfigurationForImage = .init(pointSize: 20.0)
$0.configuration?.attributedTitle = AttributedString("μƒˆλ‘œκ³ μΉ¨", attributes: AttributeContainer([NSAttributedString.Key.font: UIFont.refreshControlFont]))
$0.layer.cornerRadius = 15
}

let backButton = UIButton().then {
$0.configuration = .plain()
$0.tintColor = .label
$0.configuration?.image = UIImage(systemName: "arrowshape.turn.up.backward.circle")
$0.configuration?.imagePadding = 10
$0.configuration?.imagePlacement = .top
$0.configuration?.preferredSymbolConfigurationForImage = .init(pointSize: 20.0)
$0.configuration?.attributedTitle = AttributedString("처음으둜 이동", attributes: AttributeContainer([NSAttributedString.Key.font: UIFont.refreshControlFont]))
$0.layer.cornerRadius = 15
}

let stackView = UIStackView().then {
$0.axis = .horizontal
$0.distribution = .fillEqually
$0.spacing = 20
}


// MARK: - Initializer

override init(frame: CGRect) {
super.init(frame: frame)
setupProperty()
setupHierarchy()
setupLayout()
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

// MAKR: - Setup Methods

private func setupProperty() {
backgroundColor = .backgroundColor
isUserInteractionEnabled = true
}

private func setupHierarchy() {
addSubview(stackView)
stackView.addArrangedSubview(addBookmarkButton)
stackView.addArrangedSubview(refreshButton)
stackView.addArrangedSubview(backButton)
}

private func setupLayout() {
stackView.snp.makeConstraints { make in
make.leading.bottom.trailing.equalToSuperview().inset(20)
}
}

func setSelected(_ type: RefreshControlType) {
if type == currentType { return }
currentType = type
clear()
switch type {
case .addBookmark: addBookmarkButton.backgroundColor = .tableViewBackgroundColor
case .refresh: refreshButton.backgroundColor = .tableViewBackgroundColor
case .back: backButton.backgroundColor = .tableViewBackgroundColor
}
if UserDefaultsManager.isHaptics {
let generator = UIImpactFeedbackGenerator(style: .light)
generator.prepare()
generator.impactOccurred()
}
}

func clear() {
[addBookmarkButton, refreshButton, backButton].forEach { button in
button.backgroundColor = .clear
}
}

}
83 changes: 75 additions & 8 deletions iBox/Sources/Web/WebView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import SnapKit

class WebView: UIView {

var delegate: WebViewDelegate?

private var progressObserver: NSKeyValueObservation?

var selectedWebsite: URL? {
Expand All @@ -20,19 +22,22 @@ class WebView: UIView {
}
}

private var refreshControlHeight: CGFloat = 120.0
private var isActive = false

// MARK: - UI Components


private let webView:WKWebView

private let refreshControl = UIRefreshControl()

private let progressView = UIProgressView().then {
$0.progressViewStyle = .bar
$0.tintColor = .label
$0.sizeToFit()
}

private var refreshControl: RefreshControl?

// MARK: - Initializer

override init(frame: CGRect) {
Expand Down Expand Up @@ -64,8 +69,6 @@ class WebView: UIView {
private func setupProperty() {
backgroundColor = .backgroundColor
webView.navigationDelegate = self
webView.scrollView.refreshControl = refreshControl
refreshControl.addTarget(self, action: #selector(handleRefreshControl), for: .valueChanged)
progressObserver = webView.observe(\.estimatedProgress, options: .new) { [weak self] webView, _ in
self?.progressView.setProgress(Float(webView.estimatedProgress), animated: true)
}
Expand All @@ -86,16 +89,59 @@ class WebView: UIView {
}
}

func setupRefreshControl() {
// pan gesture
let panGestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(handleSwipe))
panGestureRecognizer.delegate = self // UIGestureRecognizerDelegate
addGestureRecognizer(panGestureRecognizer)
// refresh control
let refreshControl = RefreshControl(frame: .init(x: 0, y: -frame.size.height, width: frame.size.width, height: frame.size.height))
webView.scrollView.addSubview(refreshControl)
webView.scrollView.backgroundColor = .backgroundColor
webView.scrollView.delegate = self // UIScrollViewDelegate
self.refreshControl = refreshControl
}

private func loadWebsite() {
guard let url = selectedWebsite else { return }
webView.load(URLRequest(url: url))
webView.allowsBackForwardNavigationGestures = true
}

@objc private func handleRefreshControl() {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.7) { [weak self] in
self?.webView.reload()
self?.refreshControl.endRefreshing()
@objc func handleSwipe(_ gesture: UIPanGestureRecognizer) {
guard isActive, let refreshControl = refreshControl else { return }

let translation = gesture.translation(in: self)
if gesture.state == .changed {
if abs(translation.x) > 60.0 {
if translation.x > 0 { // 였λ₯Έμͺ½ μŠ€μ™€μ΄ν”„ : 처음 뢁마크둜 λŒμ•„κ°€κΈ°
refreshControl.setSelected(.back)
} else { // μ™Όμͺ½ μŠ€μ™€μ΄ν”„ : ν˜„μž¬ 링크 뢁마크 μΆ”κ°€
refreshControl.setSelected(.addBookmark)
}
} else { // μ•„λž˜ : μƒˆλ‘œκ³ μΉ¨
refreshControl.setSelected(.refresh)
}
} else if gesture.state == .ended { // μ‚¬μš©μžμ˜ ν„°μΉ˜κ°€ 끝났을 λ•Œ
switch refreshControl.currentType {
case .addBookmark:
guard let url = webView.url else { return }
delegate?.pushAddBookMarkViewController(url: url)
case .refresh:
self.webView.reload()
case .back:
loadWebsite()
case .none: break
}
// 제슀처 μ™„λ£Œ ν›„ μ΄ˆκΈ°ν™”
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
refreshControl.clear()
}
}
// 제슀처 μ΄ˆκΈ°ν™”
if gesture.state == .ended || gesture.state == .cancelled {
gesture.setTranslation(CGPoint.zero, in: self)
refreshControl.currentType = nil
}
}

Expand All @@ -116,5 +162,26 @@ extension WebView: WKNavigationDelegate {
self.progressView.isHidden = true
}
}

}

extension WebView: UIScrollViewDelegate {

func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.contentOffset.y < -refreshControlHeight {
isActive = true
} else {
isActive = false
}
}

}

extension WebView: UIGestureRecognizerDelegate {

func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
// λ‹€λ₯Έ 제슀처 인식기와 λ™μ‹œμ— μΈμ‹λ˜λ„λ‘ ν—ˆμš©
return true
}

}
27 changes: 27 additions & 0 deletions iBox/Sources/Web/WebViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,13 @@

import UIKit

protocol WebViewDelegate {
func pushAddBookMarkViewController(url: URL)
}

class WebViewController: BaseViewController<WebView>, BaseViewControllerProtocol {

var delegate: AddBookmarkViewControllerProtocol?
var selectedWebsite: URL?

// MARK: - Life Cycle
Expand All @@ -20,13 +25,35 @@ class WebViewController: BaseViewController<WebView>, BaseViewControllerProtocol
view.backgroundColor = .backgroundColor

guard let contentView = contentView as? WebView else { return }
contentView.delegate = self
contentView.selectedWebsite = selectedWebsite
}

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
guard let contentView = contentView as? WebView else { return }
contentView.setupRefreshControl()
}

// MARK: - BaseViewControllerProtocol

func setupNavigationBar() {
setNavigationBarHidden(true)
}

}

extension WebViewController: WebViewDelegate {

func pushAddBookMarkViewController(url: URL) {
URLDataManager.shared.incomingData = url.absoluteString

let addBookmarkViewController = AddBookmarkViewController()
addBookmarkViewController.delegate = delegate

let navigationController = UINavigationController(rootViewController: addBookmarkViewController)
navigationController.modalPresentationStyle = .pageSheet
self.present(navigationController, animated: true, completion: nil)
}

}