Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Comment): support multi-level comment preview, slightly refactor… #107

Merged
merged 1 commit into from
Jun 10, 2024
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
29 changes: 29 additions & 0 deletions BilibiliLive.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
0A41EE1C2A63102B0066444C /* dm.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41EE1A2A63102B0066444C /* dm.pb.swift */; };
0A41EE1D2A63102B0066444C /* dmView.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0A41EE1B2A63102B0066444C /* dmView.pb.swift */; };
27FECFCC2B0B98F400EC6A6D /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 27FECFCB2B0B98F400EC6A6D /* Localizable.xcstrings */; };
2806E51E2C1593A000164C10 /* LookinServer in Frameworks */ = {isa = PBXBuildFile; productRef = 2806E51D2C1593A000164C10 /* LookinServer */; };
2806E5202C15A59E00164C10 /* ReplyDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2806E51F2C15A59E00164C10 /* ReplyDetailViewController.swift */; };
2806E5232C16011B00164C10 /* ReplyCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2806E5212C16011B00164C10 /* ReplyCell.swift */; };
2806E5242C16011B00164C10 /* ReplyCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2806E5222C16011B00164C10 /* ReplyCell.xib */; };
2DBE4C4D2628818F00D20413 /* HistoryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DBE4C4C2628818F00D20413 /* HistoryViewController.swift */; };
490425F729AB54B200CDBC60 /* CategoryViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 490425F629AB54B200CDBC60 /* CategoryViewController.swift */; };
49078E47291BEA2400F556BD /* PocketSVG in Frameworks */ = {isa = PBXBuildFile; productRef = 49078E46291BEA2400F556BD /* PocketSVG */; };
Expand Down Expand Up @@ -138,6 +142,9 @@
0A41EE1A2A63102B0066444C /* dm.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = dm.pb.swift; sourceTree = "<group>"; };
0A41EE1B2A63102B0066444C /* dmView.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = dmView.pb.swift; sourceTree = "<group>"; };
27FECFCB2B0B98F400EC6A6D /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = "<group>"; };
2806E51F2C15A59E00164C10 /* ReplyDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReplyDetailViewController.swift; sourceTree = "<group>"; };
2806E5212C16011B00164C10 /* ReplyCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = ReplyCell.swift; path = BilibiliLive/Component/View/ReplyCell.swift; sourceTree = SOURCE_ROOT; };
2806E5222C16011B00164C10 /* ReplyCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ReplyCell.xib; path = BilibiliLive/Component/View/ReplyCell.xib; sourceTree = SOURCE_ROOT; };
2DBE4C4C2628818F00D20413 /* HistoryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryViewController.swift; sourceTree = "<group>"; };
490425F629AB54B200CDBC60 /* CategoryViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CategoryViewController.swift; sourceTree = "<group>"; };
490EC3E6290CC8F8001E00B6 /* RankingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RankingViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -317,6 +324,7 @@
49508E0F2943420100D26812 /* CocoaLumberjack in Frameworks */,
499C75EC293058C9003160FB /* CocoaAsyncSocket in Frameworks */,
F927ED9F2610B5C300EAB8E3 /* Kingfisher in Frameworks */,
2806E51E2C1593A000164C10 /* LookinServer in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -364,6 +372,9 @@
children = (
F9562C91261A0D2200573B74 /* VideoPlayerViewController.swift */,
F9EDADD2262AA421007CB99F /* VideoDetailViewController.swift */,
2806E51F2C15A59E00164C10 /* ReplyDetailViewController.swift */,
2806E5212C16011B00164C10 /* ReplyCell.swift */,
2806E5222C16011B00164C10 /* ReplyCell.xib */,
49389D6128AFEA2900B9DAFD /* VideoDanmuProvider.swift */,
498DB1DE291BC24700F95607 /* BMaskProvider.swift */,
49FB8EBF291F4C520045D5DE /* VMaskProvider.swift */,
Expand Down Expand Up @@ -697,6 +708,7 @@
49508E0E2943420100D26812 /* CocoaLumberjack */,
49508E102943420100D26812 /* CocoaLumberjackSwift */,
0A41EE182A630FEA0066444C /* SwiftProtobuf */,
2806E51D2C1593A000164C10 /* LookinServer */,
);
productName = BilibiliLive;
productReference = F9B57350260F5F7400771ED5 /* BilibiliLive.app */;
Expand Down Expand Up @@ -740,6 +752,7 @@
499C76142931A7AE003160FB /* XCRemoteSwiftPackageReference "SwiftyXMLParser" */,
49508E0D2943420100D26812 /* XCRemoteSwiftPackageReference "CocoaLumberjack" */,
0A41EE172A630FEA0066444C /* XCRemoteSwiftPackageReference "swift-protobuf" */,
2806E51C2C1593A000164C10 /* XCRemoteSwiftPackageReference "LookinServer" */,
);
productRefGroup = F9B57351260F5F7400771ED5 /* Products */;
projectDirPath = "";
Expand All @@ -759,6 +772,7 @@
49F918722931E927001D3EC3 /* AvTransportScpd.xml in Resources */,
F9B5735E260F5F7600771ED5 /* LaunchScreen.storyboard in Resources */,
F9B5735B260F5F7600771ED5 /* Assets.xcassets in Resources */,
2806E5242C16011B00164C10 /* ReplyCell.xib in Resources */,
49F9186E2931E3C9001D3EC3 /* DLNAInfo.xml in Resources */,
27FECFCC2B0B98F400EC6A6D /* Localizable.xcstrings in Resources */,
F9B57359260F5F7400771ED5 /* Main.storyboard in Resources */,
Expand Down Expand Up @@ -801,6 +815,7 @@
497361082BF1A16600ED213F /* Keys.swift in Sources */,
49E5F85028AF73C500FAA3CE /* BilibiliVideoResourceLoaderDelegate.swift in Sources */,
498CF2A22B63AABE0009793E /* dictionary.c in Sources */,
2806E5202C15A59E00164C10 /* ReplyDetailViewController.swift in Sources */,
494741C82902C45D005D6885 /* Array+..swift in Sources */,
498CF29E2B63AABE0009793E /* bit_cost.c in Sources */,
498CF29B2B63AABE0009793E /* utf8_util.c in Sources */,
Expand Down Expand Up @@ -849,6 +864,7 @@
494741E7290391A7005D6885 /* BLButton.swift in Sources */,
F927ED992610AD8D00EAB8E3 /* LiveViewController.swift in Sources */,
490EC3E7290CC8F8001E00B6 /* RankingViewController.swift in Sources */,
2806E5232C16011B00164C10 /* ReplyCell.swift in Sources */,
F927ED732610395300EAB8E3 /* DanmakuCell.swift in Sources */,
498CF2A92B63AABE0009793E /* bit_reader.c in Sources */,
498CF2972B63AABE0009793E /* encode.c in Sources */,
Expand Down Expand Up @@ -1126,6 +1142,14 @@
minimumVersion = 1.0.0;
};
};
2806E51C2C1593A000164C10 /* XCRemoteSwiftPackageReference "LookinServer" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/QMUI/LookinServer/";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 1.2.8;
};
};
49078E45291BEA2400F556BD /* XCRemoteSwiftPackageReference "PocketSVG" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/pocketsvg/PocketSVG.git";
Expand Down Expand Up @@ -1222,6 +1246,11 @@
package = 0A41EE172A630FEA0066444C /* XCRemoteSwiftPackageReference "swift-protobuf" */;
productName = SwiftProtobuf;
};
2806E51D2C1593A000164C10 /* LookinServer */ = {
isa = XCSwiftPackageProductDependency;
package = 2806E51C2C1593A000164C10 /* XCRemoteSwiftPackageReference "LookinServer" */;
productName = LookinServer;
};
49078E46291BEA2400F556BD /* PocketSVG */ = {
isa = XCSwiftPackageProductDependency;
package = 49078E45291BEA2400F556BD /* XCRemoteSwiftPackageReference "PocketSVG" */;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"originHash" : "f89b743e598074e66556cd063dd1258c33483d783163efc65f648349cece8790",
"pins" : [
{
"identity" : "alamofire",
Expand Down Expand Up @@ -45,6 +46,15 @@
"version" : "6.3.1"
}
},
{
"identity" : "lookinserver",
"kind" : "remoteSourceControl",
"location" : "https://github.com/QMUI/LookinServer/",
"state" : {
"revision" : "e553d1b689d147817dc54ad5c28fcff71e860101",
"version" : "1.2.8"
}
},
{
"identity" : "marqueelabel",
"kind" : "remoteSourceControl",
Expand Down Expand Up @@ -118,5 +128,5 @@
}
}
],
"version" : 2
"version" : 3
}
13 changes: 7 additions & 6 deletions BilibiliLive/Base.lproj/Main.storyboard
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder.AppleTV.Storyboard" version="3.0" toolsVersion="21507" targetRuntime="AppleTV" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder.AppleTV.Storyboard" version="3.0" toolsVersion="32700.99.1234" targetRuntime="AppleTV" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="appleTV" appearance="dark"/>
<dependencies>
<deployment identifier="tvOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="22684"/>
<capability name="Named colors" minToolsVersion="9.0"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
Expand Down Expand Up @@ -646,15 +646,15 @@
<constraints>
<constraint firstAttribute="height" constant="360" id="dCt-K6-G5Q"/>
</constraints>
<collectionViewFlowLayout key="collectionViewLayout" scrollDirection="horizontal" minimumLineSpacing="10" minimumInteritemSpacing="10" id="q3p-JN-DhJ">
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="10" minimumInteritemSpacing="10" id="q3p-JN-DhJ">
<size key="itemSize" width="582" height="360"/>
<size key="headerReferenceSize" width="0.0" height="0.0"/>
<size key="footerReferenceSize" width="0.0" height="0.0"/>
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="30" maxY="0.0"/>
<inset key="sectionInset" minX="60" minY="0.0" maxX="60" maxY="0.0"/>
</collectionViewFlowLayout>
<cells>
<collectionViewCell opaque="NO" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="ReplyCell" id="gxq-A8-Ahf" customClass="ReplyCell" customModule="BilibiliLive" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="582" height="360"/>
<rect key="frame" x="60" y="0.0" width="582" height="360"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<collectionViewCellContentView key="contentView" opaque="NO" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" id="91g-YW-NBL">
<rect key="frame" x="0.0" y="0.0" width="582" height="360"/>
Expand Down Expand Up @@ -801,6 +801,7 @@
<outlet property="playButton" destination="lfB-VX-ver" id="9XU-MT-KOf"/>
<outlet property="playCountLabel" destination="ahl-Fa-Qpg" id="q6V-be-wNj"/>
<outlet property="recommandCollectionView" destination="nw1-cq-9yk" id="w8m-bc-mWQ"/>
<outlet property="repliesCollectionViewHeightConstraints" destination="dCt-K6-G5Q" id="ZfP-oq-I5s"/>
<outlet property="replysCollectionView" destination="zj0-CY-pLt" id="8h4-LO-bUs"/>
<outlet property="scrollView" destination="Dm8-CL-kxU" id="R6I-to-71J"/>
<outlet property="titleLabel" destination="kwE-Zo-p5T" id="3Fx-I9-hrS"/>
Expand Down Expand Up @@ -936,7 +937,7 @@
<color red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<systemColor name="secondaryLabelColor">
<color red="0.0" green="0.0" blue="0.0" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
<color white="0.0" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>
111 changes: 111 additions & 0 deletions BilibiliLive/Component/Video/ReplyDetailViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
//
// Created by Yam on 2024/6/9.
//

import UIKit

class ReplyDetailViewController: UIViewController {
private var titleLabel: UILabel!
private var replyLabel: UILabel!
private var replyCollectionView: UICollectionView!

var reply: Replys.Reply

init(reply: Replys.Reply) {
self.reply = reply
super.init(nibName: nil, bundle: nil)
}

@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

override func viewDidLoad() {
super.viewDidLoad()

setUpViews()
replyLabel.text = reply.content.message
}

// MARK: - Private

private func setUpViews() {
titleLabel = {
let label = UILabel()
self.view.addSubview(label)
label.font = .boldSystemFont(ofSize: 60)
label.text = "评论"

label.snp.makeConstraints { make in
make.centerX.equalToSuperview()
make.top.equalTo(view.safeAreaLayoutGuide)
}

return label
}()

replyLabel = {
let label = UILabel()
self.view.addSubview(label)
label.numberOfLines = 0
label.font = .preferredFont(forTextStyle: .headline)

label.snp.makeConstraints { make in
make.top.equalTo(self.titleLabel.snp.bottom).offset(60)
make.leading.equalTo(self.view.snp.leadingMargin)
make.trailing.equalTo(self.view.snp.trailingMargin)
}

return label
}()

replyCollectionView = {
let flowLayout = UICollectionViewFlowLayout()
flowLayout.itemSize = CGSize(width: 582, height: 360)
flowLayout.sectionInset = .init(top: 0, left: 60, bottom: 0, right: 60)
flowLayout.minimumLineSpacing = 10
flowLayout.minimumInteritemSpacing = 10

let collectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout)
self.view.addSubview(collectionView)
collectionView.dataSource = self
collectionView.delegate = self
collectionView.register(UINib(nibName: ReplyCell.identifier, bundle: nil), forCellWithReuseIdentifier: ReplyCell.identifier)

collectionView.snp.makeConstraints { make in
make.leading.trailing.equalToSuperview()
make.top.equalTo(self.replyLabel.snp.bottom).offset(60)
make.bottom.equalToSuperview()
}

return collectionView
}()
}
}

extension ReplyDetailViewController: UICollectionViewDataSource, UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return reply.replies?.count ?? 0
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ReplyCell.identifier, for: indexPath) as? ReplyCell else {
fatalError("cell not found")
}

guard let reply = reply.replies?[indexPath.row] else {
fatalError("reply not found")
}

cell.config(replay: reply)

return cell
}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let reply = reply.replies?[indexPath.item] else { return }
let detail = ReplyDetailViewController(reply: reply)
present(detail, animated: true)
}
}
23 changes: 10 additions & 13 deletions BilibiliLive/Component/Video/VideoDetailViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
//

import AVKit
import Combine
import Foundation
import UIKit

Expand Down Expand Up @@ -43,6 +44,7 @@ class VideoDetailViewController: UIViewController {
@IBOutlet var pageCollectionView: UICollectionView!
@IBOutlet var recommandCollectionView: UICollectionView!
@IBOutlet var replysCollectionView: UICollectionView!
@IBOutlet var repliesCollectionViewHeightConstraints: NSLayoutConstraint!
@IBOutlet var ugcCollectionView: UICollectionView!

@IBOutlet var pageView: UIView!
Expand Down Expand Up @@ -71,6 +73,8 @@ class VideoDetailViewController: UIViewController {

private var allUgcEpisodes = [VideoDetail.Info.UgcSeason.UgcVideoInfo]()

private var subscriptions = [AnyCancellable]()

static func create(aid: Int, cid: Int?, epid: Int? = nil) -> VideoDetailViewController {
let vc = UIStoryboard(name: "Main", bundle: .main).instantiateViewController(identifier: String(describing: self)) as! VideoDetailViewController
vc.aid = aid
Expand Down Expand Up @@ -126,6 +130,11 @@ class VideoDetailViewController: UIViewController {
focusGuide.bottomAnchor.constraint(equalTo: actionButtonSpaceView.bottomAnchor),
])
focusGuide.preferredFocusEnvironments = [dislikeButton]

replysCollectionView.publisher(for: \.contentSize).sink { [weak self] newSize in
self?.repliesCollectionViewHeightConstraints.constant = newSize.height
self?.view.setNeedsLayout()
}.store(in: &subscriptions)
}

override var preferredFocusedView: UIView? {
Expand Down Expand Up @@ -456,7 +465,7 @@ extension VideoDetailViewController: UICollectionViewDelegate {
present(player, animated: true, completion: nil)
case replysCollectionView:
guard let reply = replys?.replies?[indexPath.item] else { return }
let detail = ContentDetailViewController.createReply(content: reply.content.message)
let detail = ReplyDetailViewController(reply: reply)
present(detail, animated: true)
case ugcCollectionView:
let video = allUgcEpisodes[indexPath.item]
Expand Down Expand Up @@ -576,18 +585,6 @@ extension VideoDetailViewController {
}
}

class ReplyCell: UICollectionViewCell {
@IBOutlet var avatarImageView: UIImageView!
@IBOutlet var userNameLabel: UILabel!
@IBOutlet var contenLabel: UILabel!

func config(replay: Replys.Reply) {
avatarImageView.kf.setImage(with: URL(string: replay.member.avatar), options: [.processor(DownsamplingImageProcessor(size: CGSize(width: 80, height: 80))), .processor(RoundCornerImageProcessor(radius: .widthFraction(0.5))), .cacheSerializer(FormatIndicatedCacheSerializer.png)])
userNameLabel.text = replay.member.uname
contenLabel.text = replay.content.message
}
}

class RelatedVideoCell: BLMotionCollectionViewCell {
let titleLabel = MarqueeLabel()
let imageView = UIImageView()
Expand Down
Loading
Loading