@@ -26,11 +26,11 @@ struct CurrentUserFooter: View {
26
26
@EnvironmentObject var switcher : AccountSwitcher
27
27
@EnvironmentObject var gateway : DiscordGateway
28
28
29
- private static let presenceIconMapping : [ PresenceStatus : String ] = [
30
- . online: " circle.fill " ,
31
- . idle: " moon.fill " ,
32
- . dnd: " minus.circle " ,
33
- . invisible: " circle "
29
+ private static let presences : [ ( presence : PresenceStatus , icon : String ) ] = [
30
+ ( . online, " circle.fill " ) ,
31
+ ( . idle, " moon.fill " ) ,
32
+ ( . dnd, " minus.circle " ) ,
33
+ ( . invisible, " circle " )
34
34
]
35
35
36
36
private static let log = Logger ( category: " CurrentUserFooter " )
@@ -81,137 +81,120 @@ struct CurrentUserFooter: View {
81
81
let curUserPresence = gateway. presences [ user. id] ? . status ?? . offline
82
82
let customStatus = gateway. presences [ user. id] ? . activities. first { $0. type == . custom }
83
83
84
- Button {
85
- userPopoverPresented = true
86
- AnalyticsWrapper . event ( type: . openPopout, properties: [
87
- " type " : " User Status Menu " ,
88
- " other_user_id " : user. id
89
- ] )
90
- } label: {
91
- HStack ( spacing: 8 ) {
92
- AvatarWithPresence (
93
- avatarURL: user. avatarURL ( ) ,
94
- presence: curUserPresence,
95
- animate: false
96
- )
97
- . controlSize ( . small)
98
- . padding ( . leading, 8 )
99
-
100
- VStack ( alignment: . leading, spacing: 0 ) {
101
- Text ( user. username) . font ( . headline)
102
- Group {
103
- if let customStatus = customStatus {
104
- Text ( customStatus. state ?? " " )
105
- } else {
106
- Text ( " # " + user. discriminator)
107
- }
108
- } . font ( . system( size: 12 ) ) . opacity ( 0.75 )
109
- }
110
- Spacer ( )
84
+ HStack ( spacing: 14 ) {
85
+ Button {
86
+ userPopoverPresented = true
87
+ AnalyticsWrapper . event ( type: . openPopout, properties: [
88
+ " type " : " User Status Menu " ,
89
+ " other_user_id " : user. id
90
+ ] )
91
+ } label: {
92
+ HStack ( spacing: 8 ) {
93
+ AvatarWithPresence (
94
+ avatarURL: user. avatarURL ( ) ,
95
+ presence: curUserPresence,
96
+ animate: false
97
+ )
98
+ . controlSize ( . small)
111
99
112
- // The hidden selector for opening the preferences window
113
- // is probably removed in macOS 13. Should check if this
114
- // is still broken once macOS 13 is stable.
115
- if #available( macOS 13 . 0 , * ) {
116
- EmptyView ( )
117
- } else {
118
- Button ( action: {
119
- NSApp . sendAction ( Selector ( ( " showPreferencesWindow: " ) ) , to: nil , from: nil )
120
- } , label: {
121
- Image ( systemName: " gearshape.fill " )
122
- . font ( . system( size: 18 ) )
123
- . opacity ( 0.75 )
124
- } )
125
- . buttonStyle ( . plain)
126
- . padding ( . trailing, 14 )
100
+ VStack ( alignment: . leading, spacing: 0 ) {
101
+ Text ( user. username) . font ( . headline)
102
+ Group {
103
+ if let customStatus = customStatus {
104
+ Text ( customStatus. state ?? " " )
105
+ } else {
106
+ Text ( " # " + user. discriminator)
107
+ }
108
+ } . font ( . system( size: 12 ) ) . opacity ( 0.75 )
109
+ }
127
110
}
111
+ . padding ( 2 )
112
+ . contentShape ( Rectangle ( ) )
128
113
}
129
- . frame ( height: 52 )
130
- . background ( Color ( nsColor: . controlBackgroundColor) . opacity ( 0.5 ) )
131
- }
132
- . buttonStyle ( . plain)
133
- . popover ( isPresented: $userPopoverPresented) {
134
- MiniUserProfileView ( user: User ( from: user) , profile: . constant( UserProfile (
135
- connected_accounts: [ ] ,
136
- user: User ( from: user)
137
- ) ) ) {
138
- VStack ( spacing: 4 ) {
139
- if !( user. bio? . isEmpty ?? true ) { Divider ( ) }
140
-
141
- // Set presence
142
- Menu {
143
- Button {
144
- updatePresence ( with: . online)
145
- } label: {
146
- // Not possible to set custom image size and color
147
- Image ( systemName: Self . presenceIconMapping [ . online] !)
148
- Text ( " user.presence.online " )
149
- }
150
- Divider ( )
151
- Button {
152
- updatePresence ( with: . idle)
114
+ . buttonStyle ( . plain)
115
+ . popover ( isPresented: $userPopoverPresented) {
116
+ MiniUserProfileView ( user: User ( from: user) , profile: . constant( UserProfile (
117
+ connected_accounts: [ ] ,
118
+ user: User ( from: user)
119
+ ) ) ) {
120
+ VStack ( spacing: 4 ) {
121
+ if !( user. bio? . isEmpty ?? true ) { Divider ( ) }
122
+
123
+ // Set presence
124
+ Menu {
125
+ ForEach ( Self . presences, id: \. icon) { ( presence, icon) in
126
+ Button {
127
+ updatePresence ( with: presence)
128
+ } label: {
129
+ // Not possible to set custom image size and color
130
+ Image ( systemName: icon)
131
+ Text ( presence. toLocalizedString ( ) )
132
+ }
133
+ if presence == Self . presences. first? . presence { Divider ( ) }
134
+ }
153
135
} label: {
154
- Image ( systemName: Self . presenceIconMapping [ . idle] !)
155
- Text ( " user.presence.idle " )
136
+ Text ( curUserPresence. toLocalizedString ( ) )
156
137
}
138
+ . controlSize ( . large)
139
+ . disabled ( settingPresence)
157
140
Button {
158
- updatePresence ( with : . dnd )
141
+ customStatusPresented = true
159
142
} label: {
160
- Image ( systemName: Self . presenceIconMapping [ . dnd] !)
161
- Text ( " user.presence.dnd " )
143
+ if customStatus != nil {
144
+ HStack {
145
+ Text ( " Edit Custom Status " )
146
+ Spacer ( )
147
+ Button {
148
+ updatePresence ( with: curUserPresence, clearCustomStatus: true )
149
+ } label: {
150
+ Image ( systemName: " xmark.circle.fill " ) . font ( . system( size: 18 ) )
151
+ }
152
+ . buttonStyle ( . plain)
153
+ . help ( " Clear Custom Status " )
154
+ }
155
+ } else {
156
+ Label ( " Set Custom Status " , systemImage: " face.smiling " )
157
+ . frame ( maxWidth: . infinity, alignment: . leading)
158
+ }
162
159
}
160
+ . buttonStyle ( FlatButtonStyle ( outlined: true , text: true ) )
161
+ . controlSize ( . small)
162
+ . disabled ( settingPresence)
163
+
164
+ Divider ( )
165
+
163
166
Button {
164
- updatePresence ( with: . invisible)
167
+ switcherPresented = true
168
+ AnalyticsWrapper . event ( type: . impressionAccountSwitcher)
165
169
} label: {
166
- Image ( systemName: Self . presenceIconMapping [ . invisible] !)
167
- Text ( " user.presence.invisible " )
168
- }
169
- } label: {
170
- Label (
171
- curUserPresence. toLocalizedString ( ) ,
172
- systemImage: Self . presenceIconMapping [ curUserPresence] ?? " circle "
173
- )
174
- }
175
- . controlSize ( . large)
176
- . disabled ( settingPresence)
177
- Button {
178
- customStatusPresented = true
179
- } label: {
180
- if customStatus != nil {
181
- HStack {
182
- Text ( " Edit Custom Status " )
183
- Spacer ( )
184
- Button {
185
- updatePresence ( with: curUserPresence, clearCustomStatus: true )
186
- } label: {
187
- Image ( systemName: " xmark.circle.fill " ) . font ( . system( size: 18 ) )
188
- }
189
- . buttonStyle ( . plain)
190
- . help ( " Clear Custom Status " )
191
- }
192
- } else {
193
- Label ( " Set Custom Status " , systemImage: " face.smiling " )
170
+ Label ( " Switch Accounts " , systemImage: " arrow.left.arrow.right " )
194
171
. frame ( maxWidth: . infinity, alignment: . leading)
195
172
}
173
+ . buttonStyle ( FlatButtonStyle ( outlined: true , text: true ) )
174
+ . controlSize ( . small)
196
175
}
197
- . buttonStyle ( FlatButtonStyle ( outlined: true , text: true ) )
198
- . controlSize ( . small)
199
- . disabled ( settingPresence)
176
+ }
177
+ }
200
178
201
- Divider ( )
179
+ Spacer ( )
202
180
203
- Button {
204
- switcherPresented = true
205
- AnalyticsWrapper . event ( type: . impressionAccountSwitcher)
206
- } label: {
207
- Label ( " Switch Accounts " , systemImage: " arrow.left.arrow.right " )
208
- . frame ( maxWidth: . infinity, alignment: . leading)
209
- }
210
- . buttonStyle ( FlatButtonStyle ( outlined: true , text: true ) )
211
- . controlSize ( . small)
181
+ Button ( action: {
182
+ if #available( macOS 13 . 0 , * ) {
183
+ NSApp . sendAction ( Selector ( ( " showSettingsWindow: " ) ) , to: nil , from: nil )
184
+ } else {
185
+ NSApp . sendAction ( Selector ( ( " showPreferencesWindow: " ) ) , to: nil , from: nil )
212
186
}
213
- }
187
+ } , label: {
188
+ Image ( systemName: " gearshape.fill " )
189
+ . font ( . system( size: 18 ) )
190
+ . opacity ( 0.75 )
191
+ } )
192
+ . buttonStyle ( . plain)
193
+ . frame ( width: 32 , height: 32 )
214
194
}
195
+ . frame ( height: 52 )
196
+ . padding ( . horizontal, 8 )
197
+ . background ( Color ( nsColor: . controlBackgroundColor) . opacity ( 0.5 ) )
215
198
. sheet ( isPresented: $switcherPresented) {
216
199
accountSwitcher ( )
217
200
}
0 commit comments