首页播放记录

This commit is contained in:
zeng 2026-03-03 16:21:54 +08:00
parent 001f392af6
commit b6a022daa9
12 changed files with 310 additions and 4 deletions

View File

@ -135,6 +135,7 @@
F3B312BD2F30B0A10093B180 /* XSSearchSuggestionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3B312B82F30B0A10093B180 /* XSSearchSuggestionCell.swift */; };
F3B312BE2F30B0A10093B180 /* XSSearchResultCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3B312B92F30B0A10093B180 /* XSSearchResultCell.swift */; };
F3B312BF2F30B2000093B180 /* XSSearchHistoryHotView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3B312B52F30B2000093B180 /* XSSearchHistoryHotView.swift */; };
F3F683ED2F56C380008AF250 /* XSHomeHistoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3F683EC2F56C380008AF250 /* XSHomeHistoryView.swift */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@ -270,6 +271,7 @@
F3B312B62F319CBE0093B180 /* XSEmpty.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XSEmpty.swift; sourceTree = "<group>"; };
F3B312B82F30B0A10093B180 /* XSSearchSuggestionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XSSearchSuggestionCell.swift; sourceTree = "<group>"; };
F3B312B92F30B0A10093B180 /* XSSearchResultCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XSSearchResultCell.swift; sourceTree = "<group>"; };
F3F683EC2F56C380008AF250 /* XSHomeHistoryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XSHomeHistoryView.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -496,6 +498,7 @@
F3B312AC2F30ACF60093B180 /* XSSearchTagsView.swift */,
F3B312B82F30B0A10093B180 /* XSSearchSuggestionCell.swift */,
F3B312B92F30B0A10093B180 /* XSSearchResultCell.swift */,
F3F683EC2F56C380008AF250 /* XSHomeHistoryView.swift */,
);
path = View;
sourceTree = "<group>";
@ -967,6 +970,7 @@
F35547FA2F4E9F0A006F28CD /* XSView.swift in Sources */,
F347D2BA2F03BABC00786648 /* XSHomeData.swift in Sources */,
F3585C4B2F14FD1000EEC469 /* XSShortDetailPlayerControlView.swift in Sources */,
F3F683ED2F56C380008AF250 /* XSHomeHistoryView.swift in Sources */,
F347D2A12F03A84300786648 /* XSScreen.swift in Sources */,
F35548062F4FD6DA006F28CD /* XSMinePlayHistoryView.swift in Sources */,
F347D2992F03730E00786648 /* XSTabBarController.swift in Sources */,

View File

@ -22,10 +22,10 @@ extension UIView {
xs_layoutSubviews()
xs_updateRoundedCorner()
//
// if let effectView = effectView, effectView.frame != self.bounds {
// effectView.frame = self.bounds
// }
if let effectView = effectView, effectView.frame != self.bounds {
effectView.frame = self.bounds
}
}
}
@ -63,3 +63,32 @@ extension UIView {
}
}
//MARK: -------------- --------------
extension UIView {
private var effectView: UIVisualEffectView? {
get {
return objc_getAssociatedObject(self, &AssociatedKeys.xs_effect) as? UIVisualEffectView
}
set {
objc_setAssociatedObject(self, &AssociatedKeys.xs_effect, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
///
func xs_addEffectView(style: UIBlurEffect.Style = .dark) {
if self.effectView == nil {
let blur = UIBlurEffect(style: style)
let effectView = UIVisualEffectView(effect: blur)
effectView.isUserInteractionEnabled = false
self.addSubview(effectView)
self.sendSubviewToBack(effectView)
self.effectView = effectView
}
}
///
func xs_removeEffectView() {
self.effectView?.removeFromSuperview()
self.effectView = nil
}
}

View File

@ -66,10 +66,23 @@ class XSHomeViewController: XSViewController {
private lazy var listContainerView: JXSegmentedListContainerView = {
return JXSegmentedListContainerView(dataSource: self)
}()
private lazy var historyView: XSHomeHistoryView = {
let view = XSHomeHistoryView()
view.isHidden = true
return view
}()
deinit {
NotificationCenter.default.removeObserver(self)
}
// MARK: - Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(loginStateDidChangeNotification), name: XSLoginManager.loginStateDidChangeNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(networkStatusDidChangeNotification), name: XSNetworkMonitorManager.networkStatusDidChangeNotification, object: nil)
xs_setupUI()
}
@ -77,6 +90,27 @@ class XSHomeViewController: XSViewController {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(true, animated: true)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
Task {
await requestVideoHistory()
}
}
@objc private func networkStatusDidChangeNotification() {
Task {
await requestVideoHistory()
}
}
@objc private func loginStateDidChangeNotification() {
self.historyView.isHidden = true
Task {
await requestVideoHistory()
}
}
}
// MARK: - UI Setup
@ -86,6 +120,7 @@ extension XSHomeViewController {
view.addSubview(listContainerView)
view.addSubview(searchButton)
view.addSubview(segmentedView)
view.addSubview(historyView)
searchButton.snp.makeConstraints { make in
make.left.equalToSuperview().offset(16)
@ -109,6 +144,12 @@ extension XSHomeViewController {
// make.top.equalTo(segmentedView.snp.bottom).offset(8)
}
historyView.snp.makeConstraints { make in
make.left.equalToSuperview().offset(8)
make.centerX.equalToSuperview()
make.bottom.equalToSuperview().offset(-(XSScreen.customTabBarHeight + 5))
}
}
}
@ -129,3 +170,18 @@ extension XSHomeViewController: JXSegmentedListContainerViewDataSource {
return viewControllers[index]
}
}
extension XSHomeViewController {
private func requestVideoHistory() async {
guard let list = await XSVideoAPI.requestPlayHistorys(page: 1, pageSize: 1) else { return }
guard let model = list.first else {
self.historyView.isHidden = true
return
}
self.historyView.isHidden = false
self.historyView.model = model
}
}

View File

@ -0,0 +1,152 @@
//
// XSHomeHistoryView.swift
// XSeri
//
// Created by 鸿 on 2026/3/3.
//
import UIKit
import SnapKit
class XSHomeHistoryView: UIView {
override var intrinsicContentSize: CGSize {
return .init(width: XSScreen.width, height: 60)
}
var model: XSShortModel? {
didSet {
coverImageView.xs_setImage(model?.image_url)
nameLabel.text = model?.name
epLabel.text = "Last WatchedEp.\(model?.current_episode ?? "")"
}
}
private lazy var borderImage = UIImage(named: "gradient_color_image_02")
private lazy var coverImageView: XSImageView = {
let imageView = XSImageView()
imageView.layer.cornerRadius = 4
return imageView
}()
private lazy var nameLabel: UILabel = {
let label = UILabel()
label.font = .font(ofSize: 12, weight: .medium)
label.textColor = .FFDAA_4
return label
}()
private lazy var epLabel: UILabel = {
let label = UILabel()
label.font = .font(ofSize: 12, weight: .regular)
label.textColor = .white.withAlphaComponent(0.8)
return label
}()
private lazy var continueButton: UIButton = {
var configuration = UIButton.Configuration.plain()
configuration.background.backgroundColor = .FFDAA_4.withAlphaComponent(0.15)
configuration.background.cornerRadius = 13.5
configuration.contentInsets = .init(top: 0, leading: 9, bottom: 0, trailing: 9)
configuration.attributedTitle = AttributedString("Continue".localized, attributes: AttributeContainer([
.font : UIFont.font(ofSize: 12, weight: .medium),
.foregroundColor : UIColor.white
]))
let button = UIButton(configuration: configuration)
button.isUserInteractionEnabled = false
return button
}()
private lazy var closeButton: UIButton = {
let button = UIButton(type: .custom, primaryAction: UIAction(handler: { [weak self] _ in
guard let self = self else { return }
self.isHidden = true
}))
button.setImage(UIImage(named: "close_icon_01"), for: .normal)
return button
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.layer.cornerRadius = 12
self.layer.masksToBounds = true
self.layer.borderColor = UIColor.FFDAA_4.cgColor
self.layer.borderWidth = 1
self.backgroundColor = ._352_D_25.withAlphaComponent(0.8)
self.xs_addEffectView()
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture))
self.addGestureRecognizer(tap)
xs_setupUI()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
self.borderImage = self.borderImage?.xs_resized(to: self.bounds.size)
self.layer.borderColor = UIColor.init(patternImage: self.borderImage!).cgColor
}
@objc private func handleTapGesture() {
guard let id = self.model?.short_play_id else { return }
let vc = XSShortDetailViewController()
vc.shortId = id
self.viewController?.navigationController?.pushViewController(vc, animated: true)
}
}
extension XSHomeHistoryView {
private func xs_setupUI() {
addSubview(coverImageView)
addSubview(continueButton)
addSubview(nameLabel)
addSubview(epLabel)
addSubview(closeButton)
coverImageView.snp.makeConstraints { make in
make.left.equalToSuperview().offset(6)
make.centerY.equalToSuperview()
make.width.equalTo(36)
make.height.equalTo(48)
}
continueButton.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.right.equalToSuperview().offset(-24)
make.height.equalTo(27)
}
nameLabel.snp.makeConstraints { make in
make.top.equalToSuperview().offset(13)
make.left.equalTo(coverImageView.snp.right).offset(12)
make.right.lessThanOrEqualTo(continueButton.snp.left).offset(-20)
}
epLabel.snp.makeConstraints { make in
make.left.equalTo(nameLabel)
make.bottom.equalToSuperview().offset(-13)
make.right.lessThanOrEqualTo(continueButton.snp.left).offset(-20)
}
closeButton.snp.makeConstraints { make in
make.right.equalToSuperview().offset(-6)
make.top.equalToSuperview().offset(6)
}
}
}

View File

@ -0,0 +1,20 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0x25",
"green" : "0x2D",
"red" : "0x35"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "关闭-按钮-icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "关闭-按钮-icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 B

View File

@ -0,0 +1,22 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "Rectangle 346272051@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "Rectangle 346272051@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@ -38,6 +38,7 @@
"feedback" = "Feedback";
"feedback_detail" = "Feedback Details";
"account_deletion" = "Account Deletion";
"Continue" = "Continue";
"empty_title_01" = "We couldnt find any dramas";