Display and edit notes on profiles (#929)

Closes #165
This commit is contained in:
Peter-Josef Meisch 2023-02-18 18:28:16 +01:00 committed by GitHub
parent 7112e6515b
commit 7cc1ca44b5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 243 additions and 0 deletions

View file

@ -253,6 +253,12 @@
"account.joined" = "Далучыліся"; "account.joined" = "Далучыліся";
"account.action.logout" = "Выйсці з уліковага запісу"; "account.action.logout" = "Выйсці з уліковага запісу";
"account.relation.note.edit" = "Edit Note";
"account.relation.note.edit.placeholder" = "Enter Note text";
"account.relation.note.edit.error.save.message" = "Error while saving your note, please try again.";
"account.relation.note.edit.error.save.title" = "Error while saving your note";
"account.relation.note.label" = "Note:";
// MARK: Package: Conversations // MARK: Package: Conversations
"conversations.action.delete" = "Выдаліць"; "conversations.action.delete" = "Выдаліць";
"conversations.action.mark-read" = "Адзначыць як прачытанае"; "conversations.action.mark-read" = "Адзначыць як прачытанае";

View file

@ -262,6 +262,12 @@
"account.joined" = "S'ha unit"; "account.joined" = "S'ha unit";
"account.action.logout" = "Tanca la sessió"; "account.action.logout" = "Tanca la sessió";
"account.relation.note.edit" = "Edit Note";
"account.relation.note.edit.placeholder" = "Enter Note text";
"account.relation.note.edit.error.save.message" = "Error while saving your note, please try again.";
"account.relation.note.edit.error.save.title" = "Error while saving your note";
"account.relation.note.label" = "Note:";
// MARK: Package: Conversations // MARK: Package: Conversations
"conversations.action.delete" = "Elimina"; "conversations.action.delete" = "Elimina";
"conversations.action.mark-read" = "Marca com a llegit"; "conversations.action.mark-read" = "Marca com a llegit";

View file

@ -264,6 +264,12 @@
"account.action.logout" = "Abmelden"; "account.action.logout" = "Abmelden";
"account.action.edit-filters" = "Filter bearbeiten"; "account.action.edit-filters" = "Filter bearbeiten";
"account.relation.note.edit" = "Edit Note";
"account.relation.note.edit.placeholder" = "Enter Note text";
"account.relation.note.edit.error.save.message" = "Error while saving your note, please try again.";
"account.relation.note.edit.error.save.title" = "Error while saving your note";
"account.relation.note.label" = "Note:";
// MARK: Package: Conversations // MARK: Package: Conversations
"conversations.action.delete" = "Löschen"; "conversations.action.delete" = "Löschen";
"conversations.action.mark-read" = "Als gelesen markieren"; "conversations.action.mark-read" = "Als gelesen markieren";

View file

@ -265,6 +265,12 @@
"account.joined" = "Joined"; "account.joined" = "Joined";
"account.action.logout" = "Log out account"; "account.action.logout" = "Log out account";
"account.relation.note.edit" = "Edit Note";
"account.relation.note.edit.placeholder" = "Enter Note text";
"account.relation.note.edit.error.save.message" = "Error while saving your note, please try again.";
"account.relation.note.edit.error.save.title" = "Error while saving your note";
"account.relation.note.label" = "Note:";
// MARK: Package: Conversations // MARK: Package: Conversations
"conversations.action.delete" = "Delete"; "conversations.action.delete" = "Delete";
"conversations.action.mark-read" = "Mark as read"; "conversations.action.mark-read" = "Mark as read";

View file

@ -264,6 +264,12 @@
"account.joined" = "Joined"; "account.joined" = "Joined";
"account.action.logout" = "Log out account"; "account.action.logout" = "Log out account";
"account.relation.note.edit" = "Edit Note";
"account.relation.note.edit.placeholder" = "Enter Note text";
"account.relation.note.edit.error.save.message" = "Error while saving your note, please try again.";
"account.relation.note.edit.error.save.title" = "Error while saving your note";
"account.relation.note.label" = "Note:";
// MARK: Package: Conversations // MARK: Package: Conversations
"conversations.action.delete" = "Delete"; "conversations.action.delete" = "Delete";
"conversations.action.mark-read" = "Mark as read"; "conversations.action.mark-read" = "Mark as read";

View file

@ -264,6 +264,12 @@
"account.joined" = "Se unió el"; "account.joined" = "Se unió el";
"account.action.logout" = "Cerrar sesión"; "account.action.logout" = "Cerrar sesión";
"account.relation.note.edit" = "Edit Note";
"account.relation.note.edit.placeholder" = "Enter Note text";
"account.relation.note.edit.error.save.message" = "Error while saving your note, please try again.";
"account.relation.note.edit.error.save.title" = "Error while saving your note";
"account.relation.note.label" = "Note:";
// MARK: Package: Conversations // MARK: Package: Conversations
"conversations.action.delete" = "Borrar"; "conversations.action.delete" = "Borrar";
"conversations.action.mark-read" = "Marcar como leído"; "conversations.action.mark-read" = "Marcar como leído";

View file

@ -264,6 +264,12 @@
"account.action.logout" = "Amaitu saioa"; "account.action.logout" = "Amaitu saioa";
"account.action.edit-filters" = "Editatu iragazkiak"; "account.action.edit-filters" = "Editatu iragazkiak";
"account.relation.note.edit" = "Edit Note";
"account.relation.note.edit.placeholder" = "Enter Note text";
"account.relation.note.edit.error.save.message" = "Error while saving your note, please try again.";
"account.relation.note.edit.error.save.title" = "Error while saving your note";
"account.relation.note.label" = "Note:";
// MARK: Package: Conversations // MARK: Package: Conversations
"conversations.action.delete" = "Ezabatu"; "conversations.action.delete" = "Ezabatu";
"conversations.action.mark-read" = "Markatu irakurritzat"; "conversations.action.mark-read" = "Markatu irakurritzat";

View file

@ -263,6 +263,12 @@
"account.joined" = "Inscrit"; "account.joined" = "Inscrit";
"account.action.logout" = "Déconnexion"; "account.action.logout" = "Déconnexion";
"account.relation.note.edit" = "Edit Note";
"account.relation.note.edit.placeholder" = "Enter Note text";
"account.relation.note.edit.error.save.message" = "Error while saving your note, please try again.";
"account.relation.note.edit.error.save.title" = "Error while saving your note";
"account.relation.note.label" = "Note:";
// MARK: Package: Conversations // MARK: Package: Conversations
"conversations.action.delete" = "Supprimer"; "conversations.action.delete" = "Supprimer";
"conversations.action.mark-read" = "Marquer comme lu"; "conversations.action.mark-read" = "Marquer comme lu";

View file

@ -264,6 +264,12 @@
"account.action.logout" = "Esci dall'account"; "account.action.logout" = "Esci dall'account";
"account.action.edit-filters" = "Modifica i Filtri"; "account.action.edit-filters" = "Modifica i Filtri";
"account.relation.note.edit" = "Edit Note";
"account.relation.note.edit.placeholder" = "Enter Note text";
"account.relation.note.edit.error.save.message" = "Error while saving your note, please try again.";
"account.relation.note.edit.error.save.title" = "Error while saving your note";
"account.relation.note.label" = "Note:";
// MARK: Package: Conversations // MARK: Package: Conversations
"conversations.action.delete" = "Cancella"; "conversations.action.delete" = "Cancella";
"conversations.action.mark-read" = "Segna come letto"; "conversations.action.mark-read" = "Segna come letto";

View file

@ -263,6 +263,12 @@
"account.joined" = "登録日"; "account.joined" = "登録日";
"account.action.logout" = "アカウントをログアウトする"; "account.action.logout" = "アカウントをログアウトする";
"account.relation.note.edit" = "Edit Note";
"account.relation.note.edit.placeholder" = "Enter Note text";
"account.relation.note.edit.error.save.message" = "Error while saving your note, please try again.";
"account.relation.note.edit.error.save.title" = "Error while saving your note";
"account.relation.note.label" = "Note:";
// MARK: Package: Conversations // MARK: Package: Conversations
"conversations.action.delete" = "削除"; "conversations.action.delete" = "削除";
"conversations.action.mark-read" = "既読にする"; "conversations.action.mark-read" = "既読にする";

View file

@ -264,6 +264,12 @@
"account.joined" = "가입"; "account.joined" = "가입";
"account.action.logout" = "로그아웃"; "account.action.logout" = "로그아웃";
"account.relation.note.edit" = "Edit Note";
"account.relation.note.edit.placeholder" = "Enter Note text";
"account.relation.note.edit.error.save.message" = "Error while saving your note, please try again.";
"account.relation.note.edit.error.save.title" = "Error while saving your note";
"account.relation.note.label" = "Note:";
// MARK: Package: Conversations // MARK: Package: Conversations
"conversations.action.delete" = "삭제"; "conversations.action.delete" = "삭제";
"conversations.action.mark-read" = "읽음으로 표시"; "conversations.action.mark-read" = "읽음으로 표시";

View file

@ -263,6 +263,12 @@
"account.joined" = "Ble med"; "account.joined" = "Ble med";
"account.action.logout" = "Logg ut konto"; "account.action.logout" = "Logg ut konto";
"account.relation.note.edit" = "Edit Note";
"account.relation.note.edit.placeholder" = "Enter Note text";
"account.relation.note.edit.error.save.message" = "Error while saving your note, please try again.";
"account.relation.note.edit.error.save.title" = "Error while saving your note";
"account.relation.note.label" = "Note:";
// MARK: Package: Conversations // MARK: Package: Conversations
"conversations.action.delete" = "Slett"; "conversations.action.delete" = "Slett";
"conversations.action.mark-read" = "Merk som lest"; "conversations.action.mark-read" = "Merk som lest";

View file

@ -261,6 +261,12 @@
"account.action.logout" = "Log uit"; "account.action.logout" = "Log uit";
"account.action.edit-filters" = "Bewerk filters"; "account.action.edit-filters" = "Bewerk filters";
"account.relation.note.edit" = "Edit Note";
"account.relation.note.edit.placeholder" = "Enter Note text";
"account.relation.note.edit.error.save.message" = "Error while saving your note, please try again.";
"account.relation.note.edit.error.save.title" = "Error while saving your note";
"account.relation.note.label" = "Note:";
// MARK: Package: Conversations // MARK: Package: Conversations
"conversations.action.delete" = "Verwijder"; "conversations.action.delete" = "Verwijder";
"conversations.action.mark-read" = "Markeer als gelezen"; "conversations.action.mark-read" = "Markeer als gelezen";

View file

@ -261,6 +261,12 @@
"account.joined" = "Dołączył(a)"; "account.joined" = "Dołączył(a)";
"account.action.logout" = "Wyloguj się"; "account.action.logout" = "Wyloguj się";
"account.relation.note.edit" = "Edit Note";
"account.relation.note.edit.placeholder" = "Enter Note text";
"account.relation.note.edit.error.save.message" = "Error while saving your note, please try again.";
"account.relation.note.edit.error.save.title" = "Error while saving your note";
"account.relation.note.label" = "Note:";
// MARK: Package: Conversations // MARK: Package: Conversations
"conversations.action.delete" = "Usuń"; "conversations.action.delete" = "Usuń";
"conversations.action.mark-read" = "Oznacz jako przeczytany"; "conversations.action.mark-read" = "Oznacz jako przeczytany";

View file

@ -263,6 +263,12 @@
"account.joined" = "Entrou em"; "account.joined" = "Entrou em";
"account.action.logout" = "Sair da conta"; "account.action.logout" = "Sair da conta";
"account.relation.note.edit" = "Edit Note";
"account.relation.note.edit.placeholder" = "Enter Note text";
"account.relation.note.edit.error.save.message" = "Error while saving your note, please try again.";
"account.relation.note.edit.error.save.title" = "Error while saving your note";
"account.relation.note.label" = "Note:";
// MARK: Package: Conversations // MARK: Package: Conversations
"conversations.action.delete" = "Excluir"; "conversations.action.delete" = "Excluir";
"conversations.action.mark-read" = "Marcar como lida"; "conversations.action.mark-read" = "Marcar como lida";

View file

@ -259,6 +259,12 @@
"account.joined" = "Katılındı"; "account.joined" = "Katılındı";
"account.action.logout" = "Log out account"; "account.action.logout" = "Log out account";
"account.relation.note.edit" = "Edit Note";
"account.relation.note.edit.placeholder" = "Enter Note text";
"account.relation.note.edit.error.save.message" = "Error while saving your note, please try again.";
"account.relation.note.edit.error.save.title" = "Error while saving your note";
"account.relation.note.label" = "Note:";
// MARK: Package: Conversations // MARK: Package: Conversations
"conversations.action.delete" = "Sil"; "conversations.action.delete" = "Sil";
"conversations.action.mark-read" = "Okundu olarak işaretle"; "conversations.action.mark-read" = "Okundu olarak işaretle";

View file

@ -264,6 +264,12 @@
"account.action.logout" = "退出登录"; "account.action.logout" = "退出登录";
"account.action.edit-filters" = "编辑过滤器"; "account.action.edit-filters" = "编辑过滤器";
"account.relation.note.edit" = "Edit Note";
"account.relation.note.edit.placeholder" = "Enter Note text";
"account.relation.note.edit.error.save.message" = "Error while saving your note, please try again.";
"account.relation.note.edit.error.save.title" = "Error while saving your note";
"account.relation.note.label" = "Note:";
// MARK: Package: Conversations // MARK: Package: Conversations
"conversations.action.delete" = "删除"; "conversations.action.delete" = "删除";
"conversations.action.mark-read" = "标记为已读"; "conversations.action.mark-read" = "标记为已读";

View file

@ -150,6 +150,12 @@ struct AccountDetailHeaderView: View {
} }
} }
} }
if let note = viewModel.relationship?.note, !note.isEmpty,
!viewModel.isCurrentUser {
makeNoteView(note)
}
EmojiTextApp(account.note, emojis: account.emojis) EmojiTextApp(account.note, emojis: account.emojis)
.font(.scaledBody) .font(.scaledBody)
.padding(.top, 8) .padding(.top, 8)
@ -193,6 +199,23 @@ struct AccountDetailHeaderView: View {
.padding(.top, 6) .padding(.top, 6)
} }
} }
@ViewBuilder
private func makeNoteView(_ note: String) -> some View {
VStack(alignment: .leading, spacing: 4) {
Text("account.relation.note.label")
.foregroundColor(.gray)
Text(note)
.frame(maxWidth: .infinity)
.padding(8)
.background(theme.secondaryBackgroundColor)
.cornerRadius(4)
.overlay(
RoundedRectangle(cornerRadius: 4)
.stroke(.gray.opacity(0.35), lineWidth: 1)
)
}
}
} }
struct AccountDetailHeaderView_Previews: PreviewProvider { struct AccountDetailHeaderView_Previews: PreviewProvider {

View file

@ -26,6 +26,7 @@ public struct AccountDetailView: View {
@State private var isEditingAccount: Bool = false @State private var isEditingAccount: Bool = false
@State private var isEditingFilters: Bool = false @State private var isEditingFilters: Bool = false
@State private var isEditingRelationshipNote: Bool = false
/// When coming from a URL like a mention tap in a status. /// When coming from a URL like a mention tap in a status.
public init(accountId: String) { public init(accountId: String) {
@ -126,6 +127,9 @@ public struct AccountDetailView: View {
.sheet(isPresented: $isEditingFilters, content: { .sheet(isPresented: $isEditingFilters, content: {
FiltersListView() FiltersListView()
}) })
.sheet(isPresented: $isEditingRelationshipNote, content: {
EditRelationshipNoteView(accountDetailViewModel: viewModel)
})
.edgesIgnoringSafeArea(.top) .edgesIgnoringSafeArea(.top)
.navigationBarTitleDisplayMode(.inline) .navigationBarTitleDisplayMode(.inline)
.toolbar { .toolbar {
@ -487,6 +491,12 @@ public struct AccountDetailView: View {
} }
Divider() Divider()
Button {
isEditingRelationshipNote = true
} label: {
Label("account.relation.note.edit", systemImage: "pencil")
}
} }
if viewModel.relationship?.following == true { if viewModel.relationship?.following == true {

View file

@ -0,0 +1,68 @@
import DesignSystem
import Network
import SwiftUI
public struct EditRelationshipNoteView: View {
@Environment(\.dismiss) private var dismiss
@EnvironmentObject private var theme: Theme
@EnvironmentObject private var client: Client
// need this model to refresh after storing the new note on mastodon
var accountDetailViewModel: AccountDetailViewModel
@StateObject private var viewModel = EditRelationshipNoteViewModel()
public var body: some View {
NavigationStack {
Form {
Section("account.relation.note.label") {
TextField("account.relation.note.edit.placeholder", text: $viewModel.note, axis: .vertical)
.frame(minHeight: 150, maxHeight: 150, alignment: .top)
}
.listRowBackground(theme.primaryBackgroundColor)
}
.scrollContentBackground(.hidden)
.background(theme.secondaryBackgroundColor)
.navigationTitle("account.relation.note.edit")
.navigationBarTitleDisplayMode(.inline)
.toolbar {
toolbarContent
}
.alert("account.relation.note.edit.error.save.title",
isPresented: $viewModel.saveError,
actions: {
Button("alert.button.ok", action: {})
}, message: { Text("account.relation.note.edit.error.save.message") })
.task {
viewModel.client = client
viewModel.relatedAccountId = accountDetailViewModel.accountId
viewModel.note = accountDetailViewModel.relationship?.note ?? ""
}
}
}
@ToolbarContentBuilder
private var toolbarContent: some ToolbarContent {
ToolbarItem(placement: .navigationBarLeading) {
Button("action.cancel") {
dismiss()
}
}
ToolbarItem(placement: .navigationBarTrailing) {
Button {
Task {
await viewModel.save()
await accountDetailViewModel.fetchAccount()
dismiss()
}
} label: {
if viewModel.isSaving {
ProgressView()
} else {
Text("action.save")
}
}
}
}
}

View file

@ -0,0 +1,27 @@
import Network
import SwiftUI
@MainActor
class EditRelationshipNoteViewModel: ObservableObject {
public var note: String = ""
public var relatedAccountId: String?
public var client: Client?
@Published var isSaving: Bool = false
@Published var saveError: Bool = false
init() {}
func save() async {
if relatedAccountId != nil,
client != nil {
isSaving = true
do {
let _ = try await client!.post(endpoint: Accounts.relationshipNote(id: relatedAccountId!, json: RelationshipNoteData(note: note)))
} catch {
isSaving = false
saveError = true
}
}
}
}

View file

@ -34,6 +34,7 @@ public enum Accounts: Endpoint {
case unblock(id: String) case unblock(id: String)
case mute(id: String, json: MuteData) case mute(id: String, json: MuteData)
case unmute(id: String) case unmute(id: String)
case relationshipNote(id: String, json: RelationshipNoteData)
public func path() -> String { public func path() -> String {
switch self { switch self {
@ -79,6 +80,8 @@ public enum Accounts: Endpoint {
return "accounts/\(id)/mute" return "accounts/\(id)/mute"
case let .unmute(id): case let .unmute(id):
return "accounts/\(id)/unmute" return "accounts/\(id)/unmute"
case let .relationshipNote(id, _):
return "accounts/\(id)/note"
} }
} }
@ -143,6 +146,8 @@ public enum Accounts: Endpoint {
switch self { switch self {
case let .mute(_, json): case let .mute(_, json):
return json return json
case let .relationshipNote(_, json):
return json
default: default:
return nil return nil
} }
@ -156,3 +161,11 @@ public struct MuteData: Encodable {
self.duration = duration self.duration = duration
} }
} }
public struct RelationshipNoteData: Encodable {
public let comment: String
public init(note comment: String) {
self.comment = comment
}
}