Skip to content

Commit 31a3dac

Browse files
authored
Merge pull request #396 from Planetable/improved-avatar-random-pick
Add simple scroll animation for avatar random pick.
2 parents 865bbcc + 2f241a8 commit 31a3dac

File tree

2 files changed

+66
-52
lines changed

2 files changed

+66
-52
lines changed

Diff for: Planet/Views/My/AvatarPickerView.swift

+65-51
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ struct AvatarPickerView: View {
3333
@State var avatars: [String: String]?
3434
@State var selectedAvatar: NSImage?
3535
@State var avatarChanged: Bool = false
36+
@State private var randomSelectedAvatarKey: String?
37+
@State private var highlightedItems: Set<String> = []
3638

3739
private func loadAvatars(category: AvatarCategory) -> [String: String]? {
3840
debugPrint("Loading Avatar category: \(category)")
@@ -74,21 +76,11 @@ struct AvatarPickerView: View {
7476
cornerRadius: 72,
7577
size: CGSize(width: 144, height: 144),
7678
uploadAction: { url in
77-
do {
78-
selectedAvatar = NSImage(contentsOf: url)
79-
avatarChanged = true
80-
}
81-
catch {
82-
debugPrint("failed to upload planet avatar: \(error)")
83-
}
79+
self.selectedAvatar = NSImage(contentsOf: url)
80+
self.avatarChanged = true
8481
},
8582
deleteAction: {
86-
do {
87-
selectedAvatar = nil
88-
}
89-
catch {
90-
debugPrint("failed to remove planet avatar: \(error)")
91-
}
83+
self.selectedAvatar = nil
9284
}
9385
)
9486
.padding(.bottom, 20)
@@ -98,53 +90,59 @@ struct AvatarPickerView: View {
9890

9991
VStack(spacing: 0) {
10092
if let avatars = avatars, let keys = Array(avatars.keys) as? [String] {
101-
ScrollView {
102-
LazyVGrid(
103-
columns: [GridItem(), GridItem(), GridItem()],
104-
alignment: .center
105-
) {
106-
ForEach(keys.sorted(), id: \.self) { aKey in
107-
VStack {
108-
Image(aKey)
109-
.interpolation(.high)
110-
.resizable()
111-
.frame(width: 64, height: 64)
112-
.cornerRadius(32)
113-
.overlay(
114-
RoundedRectangle(cornerRadius: 32)
115-
.stroke(Color("BorderColor"), lineWidth: 1)
116-
)
117-
.padding(.top, 16)
118-
.padding(.horizontal, 16)
119-
.padding(.bottom, 8)
120-
121-
Text(avatars[aKey] ?? "")
122-
.font(.caption)
123-
.foregroundColor(.primary)
124-
}
125-
.onTapGesture {
126-
debugPrint("Tapped on avatar: \(aKey)")
127-
if case .myPlanet(let planet) = store.selectedView {
128-
debugPrint("About to set planet avatar to \(aKey)")
129-
do {
93+
ScrollViewReader { proxy in
94+
ScrollView {
95+
LazyVGrid(
96+
columns: [GridItem(), GridItem(), GridItem()],
97+
alignment: .center
98+
) {
99+
ForEach(keys.sorted(), id: \.self) { aKey in
100+
VStack {
101+
let isAnimation: Bool = highlightedItems.contains(aKey)
102+
Image(aKey)
103+
.interpolation(.high)
104+
.resizable()
105+
.frame(width: 64, height: 64)
106+
.cornerRadius(32)
107+
.overlay(
108+
RoundedRectangle(cornerRadius: 32)
109+
.stroke(isAnimation ? Color.accentColor : Color("BorderColor"), lineWidth: isAnimation ? 4 : 1)
110+
)
111+
.padding(.top, 16)
112+
.padding(.horizontal, 16)
113+
.padding(.bottom, 8)
114+
.scaleEffect(isAnimation ? 1.05 : 1.0)
115+
116+
Text(avatars[aKey] ?? "")
117+
.font(.caption)
118+
.foregroundColor(.primary)
119+
}
120+
.id(aKey)
121+
.onTapGesture {
122+
debugPrint("Tapped on avatar: \(aKey)")
123+
if case .myPlanet(let planet) = store.selectedView {
124+
debugPrint("About to set planet \(planet.name) avatar to \(aKey)")
130125
let image = NSImage(named: aKey)
131126
if let image = image, let avatarURL = image.temporaryURL
132127
{
133128
selectedAvatar = image
134129
avatarChanged = true
135-
debugPrint("Set planet avatar to \(aKey)")
130+
debugPrint("Set planet avatar to \(aKey), at: \(avatarURL)")
136131
}
137132
}
138-
catch {
139-
debugPrint("failed to update planet avatar: \(error)")
133+
else {
134+
debugPrint("Cannot set planet avatar")
140135
}
141136
}
142-
else {
143-
debugPrint("Cannot set planet avatar")
144-
}
145-
146137
}
147-
138+
}
139+
}
140+
.onChange(of: randomSelectedAvatarKey) { newValue in
141+
guard let newValue else { return }
142+
Task { @MainActor in
143+
withAnimation(.easeOut(duration: 0.3)) {
144+
proxy.scrollTo(newValue, anchor: .top)
145+
}
148146
}
149147
}
150148
}
@@ -215,7 +213,23 @@ struct AvatarPickerView: View {
215213
if let image = image, let avatarURL = image.temporaryURL {
216214
selectedAvatar = image
217215
avatarChanged = true
218-
debugPrint("Set planet avatar to \(randomKey)")
216+
debugPrint("Set planet avatar to \(randomKey), at: \(avatarURL)")
217+
Task { @MainActor in
218+
highlightedItems.removeAll()
219+
randomSelectedAvatarKey = randomKey
220+
Task.detached(priority: .utility) {
221+
try? await Task.sleep(nanoseconds: 300_000_000)
222+
let _ = await MainActor.run {
223+
self.highlightedItems.insert(randomKey)
224+
}
225+
try? await Task.sleep(nanoseconds: 600_000_000)
226+
await MainActor.run {
227+
let _ = withAnimation(.easeOut(duration: 0.4)) {
228+
highlightedItems.removeAll()
229+
}
230+
}
231+
}
232+
}
219233
}
220234
}
221235
}

Diff for: Planet/versioning.xcconfig

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
CURRENT_PROJECT_VERSION = 2294
1+
CURRENT_PROJECT_VERSION = 2297

0 commit comments

Comments
 (0)