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.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
"conversations.action.delete" = "Выдаліць";
"conversations.action.mark-read" = "Адзначыць як прачытанае";

View file

@ -262,6 +262,12 @@
"account.joined" = "S'ha unit";
"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
"conversations.action.delete" = "Elimina";
"conversations.action.mark-read" = "Marca com a llegit";

View file

@ -264,6 +264,12 @@
"account.action.logout" = "Abmelden";
"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
"conversations.action.delete" = "Löschen";
"conversations.action.mark-read" = "Als gelesen markieren";

View file

@ -265,6 +265,12 @@
"account.joined" = "Joined";
"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
"conversations.action.delete" = "Delete";
"conversations.action.mark-read" = "Mark as read";

View file

@ -264,6 +264,12 @@
"account.joined" = "Joined";
"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
"conversations.action.delete" = "Delete";
"conversations.action.mark-read" = "Mark as read";

View file

@ -264,6 +264,12 @@
"account.joined" = "Se unió el";
"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
"conversations.action.delete" = "Borrar";
"conversations.action.mark-read" = "Marcar como leído";

View file

@ -264,6 +264,12 @@
"account.action.logout" = "Amaitu saioa";
"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
"conversations.action.delete" = "Ezabatu";
"conversations.action.mark-read" = "Markatu irakurritzat";

View file

@ -263,6 +263,12 @@
"account.joined" = "Inscrit";
"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
"conversations.action.delete" = "Supprimer";
"conversations.action.mark-read" = "Marquer comme lu";

View file

@ -264,6 +264,12 @@
"account.action.logout" = "Esci dall'account";
"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
"conversations.action.delete" = "Cancella";
"conversations.action.mark-read" = "Segna come letto";

View file

@ -263,6 +263,12 @@
"account.joined" = "登録日";
"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
"conversations.action.delete" = "削除";
"conversations.action.mark-read" = "既読にする";

View file

@ -264,6 +264,12 @@
"account.joined" = "가입";
"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
"conversations.action.delete" = "삭제";
"conversations.action.mark-read" = "읽음으로 표시";

View file

@ -263,6 +263,12 @@
"account.joined" = "Ble med";
"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
"conversations.action.delete" = "Slett";
"conversations.action.mark-read" = "Merk som lest";

View file

@ -261,6 +261,12 @@
"account.action.logout" = "Log uit";
"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
"conversations.action.delete" = "Verwijder";
"conversations.action.mark-read" = "Markeer als gelezen";

View file

@ -261,6 +261,12 @@
"account.joined" = "Dołączył(a)";
"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
"conversations.action.delete" = "Usuń";
"conversations.action.mark-read" = "Oznacz jako przeczytany";

View file

@ -263,6 +263,12 @@
"account.joined" = "Entrou em";
"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
"conversations.action.delete" = "Excluir";
"conversations.action.mark-read" = "Marcar como lida";

View file

@ -259,6 +259,12 @@
"account.joined" = "Katılındı";
"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
"conversations.action.delete" = "Sil";
"conversations.action.mark-read" = "Okundu olarak işaretle";

View file

@ -264,6 +264,12 @@
"account.action.logout" = "退出登录";
"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
"conversations.action.delete" = "删除";
"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)
.font(.scaledBody)
.padding(.top, 8)
@ -193,6 +199,23 @@ struct AccountDetailHeaderView: View {
.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 {

View file

@ -26,6 +26,7 @@ public struct AccountDetailView: View {
@State private var isEditingAccount: 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.
public init(accountId: String) {
@ -126,6 +127,9 @@ public struct AccountDetailView: View {
.sheet(isPresented: $isEditingFilters, content: {
FiltersListView()
})
.sheet(isPresented: $isEditingRelationshipNote, content: {
EditRelationshipNoteView(accountDetailViewModel: viewModel)
})
.edgesIgnoringSafeArea(.top)
.navigationBarTitleDisplayMode(.inline)
.toolbar {
@ -487,6 +491,12 @@ public struct AccountDetailView: View {
}
Divider()
Button {
isEditingRelationshipNote = true
} label: {
Label("account.relation.note.edit", systemImage: "pencil")
}
}
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 mute(id: String, json: MuteData)
case unmute(id: String)
case relationshipNote(id: String, json: RelationshipNoteData)
public func path() -> String {
switch self {
@ -79,6 +80,8 @@ public enum Accounts: Endpoint {
return "accounts/\(id)/mute"
case let .unmute(id):
return "accounts/\(id)/unmute"
case let .relationshipNote(id, _):
return "accounts/\(id)/note"
}
}
@ -143,6 +146,8 @@ public enum Accounts: Endpoint {
switch self {
case let .mute(_, json):
return json
case let .relationshipNote(_, json):
return json
default:
return nil
}
@ -156,3 +161,11 @@ public struct MuteData: Encodable {
self.duration = duration
}
}
public struct RelationshipNoteData: Encodable {
public let comment: String
public init(note comment: String) {
self.comment = comment
}
}