mirror of
https://github.com/mastodon/mastodon-ios.git
synced 2025-02-02 02:16:50 +01:00
feat: add discovery intro banner
This commit is contained in:
parent
1d96609003
commit
d70f734957
@ -499,7 +499,8 @@
|
||||
"hashtags": "Hashtags",
|
||||
"news": "News",
|
||||
"for_you": "For You"
|
||||
}
|
||||
},
|
||||
"intro": "These are the posts gaining traction in your corner of Mastodon."
|
||||
},
|
||||
"favorite": {
|
||||
"title": "Your Favorites"
|
||||
|
@ -148,6 +148,7 @@
|
||||
DB0618072785A8880030EE79 /* MastodonRegisterViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0618062785A8880030EE79 /* MastodonRegisterViewModel+Diffable.swift */; };
|
||||
DB06180A2785B2AB0030EE79 /* MastodonRegisterAvatarTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0618092785B2AB0030EE79 /* MastodonRegisterAvatarTableViewCell.swift */; };
|
||||
DB084B5725CBC56C00F898ED /* Status.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB084B5625CBC56C00F898ED /* Status.swift */; };
|
||||
DB0A322E280EE9FD001729D2 /* DiscoveryIntroBannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0A322D280EE9FD001729D2 /* DiscoveryIntroBannerView.swift */; };
|
||||
DB0AC6FC25CD02E600D75117 /* APIService+Instance.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0AC6FB25CD02E600D75117 /* APIService+Instance.swift */; };
|
||||
DB0C946526A6FD4D0088FB11 /* AlamofireImage in Frameworks */ = {isa = PBXBuildFile; productRef = DB0C946426A6FD4D0088FB11 /* AlamofireImage */; };
|
||||
DB0C947726A7FE840088FB11 /* NotificationAvatarButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0C947626A7FE840088FB11 /* NotificationAvatarButton.swift */; };
|
||||
@ -870,6 +871,7 @@
|
||||
DB0618062785A8880030EE79 /* MastodonRegisterViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "MastodonRegisterViewModel+Diffable.swift"; sourceTree = "<group>"; };
|
||||
DB0618092785B2AB0030EE79 /* MastodonRegisterAvatarTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonRegisterAvatarTableViewCell.swift; sourceTree = "<group>"; };
|
||||
DB084B5625CBC56C00F898ED /* Status.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Status.swift; sourceTree = "<group>"; };
|
||||
DB0A322D280EE9FD001729D2 /* DiscoveryIntroBannerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiscoveryIntroBannerView.swift; sourceTree = "<group>"; };
|
||||
DB0AC6FB25CD02E600D75117 /* APIService+Instance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Instance.swift"; sourceTree = "<group>"; };
|
||||
DB0C947626A7FE840088FB11 /* NotificationAvatarButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationAvatarButton.swift; sourceTree = "<group>"; };
|
||||
DB0EF72A26FDB1D200347686 /* SidebarListCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarListCollectionViewCell.swift; sourceTree = "<group>"; };
|
||||
@ -2023,6 +2025,14 @@
|
||||
path = CoreDataStack;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DB0A322F280EEA00001729D2 /* View */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DB0A322D280EE9FD001729D2 /* DiscoveryIntroBannerView.swift */,
|
||||
);
|
||||
path = View;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
DB0C947826A7FE950088FB11 /* Button */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -3108,6 +3118,7 @@
|
||||
DBDFF1912805544800557A48 /* Discovery */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DB0A322F280EEA00001729D2 /* View */,
|
||||
DBDFF19828055A0900557A48 /* Posts */,
|
||||
DB3E6FDE2806A41200B035AE /* Hashtags */,
|
||||
DB3E6FED2806D7FC00B035AE /* News */,
|
||||
@ -4085,6 +4096,7 @@
|
||||
DB8AF55D25C138B7002E6C99 /* UIViewController.swift in Sources */,
|
||||
DB7F48452620241000796008 /* ProfileHeaderViewModel.swift in Sources */,
|
||||
DB647C5926F1EA2700F7F82C /* WizardPreference.swift in Sources */,
|
||||
DB0A322E280EE9FD001729D2 /* DiscoveryIntroBannerView.swift in Sources */,
|
||||
2D3F9E0425DFA133004262D9 /* UITapGestureRecognizer.swift in Sources */,
|
||||
5DDDF1992617447F00311060 /* Mastodon+Entity+Tag.swift in Sources */,
|
||||
5B90C45F262599800002E742 /* SettingsToggleTableViewCell.swift in Sources */,
|
||||
|
@ -8,6 +8,7 @@
|
||||
import os.log
|
||||
import UIKit
|
||||
import Combine
|
||||
import MastodonUI
|
||||
|
||||
final class DiscoveryPostsViewController: UIViewController, NeedsDependency, MediaPreviewableViewController {
|
||||
|
||||
@ -31,6 +32,8 @@ final class DiscoveryPostsViewController: UIViewController, NeedsDependency, Med
|
||||
}()
|
||||
|
||||
let refreshControl = UIRefreshControl()
|
||||
|
||||
let discoveryIntroBannerView = DiscoveryIntroBannerView()
|
||||
|
||||
deinit {
|
||||
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
|
||||
@ -60,6 +63,21 @@ extension DiscoveryPostsViewController {
|
||||
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
||||
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
|
||||
])
|
||||
|
||||
discoveryIntroBannerView.translatesAutoresizingMaskIntoConstraints = false
|
||||
view.addSubview(discoveryIntroBannerView)
|
||||
NSLayoutConstraint.activate([
|
||||
discoveryIntroBannerView.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor),
|
||||
discoveryIntroBannerView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||
discoveryIntroBannerView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
||||
])
|
||||
|
||||
discoveryIntroBannerView.delegate = self
|
||||
discoveryIntroBannerView.isHidden = UserDefaults.shared.discoveryIntroBannerNeedsHidden
|
||||
UserDefaults.shared.publisher(for: \.discoveryIntroBannerNeedsHidden)
|
||||
.receive(on: DispatchQueue.main)
|
||||
.assign(to: \.isHidden, on: discoveryIntroBannerView)
|
||||
.store(in: &disposeBag)
|
||||
|
||||
tableView.delegate = self
|
||||
viewModel.setupDiffableDataSource(
|
||||
@ -146,3 +164,10 @@ extension DiscoveryPostsViewController: ScrollViewContainer {
|
||||
tableView
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - DiscoveryIntroBannerViewDelegate
|
||||
extension DiscoveryPostsViewController: DiscoveryIntroBannerViewDelegate {
|
||||
func discoveryIntroBannerView(_ bannerView: DiscoveryIntroBannerView, closeButtonDidPressed button: UIButton) {
|
||||
UserDefaults.shared.discoveryIntroBannerNeedsHidden = true
|
||||
}
|
||||
}
|
||||
|
101
Mastodon/Scene/Discovery/View/DiscoveryIntroBannerView.swift
Normal file
101
Mastodon/Scene/Discovery/View/DiscoveryIntroBannerView.swift
Normal file
@ -0,0 +1,101 @@
|
||||
//
|
||||
// DiscoveryIntroBannerView.swift
|
||||
// Mastodon
|
||||
//
|
||||
// Created by MainasuK on 2022-4-19.
|
||||
//
|
||||
|
||||
import os.log
|
||||
import UIKit
|
||||
import Combine
|
||||
import MastodonAsset
|
||||
|
||||
public protocol DiscoveryIntroBannerViewDelegate: AnyObject {
|
||||
func discoveryIntroBannerView(_ bannerView: DiscoveryIntroBannerView, closeButtonDidPressed button: UIButton)
|
||||
}
|
||||
|
||||
public final class DiscoveryIntroBannerView: UIView {
|
||||
|
||||
let logger = Logger(subsystem: "DiscoveryIntroBannerView", category: "View")
|
||||
|
||||
var _disposeBag = Set<AnyCancellable>()
|
||||
|
||||
public weak var delegate: DiscoveryIntroBannerViewDelegate?
|
||||
|
||||
let label: UILabel = {
|
||||
let label = UILabel()
|
||||
label.font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 16, weight: .regular))
|
||||
label.textColor = Asset.Colors.Label.primary.color
|
||||
label.text = "These are the posts gaining traction in your corner of Mastodon." // TODO: i18n
|
||||
label.numberOfLines = 0
|
||||
return label
|
||||
}()
|
||||
|
||||
let closeButton: HitTestExpandedButton = {
|
||||
let button = HitTestExpandedButton(type: .system)
|
||||
button.setImage(UIImage(systemName: "xmark.circle.fill"), for: .normal)
|
||||
button.tintColor = Asset.Colors.Label.secondary.color
|
||||
return button
|
||||
}()
|
||||
|
||||
public override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
_init()
|
||||
}
|
||||
|
||||
public required init?(coder: NSCoder) {
|
||||
super.init(coder: coder)
|
||||
_init()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension DiscoveryIntroBannerView {
|
||||
private func _init() {
|
||||
preservesSuperviewLayoutMargins = true
|
||||
|
||||
setupAppearance(theme: ThemeService.shared.currentTheme.value)
|
||||
ThemeService.shared.currentTheme
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] theme in
|
||||
guard let self = self else { return }
|
||||
self.setupAppearance(theme: theme)
|
||||
}
|
||||
.store(in: &_disposeBag)
|
||||
|
||||
closeButton.translatesAutoresizingMaskIntoConstraints = false
|
||||
addSubview(closeButton)
|
||||
NSLayoutConstraint.activate([
|
||||
closeButton.topAnchor.constraint(equalTo: topAnchor, constant: 16).priority(.required - 1),
|
||||
layoutMarginsGuide.trailingAnchor.constraint(equalTo: closeButton.trailingAnchor),
|
||||
closeButton.heightAnchor.constraint(equalToConstant: 20).priority(.required - 1),
|
||||
closeButton.widthAnchor.constraint(equalToConstant: 20).priority(.required - 1),
|
||||
])
|
||||
|
||||
label.translatesAutoresizingMaskIntoConstraints = false
|
||||
addSubview(label)
|
||||
NSLayoutConstraint.activate([
|
||||
label.topAnchor.constraint(equalTo: topAnchor, constant: 16).priority(.required - 1),
|
||||
label.leadingAnchor.constraint(equalTo: layoutMarginsGuide.leadingAnchor),
|
||||
closeButton.leadingAnchor.constraint(equalTo: label.trailingAnchor, constant: 10),
|
||||
bottomAnchor.constraint(equalTo: label.bottomAnchor, constant: 16).priority(.required - 1),
|
||||
])
|
||||
|
||||
closeButton.addTarget(self, action: #selector(DiscoveryIntroBannerView.closeButtonDidPressed(_:)), for: .touchUpInside)
|
||||
}
|
||||
}
|
||||
|
||||
extension DiscoveryIntroBannerView {
|
||||
@objc private func closeButtonDidPressed(_ sender: UIButton) {
|
||||
logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)")
|
||||
delegate?.discoveryIntroBannerView(self, closeButtonDidPressed: sender)
|
||||
}
|
||||
}
|
||||
|
||||
extension DiscoveryIntroBannerView {
|
||||
|
||||
private func setupAppearance(theme: Theme) {
|
||||
backgroundColor = theme.systemBackgroundColor
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
//
|
||||
// Preference+Discovery.swift
|
||||
//
|
||||
//
|
||||
// Created by MainasuK on 2022-4-19.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
extension UserDefaults {
|
||||
|
||||
@objc public dynamic var discoveryIntroBannerNeedsHidden: Bool {
|
||||
get {
|
||||
return bool(forKey: #function)
|
||||
}
|
||||
set { self[#function] = newValue }
|
||||
}
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user