Skip to content

Commit

Permalink
ui: minor tweaks of topic list and details (#36)
Browse files Browse the repository at this point in the history
* ui: refine user view

* ui: extract reply button in topic details

* ui: refresh after a long background time

* ui: swipe floor to quote
  • Loading branch information
BugenZhao authored Oct 29, 2021
1 parent fbbd7a3 commit adb426c
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 26 deletions.
2 changes: 1 addition & 1 deletion app/Shared/Models/NotificationModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class NotificationModel: ObservableObject {
if self?.showing == true { self?.objectWillChange.send() }
} .store(in: &cancellables)

dataSource.$refreshedTimes
dataSource.$lastRefreshTime
.map { _ in self.dataSource.items.filter { n in n.read == false }.count }
.prepend(0)
.pairwise()
Expand Down
16 changes: 12 additions & 4 deletions app/Shared/Models/PagingDataSource.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class PagingDataSource<Res: SwiftProtobuf.Message, Item>: ObservableObject {
@Published var isLoading = false
@Published var isRefreshing = false
@Published var latestResponse: Res?
@Published var refreshedTimes = 0
@Published var lastRefreshTime: Date?
@Published var loadFromPage: Int?

private var loadedPage = 0
Expand All @@ -39,7 +39,7 @@ class PagingDataSource<Res: SwiftProtobuf.Message, Item>: ObservableObject {
var nextPage: Int? { hasMore ? loadedPage + 1 : nil }
var isInitialLoading: Bool { isLoading && loadedPage == 0 }
var firstLoadedPage: Int? { itemToIndexAndPage.values.map { $0.page }.min() }
var notLoaded: Bool { items.isEmpty && refreshedTimes == 0 }
var notLoaded: Bool { items.isEmpty && lastRefreshTime == nil }

init(
buildRequest: @escaping (_ page: Int) -> AsyncRequest.OneOf_Value,
Expand Down Expand Up @@ -150,7 +150,7 @@ class PagingDataSource<Res: SwiftProtobuf.Message, Item>: ObservableObject {

self.totalPages = newTotalPages ?? self.totalPages
self.loadedPage += 1
self.refreshedTimes += 1
self.lastRefreshTime = Date()
}

private func onRefreshError(e: LogicError, animated: Bool) {
Expand Down Expand Up @@ -261,7 +261,7 @@ class PagingDataSource<Res: SwiftProtobuf.Message, Item>: ObservableObject {


extension View {
func refreshable<Res, Item>(dataSource: PagingDataSource<Res, Item>, iOS15Only: Bool = false) -> some View {
func refreshable<Res, Item>(dataSource: PagingDataSource<Res, Item>, iOS15Only: Bool = false, refreshWhenEnterForeground: Bool = false) -> some View {
#if canImport(SwiftUIRefresh)
Group {
if #available(iOS 15.0, *) {
Expand All @@ -275,6 +275,14 @@ extension View {
} else {
self
}
} .onReceive(NotificationCenter.default.publisher(for: UIApplication.willEnterForegroundNotification)) { _ in
guard refreshWhenEnterForeground else { return }
guard let last = dataSource.lastRefreshTime else { return }

let elasped = Date().timeIntervalSince(last)
if elasped > 60 * 60 { // 1 hour elapsed
dataSource.refresh()
}
}
#else
self
Expand Down
15 changes: 14 additions & 1 deletion app/Shared/Views/PostRowView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ struct PostRowView: View {
}

var body: some View {
VStack(alignment: .leading, spacing: 10) {
let body = VStack(alignment: .leading, spacing: 10) {
header
content
footer
Expand All @@ -184,8 +184,21 @@ struct PostRowView: View {
#endif
.onAppear { self.post.attachments.map(\.url).forEach(attachments.add(_:)) }
.environmentObject(attachments)

if #available(iOS 15.0, *), let model = postReply {
body
.swipeActions(edge: .leading) { Button(action: { self.doQuote(model: model) }) { Image(systemName: "quote.bubble") } .tint(.accentColor) }
} else {
body
}
}

func onLongPress() {
if let model = postReply {
HapticUtils.play(style: .medium)
doQuote(model: model)
}
}

func doVote(_ operation: PostVoteRequest.Operation) {
logicCallAsync(.postVote(.with {
Expand Down
15 changes: 6 additions & 9 deletions app/Shared/Views/TopicDetailsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -159,12 +159,6 @@ struct TopicDetailsView: View {
@ViewBuilder
var moreMenu: some View {
Menu {
#if os(iOS)
Section {
replyButton
}
#endif

Section {
if enableAuthorOnly {
Button(action: { self.action.navigateToAuthorOnly = self.topic.authorID }) {
Expand Down Expand Up @@ -226,7 +220,10 @@ struct TopicDetailsView: View {
Label("See Full Topic", systemImage: "doc.richtext")
}
} else {
moreMenu
HStack {
replyButton
moreMenu
}
}
}

Expand Down Expand Up @@ -393,8 +390,8 @@ struct TopicDetailsView: View {
@ToolbarContentBuilder
var toolbar: some ToolbarContent {
#if os(iOS)
ToolbarItem(placement: .mayNavigationBarLeading) { loadFirstPageButton }
ToolbarItem(placement: .navigationBarTrailing) { progress }
ToolbarItem(placement: .navigationBarTrailing) { loadFirstPageButton }
ToolbarItem(placement: .navigationBarTrailing) { menu }
#elseif os(macOS)
ToolbarItemGroup {
Expand Down Expand Up @@ -427,7 +424,7 @@ struct TopicDetailsView: View {
}
} .mayGroupedListStyle()
.withTopicDetailsAction(action: action)
.onReceive(dataSource.$refreshedTimes) { _ in mayScrollToJumpFloor() }
.onReceive(dataSource.$lastRefreshTime) { _ in mayScrollToJumpFloor() }
.sheet(isPresented: $showJumpSelector) { TopicJumpSelectorView(maxFloor: maxFloor, initialFloor: floorToJump ?? 0, floorToJump: $floorToJump, pageToJump: $dataSource.loadFromPage) }
}

Expand Down
2 changes: 1 addition & 1 deletion app/Shared/Views/TopicListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ struct TopicListView: View {
}
}
}
.refreshable(dataSource: dataSource)
.refreshable(dataSource: dataSource, refreshWhenEnterForeground: true)
.mayGroupedListStyle()
}

Expand Down
23 changes: 13 additions & 10 deletions app/Shared/Views/UserView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@ struct UserView: View {

@ViewBuilder
var avatar: some View {
if let user = self.user, let action = self.action {
Button(action: { action.showUserProfile = user }) {
if style == .huge, let url = avatarURL {
Button(action: { viewingImage.show(url: url) }) {
avatarInner
} .buttonStyle(PlainButtonStyle())
} else if style == .huge, let url = avatarURL {
Button(action: { viewingImage.show(url: url) }) {
} else if let user = self.user, let action = self.action {
Button(action: { action.showUserProfile = user }) {
avatarInner
} .buttonStyle(PlainButtonStyle())
} else {
Expand Down Expand Up @@ -117,17 +117,20 @@ struct UserView: View {
Text("\(user?.postNum ?? 0)")
.redacted(if: badUser)
} .foregroundColor((1..<50 ~= user?.postNum ?? 50) ? .red : .secondary)
HStack(spacing: 2) {
Image(systemName: "calendar")
Text(Date(timeIntervalSince1970: TimeInterval(user?.regDate ?? 0)), style: .date)
.redacted(if: badUser)
}

HStack(spacing: 2) {
Image(systemName: "flag")
Text("\((user?.fame ?? 0) / 10)")
Text(String(format: "%.01f", Double(user?.fame ?? 0) / 10.0))
.redacted(if: badUser)
} .foregroundColor((user?.fame ?? 0 < 0) ? .red : .secondary)

if style == .huge {
HStack(spacing: 2) {
Image(systemName: "calendar")
Text(Date(timeIntervalSince1970: TimeInterval(user?.regDate ?? 0)), style: .date)
.redacted(if: badUser)
}
}
} .font(.footnote)
.foregroundColor(.secondary)
}
Expand Down

0 comments on commit adb426c

Please sign in to comment.