@@ -26,6 +26,7 @@ public struct PostDisplayView: View {
2626 @State private var displayedScore : Int
2727 @State private var displayedUpvoted : Bool
2828 @State private var displayedBookmarked : Bool
29+ @State private var displayedVoteLinks : VoteLinks ?
2930
3031 public init (
3132 post: Post ,
@@ -50,6 +51,7 @@ public struct PostDisplayView: View {
5051 _displayedScore = State ( initialValue: post. score)
5152 _displayedUpvoted = State ( initialValue: post. upvoted)
5253 _displayedBookmarked = State ( initialValue: post. isBookmarked)
54+ _displayedVoteLinks = State ( initialValue: post. voteLinks)
5355 }
5456
5557 public var body : some View {
@@ -101,6 +103,7 @@ public struct PostDisplayView: View {
101103 displayedScore = post. score
102104 displayedUpvoted = post. upvoted
103105 displayedBookmarked = post. isBookmarked
106+ displayedVoteLinks = post. voteLinks
104107 }
105108 . onChange ( of: post. score) { newValue in
106109 displayedScore = newValue
@@ -111,6 +114,9 @@ public struct PostDisplayView: View {
111114 . onChange ( of: post. isBookmarked) { newValue in
112115 displayedBookmarked = newValue
113116 }
117+ . onChange ( of: post. voteLinks) { newValue in
118+ displayedVoteLinks = newValue
119+ }
114120 . onChange ( of: votingState? . score) { newValue in
115121 if let newValue {
116122 displayedScore = newValue
@@ -127,8 +133,9 @@ public struct PostDisplayView: View {
127133 let score = displayedScore
128134 let isUpvoted = displayedUpvoted
129135 let isLoading = isSubmittingUpvote
130- let canVote = post. voteLinks? . upvote != nil
131- let canUnvote = post. voteLinks? . unvote != nil
136+ let currentVoteLinks = displayedVoteLinks ?? post. voteLinks
137+ let canVote = currentVoteLinks? . upvote != nil
138+ let canUnvote = currentVoteLinks? . unvote != nil
132139 let canInteract = ( ( canVote && !isUpvoted) || ( canUnvote && isUpvoted) ) && !isLoading
133140 // Avoid keeping a disabled Button so the upvoted state retains the bright tint
134141 let ( backgroundColor, textColor) : ( Color , Color ) = {
@@ -217,22 +224,26 @@ public struct PostDisplayView: View {
217224 guard !isSubmittingUpvote else { return }
218225
219226 let isCurrentlyUpvoted = displayedUpvoted
220- let canUnvote = post. voteLinks? . unvote != nil
227+ let currentVoteLinks = displayedVoteLinks ?? post. voteLinks
228+ let canUnvote = currentVoteLinks? . unvote != nil
221229
222230 // If already upvoted and can unvote, perform unvote
223231 if isCurrentlyUpvoted && canUnvote {
224232 guard let onUnvoteTap else { return }
225233 isSubmittingUpvote = true
226234 let previousScore = displayedScore
227235 let previousUpvoted = displayedUpvoted
236+ let previousVoteLinks = currentVoteLinks
228237 displayedUpvoted = false
229238 displayedScore -= 1
239+ displayedVoteLinks = VoteLinks ( upvote: previousVoteLinks? . upvote, unvote: nil )
230240 Task {
231241 let success = await onUnvoteTap ( )
232242 await MainActor . run {
233243 if !success {
234244 displayedScore = previousScore
235245 displayedUpvoted = previousUpvoted
246+ displayedVoteLinks = previousVoteLinks
236247 }
237248 isSubmittingUpvote = false
238249 }
@@ -243,14 +254,17 @@ public struct PostDisplayView: View {
243254 isSubmittingUpvote = true
244255 let previousScore = displayedScore
245256 let previousUpvoted = displayedUpvoted
257+ let previousVoteLinks = currentVoteLinks
246258 displayedUpvoted = true
247259 displayedScore += 1
260+ displayedVoteLinks = derivedVoteLinks ( afterUpvoteFrom: previousVoteLinks)
248261 Task {
249262 let success = await onUpvoteTap ( )
250263 await MainActor . run {
251264 if !success {
252265 displayedScore = previousScore
253266 displayedUpvoted = previousUpvoted
267+ displayedVoteLinks = previousVoteLinks
254268 }
255269 isSubmittingUpvote = false
256270 }
@@ -259,6 +273,28 @@ public struct PostDisplayView: View {
259273 }
260274 }
261275
276+ private func derivedVoteLinks( afterUpvoteFrom voteLinks: VoteLinks ? ) -> VoteLinks ? {
277+ guard let voteLinks else { return nil }
278+ if voteLinks. unvote != nil {
279+ return voteLinks
280+ }
281+ guard let upvoteURL = voteLinks. upvote else {
282+ return voteLinks
283+ }
284+ let absolute = upvoteURL. absoluteString
285+ if absolute. contains ( " how=up " ) ,
286+ let unvoteURL = URL ( string: absolute. replacingOccurrences ( of: " how=up " , with: " how=un " ) )
287+ {
288+ return VoteLinks ( upvote: upvoteURL, unvote: unvoteURL)
289+ }
290+ if absolute. contains ( " how%3Dup " ) ,
291+ let unvoteURL = URL ( string: absolute. replacingOccurrences ( of: " how%3Dup " , with: " how%3Dun " ) )
292+ {
293+ return VoteLinks ( upvote: upvoteURL, unvote: unvoteURL)
294+ }
295+ return voteLinks
296+ }
297+
262298 private func makeBookmarkAction( ) -> ( ( ) -> Void ) ? {
263299 guard let onBookmarkTap else { return nil }
264300 return {
0 commit comments