From 037698a8905b2881b3c8e15007455d53b668363e Mon Sep 17 00:00:00 2001 From: Mark Chan <45706356+WindowsMEMZ@users.noreply.github.com> Date: Mon, 12 Feb 2024 17:16:25 +0800 Subject: [PATCH] Updated live on iOS (#214) --- DarockBili.xcodeproj/project.pbxproj | 38 +-- Localizable.xcstrings | 14 +- MeowBili/Live/LiveDetailView.swift | 242 ++++++------------- MeowBili/Live/LivePlayerView.swift | 17 +- MeowBili/MeowBili.entitlements | 10 + MeowBili/PersonalCenter/UserDetailView.swift | 11 +- MeowBili/Video/VideoDetailView.swift | 16 +- MeowBili/Video/VideoPlayerView.swift | 3 +- 8 files changed, 143 insertions(+), 208 deletions(-) create mode 100644 MeowBili/MeowBili.entitlements diff --git a/DarockBili.xcodeproj/project.pbxproj b/DarockBili.xcodeproj/project.pbxproj index 39aa13047..b878032f2 100644 --- a/DarockBili.xcodeproj/project.pbxproj +++ b/DarockBili.xcodeproj/project.pbxproj @@ -275,6 +275,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 8C0557E02B7A0480009D9CD0 /* MeowBili.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = MeowBili.entitlements; sourceTree = ""; }; 8C372ED62B6CF08D002033A1 /* LiveMessagesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LiveMessagesView.swift; sourceTree = ""; }; 8C72E32A2B6605B80087486E /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 8C72E32D2B6607240087486E /* DownloadObj.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadObj.swift; sourceTree = ""; }; @@ -504,6 +505,7 @@ 8CA7CBC12B77AC4A008E587F /* MeowBili */ = { isa = PBXGroup; children = ( + 8C0557E02B7A0480009D9CD0 /* MeowBili.entitlements */, 8CA7CC632B77AD5B008E587F /* Info.plist */, 8CA7CC752B77AF4B008E587F /* MeowBili-Bridging-Header.h */, 8CA7CBC22B77AC4A008E587F /* MeowBiliApp.swift */, @@ -1366,8 +1368,9 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = MeowBili/MeowBili.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 440; + CURRENT_PROJECT_VERSION = 445; DEVELOPMENT_ASSET_PATHS = "\"MeowBili/Preview Content\""; DEVELOPMENT_TEAM = B57D8PP775; ENABLE_PREVIEWS = YES; @@ -1386,19 +1389,20 @@ "$(inherited)", "@executable_path/Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 13.0; MARKETING_VERSION = 1.0.0; PRODUCT_BUNDLE_IDENTIFIER = com.darock.DarockBili; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; - SUPPORTS_MACCATALYST = NO; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = YES; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; - SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; + SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OBJC_BRIDGING_HEADER = "MeowBili/MeowBili-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2,7"; + TARGETED_DEVICE_FAMILY = "1,2,6"; }; name = Debug; }; @@ -1409,8 +1413,9 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = MeowBili/MeowBili.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 440; + CURRENT_PROJECT_VERSION = 445; DEVELOPMENT_ASSET_PATHS = "\"MeowBili/Preview Content\""; DEVELOPMENT_TEAM = B57D8PP775; ENABLE_PREVIEWS = YES; @@ -1429,18 +1434,19 @@ "$(inherited)", "@executable_path/Frameworks", ); + MACOSX_DEPLOYMENT_TARGET = 13.0; MARKETING_VERSION = 1.0.0; PRODUCT_BUNDLE_IDENTIFIER = com.darock.DarockBili; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = "iphoneos iphonesimulator macosx xros xrsimulator"; - SUPPORTS_MACCATALYST = NO; + SUPPORTED_PLATFORMS = "iphoneos iphonesimulator"; + SUPPORTS_MACCATALYST = YES; SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO; - SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO; + SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OBJC_BRIDGING_HEADER = "MeowBili/MeowBili-Bridging-Header.h"; SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2,7"; + TARGETED_DEVICE_FAMILY = "1,2,6"; VALIDATE_PRODUCT = YES; }; name = Release; @@ -1451,7 +1457,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 440; + CURRENT_PROJECT_VERSION = 445; DEVELOPMENT_ASSET_PATHS = "\"DarockBili Watch App/Preview Content\""; DEVELOPMENT_TEAM = B57D8PP775; ENABLE_PREVIEWS = YES; @@ -1483,7 +1489,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 440; + CURRENT_PROJECT_VERSION = 445; DEVELOPMENT_ASSET_PATHS = "\"DarockBili Watch App/Preview Content\""; DEVELOPMENT_TEAM = B57D8PP775; ENABLE_PREVIEWS = YES; @@ -1636,7 +1642,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 440; + CURRENT_PROJECT_VERSION = 445; DEVELOPMENT_ASSET_PATHS = "\"DarockBili Watch App/Preview Content\""; DEVELOPMENT_TEAM = B57D8PP775; ENABLE_PREVIEWS = YES; @@ -1668,7 +1674,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 440; + CURRENT_PROJECT_VERSION = 445; DEVELOPMENT_ASSET_PATHS = "\"DarockBili Watch App/Preview Content\""; DEVELOPMENT_TEAM = B57D8PP775; ENABLE_PREVIEWS = YES; @@ -1700,7 +1706,7 @@ buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 440; + CURRENT_PROJECT_VERSION = 445; DEVELOPMENT_TEAM = B57D8PP775; INFOPLIST_KEY_CFBundleDisplayName = DarockBili; MARKETING_VERSION = 1.0.0; @@ -1716,7 +1722,7 @@ buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 440; + CURRENT_PROJECT_VERSION = 445; DEVELOPMENT_TEAM = B57D8PP775; INFOPLIST_KEY_CFBundleDisplayName = DarockBili; MARKETING_VERSION = 1.0.0; diff --git a/Localizable.xcstrings b/Localizable.xcstrings index 5e3de4544..d1e57545f 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -4458,6 +4458,9 @@ } } } + }, + "Video.details.danmaku.%@" : { + }, "Video.details.danmaku.%lld" : { "localizations" : { @@ -4502,6 +4505,9 @@ } } } + }, + "Video.details.watches.%@" : { + }, "Video.details.watches.%lld" : { "localizations" : { @@ -4530,6 +4536,9 @@ } } } + }, + "Video.details.watching-people.%@" : { + }, "Video.details.watching-people.%lld" : { "localizations" : { @@ -4574,6 +4583,9 @@ } } } + }, + "Video.fans.%@" : { + }, "Video.fans.%lld" : { "localizations" : { @@ -4866,4 +4878,4 @@ } }, "version" : "1.0" -} +} \ No newline at end of file diff --git a/MeowBili/Live/LiveDetailView.swift b/MeowBili/Live/LiveDetailView.swift index 33d5b9ed6..89884a656 100644 --- a/MeowBili/Live/LiveDetailView.swift +++ b/MeowBili/Live/LiveDetailView.swift @@ -40,153 +40,36 @@ struct LiveDetailView: View { @State var streamerFaceUrl = "" @State var streamerFansCount = 0 @State var tagName = "" - @State var isLoading = false @State var backgroundPicOpacity = 0.0 - @State var isLivePlayerPresented = false + @State var isDecoded = false var body: some View { - ZStack { - Group { - ScrollView { - FirstPageBase(liveDetails: liveDetails, streamerName: $streamerName, isLoading: $isLoading, isLivePlayerPresented: $isLivePlayerPresented) - SecondPageBase(liveDetails: liveDetails, watchingCount: $watchingCount, description: $description, liveStatus: $liveStatus, startTime: $startTime, streamerId: $streamerId, streamerName: $streamerName, streamerFaceUrl: $streamerFaceUrl, streamerFansCount: $streamerFansCount, tagName: $tagName) - } - } - .blur(radius: isLoading ? 14 : 0) - if isLoading { - Text("Video.analyzing") - .font(.title2) - .bold() + VStack { + if isDecoded { + LivePlayerView() + .frame(height: 240) + } else { + Rectangle() + .frame(height: 240) + .redacted(reason: .placeholder) } - } - .navigationTitle("Live") - .navigationBarTitleDisplayMode(.inline) - .sheet(isPresented: $isLivePlayerPresented, content: {LivePlayerView()}) - .onAppear { - let headers: HTTPHeaders = [ - "cookie": "SESSDATA=\(sessdata)", - "User-Agent": "Mozilla/5.0 (X11; CrOS x86_64 14541.0.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" - ] - DarockKit.Network.shared.requestJSON("https://api.live.bilibili.com/room/v1/Room/get_info?room_id=\(liveDetails["ID"]!)") { respJson, isSuccess in - if isSuccess { - watchingCount = respJson["data"]["online"].int ?? 0 - description = respJson["data"]["description"].string ?? "[加载失败]" - liveStatus = LiveRoomStatus(rawValue: respJson["data"]["live_status"].int ?? 0) ?? .notStart - startTime = respJson["data"]["live_time"].string ?? "0000-00-00 00:00:00" - tagName = respJson["data"]["tags"].string ?? "[加载失败]" - if let upUid = respJson["data"]["uid"].int64 { - streamerId = upUid - biliWbiSign(paramEncoded: "mid=\(upUid)".base64Encoded()) { signed in - if let signed { - debugPrint(signed) - autoRetryRequestApi("https://api.bilibili.com/x/space/wbi/acc/info?\(signed)", headers: headers) { respJson, isSuccess in - if isSuccess { - if !CheckBApiError(from: respJson) { return } - streamerFaceUrl = respJson["data"]["face"].string ?? "E" - streamerName = respJson["data"]["name"].string ?? "[加载失败]" - DarockKit.Network.shared.requestJSON("https://api.bilibili.com/x/relation/stat?vmid=\(upUid)", headers: headers) { respJson, isSuccess in - if isSuccess { - streamerFansCount = respJson["data"]["follower"].int ?? -1 - } - } - } - } - } + ScrollView { + VStack { + Spacer() + Marquee { + HStack { + Text(liveDetails["Title"]!) + .lineLimit(1) + .font(.system(size: 18, weight: .bold)) + .multilineTextAlignment(.center) } } - } - } - } - } - - struct FirstPageBase: View { - var liveDetails: [String: String] - @Binding var streamerName: String - @Binding var isLoading: Bool - @Binding var isLivePlayerPresented: Bool - @State var isCoverImageViewPresented = false - var body: some View { - VStack { - Spacer() - WebImage(url: URL(string: liveDetails["Cover"]! + "@240w_160h")!, options: [.progressiveLoad, .scaleDownLargeImages]) - .placeholder { - RoundedRectangle(cornerRadius: 14) - .frame(width: 120, height: 80) - .foregroundColor(Color(hex: 0x3D3D3D)) - .redacted(reason: .placeholder) - } - .resizable() - .scaledToFit() - .frame(width: 120, height: 80) - .cornerRadius(14) - .shadow(color: .black.opacity(0.5), radius: 5, x: 1, y: 2) - .offset(y: 8) - .sheet(isPresented: $isCoverImageViewPresented, content: {ImageViewerView(url: liveDetails["Cover"]!)}) - .onTapGesture { - isCoverImageViewPresented = true - } - Spacer() + .marqueeWhenNotFit(true) + .marqueeDuration(10) + .marqueeIdleAlignment(.center) .frame(height: 20) - Marquee { - HStack { - Text(liveDetails["Title"]!) - .lineLimit(1) - .font(.system(size: 12, weight: .bold)) - .multilineTextAlignment(.center) - } - } - .marqueeWhenNotFit(true) - .marqueeDuration(10) - .marqueeIdleAlignment(.center) - .frame(height: 20) - .padding(.horizontal, 10) - Text(streamerName) - .lineLimit(1) - .font(.system(size: 12)) - .padding(.horizontal, 40) - .padding(.vertical, 0) - .opacity(0.65) - Spacer() - .frame(height: 20) - if #unavailable(watchOS 10) { - Button(action: { - isLoading = true - - DarockKit.Network.shared.requestJSON("https://api.live.bilibili.com/room/v1/Room/playUrl?cid=\(liveDetails["ID"]!)&qn=150&platform=h5") { respJson, isSuccess in - if isSuccess { - debugPrint(respJson) - LiveDetailView.willPlayStreamUrl = respJson["data"]["durl"][0]["url"].string ?? "" - debugPrint(LiveDetailView.willPlayStreamUrl) - isLivePlayerPresented = true - isLoading = false - } - } - }, label: { - Label("Video.play", systemImage: "play.fill") - }) - } - } - } - } - - struct SecondPageBase: View { - var liveDetails: [String: String] - @Binding var watchingCount: Int - @Binding var description: String - @Binding var liveStatus: LiveRoomStatus - @Binding var startTime: String - @Binding var streamerId: Int64 - @Binding var streamerName: String - @Binding var streamerFaceUrl: String - @Binding var streamerFansCount: Int - @Binding var tagName: String - @State var ownerBlockOffset: CGFloat = 20 - @State var nowWatchingCountOffset: CGFloat = 20 - @State var publishTimeTextOffset: CGFloat = 20 - @State var liveIdTextOffset: CGFloat = 20 - @State var descOffset: CGFloat = 20 - var body: some View { - ScrollView { - VStack { + .padding(.horizontal, 10) + Spacer() + .frame(height: 20) if streamerId != 0 { NavigationLink(destination: {UserDetailView(uid: String(streamerId))}, label: { HStack { @@ -202,7 +85,7 @@ struct LiveDetailView: View { Spacer() } HStack { - Text("Video.fans.\(Int(String(streamerFansCount).shorter()) ?? 0)") + Text("Video.fans.\(String(streamerFansCount).shorter())") .font(.system(size: 11)) .lineLimit(1) .opacity(0.6) @@ -213,11 +96,6 @@ struct LiveDetailView: View { } }) .buttonBorderShape(.roundedRectangle(radius: 18)) - .offset(y: ownerBlockOffset) - .animation(.easeOut(duration: 0.3), value: ownerBlockOffset) - .onAppear { - ownerBlockOffset = 0 - } } LazyVStack { Spacer() @@ -225,35 +103,20 @@ struct LiveDetailView: View { VStack { HStack { Image(systemName: "person.2") - Text("Video.details.watching-people.\(Int(watchingCount) ?? 0)") + Text("Video.details.watching-people.\(watchingCount)") .offset(x: -1) Spacer() } - .offset(x: -2, y: nowWatchingCountOffset) - .animation(.easeOut(duration: 0.55), value: nowWatchingCountOffset) - .onAppear { - nowWatchingCountOffset = 0 - } HStack { Image(systemName: "clock") Text("Live.starting.\(startTime)") Spacer() } - .offset(y: publishTimeTextOffset) - .animation(.easeOut(duration: 0.65), value: publishTimeTextOffset) - .onAppear { - publishTimeTextOffset = 0 - } HStack { Image(systemName: "movieclapper") Text(liveDetails["ID"]!) Spacer() } - .offset(x: -1, y: liveIdTextOffset) - .animation(.easeOut(duration: 0.75), value: liveIdTextOffset) - .onAppear { - liveIdTextOffset = 0 - } } .font(.system(size: 11)) .opacity(0.6) @@ -271,11 +134,6 @@ struct LiveDetailView: View { .font(.system(size: 12)) .opacity(0.65) .padding(.horizontal, 8) - .offset(y: descOffset) - .animation(.easeOut(duration: 0.4), value: descOffset) - .onAppear { - descOffset = 0 - } HStack { VStack { Image(systemName: "tag") @@ -287,12 +145,56 @@ struct LiveDetailView: View { .font(.system(size: 12)) .opacity(0.65) .padding(.horizontal, 8) - .offset(y: descOffset) - .animation(.easeOut(duration: 0.4), value: descOffset) } } } } + .navigationTitle("Live") + .navigationBarTitleDisplayMode(.inline) + .onAppear { + let headers: HTTPHeaders = [ + "cookie": "SESSDATA=\(sessdata)", + "User-Agent": "Mozilla/5.0 (X11; CrOS x86_64 14541.0.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" + ] + DarockKit.Network.shared.requestJSON("https://api.live.bilibili.com/room/v1/Room/get_info?room_id=\(liveDetails["ID"]!)") { respJson, isSuccess in + if isSuccess { + watchingCount = respJson["data"]["online"].int ?? 0 + description = respJson["data"]["description"].string ?? "[加载失败]" + liveStatus = LiveRoomStatus(rawValue: respJson["data"]["live_status"].int ?? 0) ?? .notStart + startTime = respJson["data"]["live_time"].string ?? "0000-00-00 00:00:00" + tagName = respJson["data"]["tags"].string ?? "[加载失败]" + if let upUid = respJson["data"]["uid"].int64 { + streamerId = upUid + biliWbiSign(paramEncoded: "mid=\(upUid)".base64Encoded()) { signed in + if let signed { + debugPrint(signed) + autoRetryRequestApi("https://api.bilibili.com/x/space/wbi/acc/info?\(signed)", headers: headers) { respJson, isSuccess in + if isSuccess { + if !CheckBApiError(from: respJson) { return } + streamerFaceUrl = respJson["data"]["face"].string ?? "E" + streamerName = respJson["data"]["name"].string ?? "[加载失败]" + DarockKit.Network.shared.requestJSON("https://api.bilibili.com/x/relation/stat?vmid=\(upUid)", headers: headers) { respJson, isSuccess in + if isSuccess { + streamerFansCount = respJson["data"]["follower"].int ?? -1 + } + } + } + } + } + } + } + } + } + + DarockKit.Network.shared.requestJSON("https://api.live.bilibili.com/room/v1/Room/playUrl?cid=\(liveDetails["ID"]!)&qn=150&platform=h5") { respJson, isSuccess in + if isSuccess { + debugPrint(respJson) + LiveDetailView.willPlayStreamUrl = respJson["data"]["durl"][0]["url"].string ?? "" + debugPrint(LiveDetailView.willPlayStreamUrl) + isDecoded = true + } + } + } } } diff --git a/MeowBili/Live/LivePlayerView.swift b/MeowBili/Live/LivePlayerView.swift index 294dcc7ec..7fb7997d6 100644 --- a/MeowBili/Live/LivePlayerView.swift +++ b/MeowBili/Live/LivePlayerView.swift @@ -27,15 +27,12 @@ struct LivePlayerView: View { @State var livePlayer: AVPlayer? = nil @State var tabviewChoseTab = 2 var body: some View { - TabView(selection: $tabviewChoseTab) { - VideoPlayer(player: livePlayer) - .ignoresSafeArea() - .tag(2) - } - .onAppear { - let asset = AVURLAsset(url: URL(string: LiveDetailView.willPlayStreamUrl)!, options: ["AVURLAssetHTTPHeaderFieldsKey": ["User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15", "Referer": "https://www.bilibili.com"]]) - let item = AVPlayerItem(asset: asset) - livePlayer = AVPlayer(playerItem: item) - } + VideoPlayer(player: livePlayer) + .onAppear { + let asset = AVURLAsset(url: URL(string: LiveDetailView.willPlayStreamUrl)!, options: ["AVURLAssetHTTPHeaderFieldsKey": ["User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15", "Referer": "https://www.bilibili.com"]]) + let item = AVPlayerItem(asset: asset) + livePlayer = AVPlayer(playerItem: item) + livePlayer?.play() + } } } diff --git a/MeowBili/MeowBili.entitlements b/MeowBili/MeowBili.entitlements new file mode 100644 index 000000000..ee95ab7e5 --- /dev/null +++ b/MeowBili/MeowBili.entitlements @@ -0,0 +1,10 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.network.client + + + diff --git a/MeowBili/PersonalCenter/UserDetailView.swift b/MeowBili/PersonalCenter/UserDetailView.swift index fce9b772a..37d88f899 100644 --- a/MeowBili/PersonalCenter/UserDetailView.swift +++ b/MeowBili/PersonalCenter/UserDetailView.swift @@ -54,7 +54,7 @@ struct UserDetailView: View { FirstPageBase(uid: uid, userFaceUrl: $userFaceUrl, username: $username, followCount: $followCount, fansCount: $fansCount, coinCount: $coinCount, isFollowed: $isFollowed) .offset(y: -10) .navigationTitle(username) - SecondPageBase(officialType: $officialType, officialTitle: $officialTitle, userSign: $userSign, userLevel: $userLevel, vipLabel: $vipLabel) + SecondPageBase(uid: uid, officialType: $officialType, officialTitle: $officialTitle, userSign: $userSign, userLevel: $userLevel, vipLabel: $vipLabel) } .tag(1) .tabItem { @@ -227,6 +227,7 @@ struct UserDetailView: View { } } struct SecondPageBase: View { + var uid: String @Binding var officialType: Int @Binding var officialTitle: String @Binding var userSign: String @@ -241,6 +242,14 @@ struct UserDetailView: View { Color(red: 234/255, green: 51/255, blue: 35/255)] //6 var body: some View { VStack { + HStack { + Image(systemName: "person.text.rectangle") + .foregroundColor(.secondary) + .frame(width: 20, height: 20) + Text(uid) + .font(.system(size: 15)) + Spacer() + } if officialType != -1 { HStack { Image(systemName: "bolt.circle") diff --git a/MeowBili/Video/VideoDetailView.swift b/MeowBili/Video/VideoDetailView.swift index d60be8907..a74c346c4 100644 --- a/MeowBili/Video/VideoDetailView.swift +++ b/MeowBili/Video/VideoDetailView.swift @@ -51,7 +51,7 @@ struct VideoDetailView: View { @State var honors = [String]() @State var tags = [String]() @State var subTitles = [[String: String]]() - @State var ownerFansCount = 0 + @State var ownerFansCount: Int64 = 0 @State var nowPlayingCount = "0" @State var publishTime = "" @State var videoDesc = "" @@ -221,7 +221,7 @@ struct VideoDetailView: View { Spacer() } HStack { - Text("Video.fans.\(Int(String(ownerFansCount).shorter()) ?? 0)") + Text("Video.fans.\(String(ownerFansCount).shorter())") .font(.system(size: 11)) .lineLimit(1) .foregroundColor(.gray) @@ -317,26 +317,26 @@ struct VideoDetailView: View { Spacer() .frame(height: 10) VStack { + // !!!: 不要为了本地化将此处字符串内插值进行类型转换 HStack { Image(systemName: "text.word.spacing") - Text("Video.details.danmaku.\(Int(videoDetails["Danmaku"]!.shorter()) ?? 0)") + Text("\(videoDetails["Danmaku"]!.shorter()) 弹幕") Spacer() } HStack { Image(systemName: "person.2") - Text("Video.details.watching-people.\(Int(nowPlayingCount) ?? 0)") - .offset(x: -1) + Text("\(nowPlayingCount) 人在看") Spacer() } HStack { Image(systemName: "play.circle") - Text("Video.details.watches.\(Int(videoDetails["View"]!.shorter()) ?? 0)") + Text("\(videoDetails["View"]!.shorter()) 播放") .offset(x: 1) Spacer() } HStack { Image(systemName: "clock") - Text("Video.details.publish-time.\(publishTime)") + Text("发布于 \(publishTime)") Spacer() } HStack { @@ -470,7 +470,7 @@ struct VideoDetailView: View { if let mid = respJson["data"]["owner"]["mid"].int { DarockKit.Network.shared.requestJSON("https://api.bilibili.com/x/relation/stat?vmid=\(mid)", headers: headers) { respJson, isSuccess in if isSuccess { - ownerFansCount = respJson["data"]["follower"].int ?? -1 + ownerFansCount = respJson["data"]["follower"].int64 ?? -1 } } } diff --git a/MeowBili/Video/VideoPlayerView.swift b/MeowBili/Video/VideoPlayerView.swift index b55d3c06b..7e82f2050 100644 --- a/MeowBili/Video/VideoPlayerView.swift +++ b/MeowBili/Video/VideoPlayerView.swift @@ -55,6 +55,7 @@ struct VideoPlayerView: View { let headers: HTTPHeaders = [ "cookie": "SESSDATA=\(sessdata)" ] + if isRecordHistory { AF.request("https://api.bilibili.com/x/click-interface/web/heartbeat", method: .post, parameters: ["bvid": VideoDetailView.willPlayVideoBV, "mid": dedeUserID, "type": 3, "dt": 2, "play_type": 2, "csrf": biliJct], headers: headers).response { response in debugPrint(response) @@ -74,7 +75,6 @@ struct VideoPlayerView: View { AF.request("https://api.bilibili.com/x/v1/dm/list.so?oid=\(VideoDetailView.willPlayVideoCID)").response { response in let danmakus = String(data: response.data!, encoding: .utf8)! - debugPrint(danmakus) if danmakus.contains("")[1].split(separator: "")[0] let danmakuSpd = danmakuOnly.split(separator: "") @@ -109,7 +109,6 @@ struct VideoPlayerView: View { removedCount++ } } - debugPrint(showDanmakus) } }