Skip to content

Commit

Permalink
feat (settings): re-add footer settings button with working selector
Browse files Browse the repository at this point in the history
turns out the selector still worked, just under a new name

refactor: user footer to be closer in styling to the official client’s one
  • Loading branch information
cryptoAlgorithm committed Apr 22, 2023
1 parent 8be47fc commit 5d9b7f3
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 121 deletions.
6 changes: 5 additions & 1 deletion Swiftcord/Views/User/Avatar/UserAvatarView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ struct UserAvatarView: View, Equatable {
)
.font(.headline)
.textCase(.uppercase)
.padding(.top, 6)
if !roles.isEmpty {
TagCloudView(
content: roles.map { role in
Expand All @@ -124,7 +125,10 @@ struct UserAvatarView: View, Equatable {
.tint(.blue)
}
}
Text("user.note").font(.headline).textCase(.uppercase)
Text("user.note")
.font(.headline)
.textCase(.uppercase)
.padding(.top, 6)
// Notes are stored locally for now, but eventually will be synced with the Discord API
TextField("Add a note to this user (only visible to you)", text: $note)
.textFieldStyle(.roundedBorder)
Expand Down
221 changes: 102 additions & 119 deletions Swiftcord/Views/User/CurrentUserFooter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ struct CurrentUserFooter: View {
@EnvironmentObject var switcher: AccountSwitcher
@EnvironmentObject var gateway: DiscordGateway

private static let presenceIconMapping: [PresenceStatus: String] = [
.online: "circle.fill",
.idle: "moon.fill",
.dnd: "minus.circle",
.invisible: "circle"
private static let presences: [(presence: PresenceStatus, icon: String)] = [
(.online, "circle.fill"),
(.idle, "moon.fill"),
(.dnd, "minus.circle"),
(.invisible, "circle")
]

private static let log = Logger(category: "CurrentUserFooter")
Expand Down Expand Up @@ -81,137 +81,120 @@ struct CurrentUserFooter: View {
let curUserPresence = gateway.presences[user.id]?.status ?? .offline
let customStatus = gateway.presences[user.id]?.activities.first { $0.type == .custom }

Button {
userPopoverPresented = true
AnalyticsWrapper.event(type: .openPopout, properties: [
"type": "User Status Menu",
"other_user_id": user.id
])
} label: {
HStack(spacing: 8) {
AvatarWithPresence(
avatarURL: user.avatarURL(),
presence: curUserPresence,
animate: false
)
.controlSize(.small)
.padding(.leading, 8)

VStack(alignment: .leading, spacing: 0) {
Text(user.username).font(.headline)
Group {
if let customStatus = customStatus {
Text(customStatus.state ?? "")
} else {
Text("#" + user.discriminator)
}
}.font(.system(size: 12)).opacity(0.75)
}
Spacer()
HStack(spacing: 14) {
Button {
userPopoverPresented = true
AnalyticsWrapper.event(type: .openPopout, properties: [
"type": "User Status Menu",
"other_user_id": user.id
])
} label: {
HStack(spacing: 8) {
AvatarWithPresence(
avatarURL: user.avatarURL(),
presence: curUserPresence,
animate: false
)
.controlSize(.small)

// The hidden selector for opening the preferences window
// is probably removed in macOS 13. Should check if this
// is still broken once macOS 13 is stable.
if #available(macOS 13.0, *) {
EmptyView()
} else {
Button(action: {
NSApp.sendAction(Selector(("showPreferencesWindow:")), to: nil, from: nil)
}, label: {
Image(systemName: "gearshape.fill")
.font(.system(size: 18))
.opacity(0.75)
})
.buttonStyle(.plain)
.padding(.trailing, 14)
VStack(alignment: .leading, spacing: 0) {
Text(user.username).font(.headline)
Group {
if let customStatus = customStatus {
Text(customStatus.state ?? "")
} else {
Text("#" + user.discriminator)
}
}.font(.system(size: 12)).opacity(0.75)
}
}
.padding(2)
.contentShape(Rectangle())
}
.frame(height: 52)
.background(Color(nsColor: .controlBackgroundColor).opacity(0.5))
}
.buttonStyle(.plain)
.popover(isPresented: $userPopoverPresented) {
MiniUserProfileView(user: User(from: user), profile: .constant(UserProfile(
connected_accounts: [],
user: User(from: user)
))) {
VStack(spacing: 4) {
if !(user.bio?.isEmpty ?? true) { Divider() }

// Set presence
Menu {
Button {
updatePresence(with: .online)
} label: {
// Not possible to set custom image size and color
Image(systemName: Self.presenceIconMapping[.online]!)
Text("user.presence.online")
}
Divider()
Button {
updatePresence(with: .idle)
.buttonStyle(.plain)
.popover(isPresented: $userPopoverPresented) {
MiniUserProfileView(user: User(from: user), profile: .constant(UserProfile(
connected_accounts: [],
user: User(from: user)
))) {
VStack(spacing: 4) {
if !(user.bio?.isEmpty ?? true) { Divider() }

// Set presence
Menu {
ForEach(Self.presences, id: \.icon) { (presence, icon) in
Button {
updatePresence(with: presence)
} label: {
// Not possible to set custom image size and color
Image(systemName: icon)
Text(presence.toLocalizedString())
}
if presence == Self.presences.first?.presence { Divider() }
}
} label: {
Image(systemName: Self.presenceIconMapping[.idle]!)
Text("user.presence.idle")
Text(curUserPresence.toLocalizedString())
}
.controlSize(.large)
.disabled(settingPresence)
Button {
updatePresence(with: .dnd)
customStatusPresented = true
} label: {
Image(systemName: Self.presenceIconMapping[.dnd]!)
Text("user.presence.dnd")
if customStatus != nil {
HStack {
Text("Edit Custom Status")
Spacer()
Button {
updatePresence(with: curUserPresence, clearCustomStatus: true)
} label: {
Image(systemName: "xmark.circle.fill").font(.system(size: 18))
}
.buttonStyle(.plain)
.help("Clear Custom Status")
}
} else {
Label("Set Custom Status", systemImage: "face.smiling")
.frame(maxWidth: .infinity, alignment: .leading)
}
}
.buttonStyle(FlatButtonStyle(outlined: true, text: true))
.controlSize(.small)
.disabled(settingPresence)

Divider()

Button {
updatePresence(with: .invisible)
switcherPresented = true
AnalyticsWrapper.event(type: .impressionAccountSwitcher)
} label: {
Image(systemName: Self.presenceIconMapping[.invisible]!)
Text("user.presence.invisible")
}
} label: {
Label(
curUserPresence.toLocalizedString(),
systemImage: Self.presenceIconMapping[curUserPresence] ?? "circle"
)
}
.controlSize(.large)
.disabled(settingPresence)
Button {
customStatusPresented = true
} label: {
if customStatus != nil {
HStack {
Text("Edit Custom Status")
Spacer()
Button {
updatePresence(with: curUserPresence, clearCustomStatus: true)
} label: {
Image(systemName: "xmark.circle.fill").font(.system(size: 18))
}
.buttonStyle(.plain)
.help("Clear Custom Status")
}
} else {
Label("Set Custom Status", systemImage: "face.smiling")
Label("Switch Accounts", systemImage: "arrow.left.arrow.right")
.frame(maxWidth: .infinity, alignment: .leading)
}
.buttonStyle(FlatButtonStyle(outlined: true, text: true))
.controlSize(.small)
}
.buttonStyle(FlatButtonStyle(outlined: true, text: true))
.controlSize(.small)
.disabled(settingPresence)
}
}

Divider()
Spacer()

Button {
switcherPresented = true
AnalyticsWrapper.event(type: .impressionAccountSwitcher)
} label: {
Label("Switch Accounts", systemImage: "arrow.left.arrow.right")
.frame(maxWidth: .infinity, alignment: .leading)
}
.buttonStyle(FlatButtonStyle(outlined: true, text: true))
.controlSize(.small)
Button(action: {
if #available(macOS 13.0, *) {
NSApp.sendAction(Selector(("showSettingsWindow:")), to: nil, from: nil)
} else {
NSApp.sendAction(Selector(("showPreferencesWindow:")), to: nil, from: nil)
}
}
}, label: {
Image(systemName: "gearshape.fill")
.font(.system(size: 18))
.opacity(0.75)
})
.buttonStyle(.plain)
.frame(width: 32, height: 32)
}
.frame(height: 52)
.padding(.horizontal, 8)
.background(Color(nsColor: .controlBackgroundColor).opacity(0.5))
.sheet(isPresented: $switcherPresented) {
accountSwitcher()
}
Expand Down
2 changes: 1 addition & 1 deletion Swiftcord/Views/User/Profile/MiniUserProfileView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ struct MiniUserProfileView<RichContentSlot: View>: View {
.fixedSize(horizontal: false, vertical: true)
}

contentSlot.padding(.top, 6)
contentSlot
}
}
.padding(12)
Expand Down

0 comments on commit 5d9b7f3

Please sign in to comment.