Merge branch 'main' into tip-system

This commit is contained in:
Thomas Ricouard 2024-06-26 07:25:12 +02:00
commit b008b5bce2
8 changed files with 125 additions and 27 deletions

View file

@ -23,8 +23,8 @@
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",
"location" : "https://github.com/divadretlaw/EmojiText", "location" : "https://github.com/divadretlaw/EmojiText",
"state" : { "state" : {
"revision" : "415112e5f14619be0fdddd9dc6594bd76702927c", "revision" : "174a7bc7bd75650ad1acb5679dbb754296093de0",
"version" : "4.0.3" "version" : "4.0.0"
} }
}, },
{ {
@ -68,8 +68,8 @@
"kind" : "remoteSourceControl", "kind" : "remoteSourceControl",
"location" : "https://github.com/kean/Nuke", "location" : "https://github.com/kean/Nuke",
"state" : { "state" : {
"revision" : "2efd206503e99dd3a88a4dc433a76f98ce8cc198", "revision" : "311016d972aa751ae8ab0cd5897422ebe7db0501",
"version" : "12.7.1" "version" : "12.7.3"
} }
}, },
{ {

View file

@ -9,6 +9,7 @@ struct ToolbarTab: ToolbarContent {
@Environment(\.horizontalSizeClass) private var horizontalSizeClass @Environment(\.horizontalSizeClass) private var horizontalSizeClass
@Environment(UserPreferences.self) private var userPreferences @Environment(UserPreferences.self) private var userPreferences
@Environment(Theme.self) private var theme
@Binding var routerPath: RouterPath @Binding var routerPath: RouterPath
@ -35,7 +36,7 @@ struct ToolbarTab: ToolbarContent {
(UIDevice.current.userInterfaceIdiom == .pad && horizontalSizeClass == .compact) (UIDevice.current.userInterfaceIdiom == .pad && horizontalSizeClass == .compact)
{ {
ToolbarItem(placement: .navigationBarLeading) { ToolbarItem(placement: .navigationBarLeading) {
AppAccountsSelectorView(routerPath: routerPath) AppAccountsSelectorView(routerPath: routerPath, avatarConfig: theme.avatarShape == .circle ? .badge : .badgeRounded)
} }
} }
} }

View file

@ -13465,6 +13465,23 @@
} }
} }
}, },
"account.edit.avatar.delete" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Delete avatar"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Supprimer l'avatar"
}
}
}
},
"account.edit.display-name" : { "account.edit.display-name" : {
"extractionState" : "manual", "extractionState" : "manual",
"localizations" : { "localizations" : {
@ -13941,6 +13958,23 @@
} }
} }
}, },
"account.edit.header.delete" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Delete header"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "Supprimer la bannière"
}
}
}
},
"account.edit.metadata-name-placeholder" : { "account.edit.metadata-name-placeholder" : {
"extractionState" : "manual", "extractionState" : "manual",
"localizations" : { "localizations" : {

View file

@ -87,28 +87,45 @@ public struct EditAccountView: View {
.frame(height: 150) .frame(height: 150)
} }
} }
if let avatar = viewModel.avatar { ZStack(alignment: .bottomLeading) {
ZStack(alignment: .bottomLeading) { AvatarView(viewModel.avatar, config: .account)
AvatarView(avatar, config: .account) Menu {
Menu { Button("account.edit.avatar") {
Button("account.edit.avatar") { viewModel.isChangingAvatar = true
viewModel.isChangingAvatar = true viewModel.isPhotoPickerPresented = true
viewModel.isPhotoPickerPresented = true
}
Button("account.edit.header") {
viewModel.isChangingHeader = true
viewModel.isPhotoPickerPresented = true
}
} label: {
Image(systemName: "photo.badge.plus")
.foregroundStyle(.white)
} }
.buttonStyle(.borderedProminent) Button("account.edit.header") {
.clipShape(Circle()) viewModel.isChangingHeader = true
.offset(x: -8, y: 8) viewModel.isPhotoPickerPresented = true
}
if viewModel.avatar != nil || viewModel.header != nil {
Divider()
}
if viewModel.avatar != nil {
Button("account.edit.avatar.delete", role: .destructive) {
Task {
await viewModel.deleteAvatar()
}
}
}
if viewModel.header != nil {
Button("account.edit.header.delete", role: .destructive) {
Task {
await viewModel.deleteHeader()
}
}
}
} label: {
Image(systemName: "photo.badge.plus")
.foregroundStyle(.white)
} }
.buttonStyle(.borderedProminent)
.clipShape(Circle())
.offset(x: -8, y: 8)
.padding(EdgeInsets(top: 0, leading: 0, bottom: 8, trailing: 0))
} }
} }
.frame(minWidth: 0, maxWidth: .infinity)
.overlay { .overlay {
if viewModel.isChangingAvatar || viewModel.isChangingHeader { if viewModel.isChangingAvatar || viewModel.isChangingHeader {
ZStack(alignment: .center) { ZStack(alignment: .center) {

View file

@ -82,8 +82,8 @@ import SwiftUI
isBot = account.bot isBot = account.bot
isLocked = account.locked isLocked = account.locked
isDiscoverable = account.discoverable ?? false isDiscoverable = account.discoverable ?? false
avatar = account.avatar avatar = account.haveAvatar ? account.avatar : nil
header = account.header header = account.haveHeader ? account.header : nil
fields = account.source?.fields.map { .init(name: $0.name, value: $0.value.asRawText) } ?? [] fields = account.source?.fields.map { .init(name: $0.name, value: $0.value.asRawText) } ?? []
withAnimation { withAnimation {
isLoading = false isLoading = false
@ -112,6 +112,28 @@ import SwiftUI
} }
} }
func deleteAvatar() async -> Bool {
guard let client else { return false }
do {
let response = try await client.delete(endpoint: Profile.deleteAvatar)
avatar = nil
return response?.statusCode == 200
} catch {
return false
}
}
func deleteHeader() async -> Bool {
guard let client else { return false }
do {
let response = try await client.delete(endpoint: Profile.deleteHeader)
header = nil
return response?.statusCode == 200
} catch {
return false
}
}
private func uploadHeader(data: Data) async -> Bool { private func uploadHeader(data: Data) async -> Bool {
guard let client else { return false } guard let client else { return false }
do { do {

View file

@ -19,8 +19,8 @@ let package = Package(
dependencies: [ dependencies: [
.package(name: "Models", path: "../Models"), .package(name: "Models", path: "../Models"),
.package(name: "Env", path: "../Env"), .package(name: "Env", path: "../Env"),
.package(url: "https://github.com/kean/Nuke", from: "12.4.0"), .package(url: "https://github.com/kean/Nuke", exact: "12.7.3"),
.package(url: "https://github.com/divadretlaw/EmojiText", from: "4.0.0"), .package(url: "https://github.com/divadretlaw/EmojiText", exact: "4.0.0"),
], ],
targets: [ targets: [
.target( .target(

View file

@ -53,6 +53,7 @@ public struct AvatarView: View {
#endif #endif
public static let embed = FrameConfig(width: 34, height: 34) public static let embed = FrameConfig(width: 34, height: 34)
public static let badge = FrameConfig(width: 28, height: 28, cornerRadius: 14) public static let badge = FrameConfig(width: 28, height: 28, cornerRadius: 14)
public static let badgeRounded = FrameConfig(width: 28, height: 28)
public static let list = FrameConfig(width: 20, height: 20, cornerRadius: 10) public static let list = FrameConfig(width: 20, height: 20, cornerRadius: 10)
public static let boost = FrameConfig(width: 12, height: 12, cornerRadius: 6) public static let boost = FrameConfig(width: 12, height: 12, cornerRadius: 6)
} }

View file

@ -0,0 +1,23 @@
import Foundation
public enum Profile: Endpoint {
case deleteAvatar
case deleteHeader
public func path() -> String {
switch self {
case .deleteAvatar:
"profile/avatar"
case .deleteHeader:
"profile/header"
}
}
public func queryItems() -> [URLQueryItem]? {
switch self {
case .deleteAvatar, .deleteHeader:
nil
}
}
}