diff --git a/Model/CommentsModel.swift b/Model/CommentsModel.swift index 23922a9b..41b2c3b5 100644 --- a/Model/CommentsModel.swift +++ b/Model/CommentsModel.swift @@ -8,7 +8,8 @@ final class CommentsModel: ObservableObject { @Published var nextPage: String? @Published var firstPage = true - @Published var loaded = true + @Published var loading = false + @Published var loaded = false @Published var disabled = false @Published var replies = [Comment]() @@ -18,16 +19,16 @@ final class CommentsModel: ObservableObject { var accounts: AccountsModel! var player: PlayerModel! - var instance: Instance? { + static var instance: Instance? { InstancesModel.find(Defaults[.commentsInstanceID]) } var api: VideosAPI? { - instance.isNil ? nil : PipedAPI(account: instance!.anonymousAccount) + Self.instance.isNil ? nil : PipedAPI(account: Self.instance!.anonymousAccount) } static var enabled: Bool { - !Defaults[.commentsInstanceID].isNil && !Defaults[.commentsInstanceID]!.isEmpty + !instance.isNil } #if !os(tvOS) @@ -41,13 +42,15 @@ final class CommentsModel: ObservableObject { } func load(page: String? = nil) { - guard Self.enabled else { + guard Self.enabled, !loading else { return } reset() - guard !instance.isNil, + loading = true + + guard !Self.instance.isNil, !(player?.currentVideo.isNil ?? true) else { return @@ -65,6 +68,7 @@ final class CommentsModel: ObservableObject { } } .onCompletion { [weak self] _ in + self?.loading = false self?.loaded = true } } @@ -91,9 +95,10 @@ final class CommentsModel: ObservableObject { .onSuccess { [weak self] response in if let page: CommentsPage = response.typedContent() { self?.replies = page.comments + self?.repliesLoaded = true } } - .onCompletion { [weak self] _ in + .onFailure { [weak self] _ in self?.repliesLoaded = true } } @@ -104,6 +109,7 @@ final class CommentsModel: ObservableObject { firstPage = true nextPage = nil loaded = false + loading = false replies = [] repliesLoaded = false } diff --git a/Shared/Player/CommentView.swift b/Shared/Player/CommentView.swift index 377e9539..56982f95 100644 --- a/Shared/Player/CommentView.swift +++ b/Shared/Player/CommentView.swift @@ -1,65 +1,81 @@ import SDWebImageSwiftUI - import SwiftUI struct CommentView: View { let comment: Comment @Binding var repliesID: Comment.ID? + @State private var subscribed = false + #if os(iOS) @Environment(\.horizontalSizeClass) private var horizontalSizeClass #endif + + @Environment(\.colorScheme) private var colorScheme @Environment(\.navigationStyle) private var navigationStyle @EnvironmentObject private var comments @EnvironmentObject private var navigation @EnvironmentObject private var player @EnvironmentObject private var recents + @EnvironmentObject private var subscriptions var body: some View { VStack(alignment: .leading) { HStack(alignment: .center, spacing: 10) { - authorAvatar + HStack(spacing: 10) { + ZStack(alignment: .bottomTrailing) { + authorAvatar - #if os(iOS) - Group { - if horizontalSizeClass == .regular { - HStack(spacing: 20) { - authorAndTime - - Spacer() - - Group { - statusIcons - likes - } - } - } else { - HStack(alignment: .center, spacing: 20) { - authorAndTime - - Spacer() - - VStack(alignment: .trailing, spacing: 8) { - likes - statusIcons - } - } + if subscribed { + Image(systemName: "star.circle.fill") + #if os(tvOS) + .background(Color.background(scheme: colorScheme)) + #else + .background(Color.background) + #endif + .clipShape(Circle()) + .foregroundColor(.secondary) } } - .font(.system(size: 15)) + .onAppear { + subscribed = subscriptions.isSubscribing(comment.channel.id) + } - #else - HStack(spacing: 20) { - authorAndTime + authorAndTime + } + .contextMenu { + Button(action: openChannelAction) { + Label("\(comment.channel.name) Channel", systemImage: "rectangle.stack.fill.badge.person.crop") + } + } - Spacer() + Spacer() + Group { + #if os(iOS) + if horizontalSizeClass == .regular { + Group { + statusIcons + likes + } + } else { + VStack(alignment: .trailing, spacing: 8) { + likes + statusIcons + } + } + #else statusIcons likes - } - #endif + #endif + } } + #if os(tvOS) + .font(.system(size: 25).bold()) + #else + .font(.system(size: 15)) + #endif Group { commentText @@ -94,23 +110,25 @@ struct CommentView: View { .retryOnAppear(false) .indicator(.activity) .mask(RoundedRectangle(cornerRadius: 60)) - .frame(width: 45, height: 45, alignment: .leading) - .contextMenu { - Button(action: openChannelAction) { - Label("\(comment.channel.name) Channel", systemImage: "rectangle.stack.fill.badge.person.crop") - } - } #if os(tvOS) + .frame(width: 80, height: 80, alignment: .leading) .focusable() + #else + .frame(width: 45, height: 45, alignment: .leading) #endif } private var authorAndTime: some View { VStack(alignment: .leading) { Text(comment.author) - .fontWeight(.bold) + #if os(tvOS) + .font(.system(size: 30).bold()) + #else + .font(.system(size: 14).bold()) + #endif Text(comment.time) + .font(.caption2) .foregroundColor(.secondary) } .lineLimit(1) @@ -125,6 +143,9 @@ struct CommentView: View { Image(systemName: "heart.fill") } } + #if !os(tvOS) + .font(.system(size: 12)) + #endif .foregroundColor(.secondary) } @@ -135,6 +156,9 @@ struct CommentView: View { Image(systemName: "hand.thumbsup") Text("\(comment.likeCount.formattedAsAbbreviation())") } + #if !os(tvOS) + .font(.system(size: 12)) + #endif } } .foregroundColor(.secondary) @@ -163,6 +187,7 @@ struct CommentView: View { #if os(tvOS) .padding(.leading, 5) #else + .font(.system(size: 13)) .foregroundColor(.secondary) #endif } @@ -181,7 +206,7 @@ struct CommentView: View { #if os(macOS) 0.4 #else - 0.8 + 0.6 #endif } @@ -226,17 +251,13 @@ struct CommentView: View { } private func openChannelAction() { - player.presentingPlayer = false - DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { - let recent = RecentItem(from: comment.channel) - recents.add(recent) - navigation.presentingChannel = true - - if navigationStyle == .sidebar { - navigation.sidebarSectionChanged.toggle() - navigation.tabSelection = .recentlyOpened(recent.tag) - } - } + NavigationModel.openChannel( + comment.channel, + player: player, + recents: recents, + navigation: navigation, + navigationStyle: navigationStyle + ) } } @@ -247,5 +268,7 @@ struct CommentView_Previews: PreviewProvider { static var previews: some View { CommentView(comment: fixture, repliesID: .constant(fixture.id)) + .environmentObject(SubscriptionsModel()) + .padding(5) } } diff --git a/Shared/Player/CommentsView.swift b/Shared/Player/CommentsView.swift index ced2994f..0ddaaa95 100644 --- a/Shared/Player/CommentsView.swift +++ b/Shared/Player/CommentsView.swift @@ -16,6 +16,9 @@ struct CommentsView: View { .foregroundColor(.secondary) } else if !comments.loaded { progressView + .onAppear { + comments.load() + } } else { ScrollView(.vertical, showsIndicators: false) { VStack(alignment: .leading) { @@ -48,6 +51,7 @@ struct CommentsView: View { } } } + .font(.system(size: 13)) .buttonStyle(.plain) .padding(.vertical, 8) .foregroundColor(.secondary) @@ -56,11 +60,6 @@ struct CommentsView: View { } } .padding(.horizontal) - .onAppear { - if !comments.loaded { - comments.load() - } - } } private var progressView: some View { diff --git a/tvOS/NowPlayingView.swift b/tvOS/NowPlayingView.swift index 8c8e8673..26d0da2c 100644 --- a/tvOS/NowPlayingView.swift +++ b/tvOS/NowPlayingView.swift @@ -117,9 +117,18 @@ struct NowPlayingView: View { } if sections.contains(.comments) { - Section { - ForEach(comments.all) { comment in - CommentView(comment: comment, repliesID: $repliesID) + if !comments.loaded { + VStack(alignment: .center) { + progressView + .onAppear { + comments.load() + } + } + } else { + Section { + ForEach(comments.all) { comment in + CommentView(comment: comment, repliesID: $repliesID) + } } } } @@ -137,6 +146,19 @@ struct NowPlayingView: View { .font((inInfoViewController ? Font.system(size: 40) : .title3).bold()) .foregroundColor(.secondary) } + + private var progressView: some View { + VStack { + Spacer() + + HStack { + Spacer() + ProgressView() + Spacer() + } + Spacer() + } + } } struct NowPlayingView_Previews: PreviewProvider {