gitbay/Discovery/ProfileEdit.swift
64 lines · 2430 bytes
1import Foundation
2
3/// `profile set` — unlike every other filter or edit in the app, `--link`
4/// replaces the whole set rather than appending, so every link the form
5/// wants to keep is sent on every save. The form is always seeded from
6/// the current profile, so every other field is also sent every time,
7/// including empty ones: `--description ""` clears, omitting the flag
8/// would leave the old value alone.
9///
10/// The about text is not here. It is a file in `<owner>/.gitbay`, written
11/// through the file editor like any other file.
12nonisolated struct ProfileEdit: Equatable, Sendable {
13
14 nonisolated struct Link: Equatable, Sendable, Identifiable {
15 var id = UUID()
16 var label: String
17 var url: String
18 }
19
20 var description: String
21 var website: String
22 var links: [Link]
23
24 init(description: String = "", website: String = "", links: [Link] = []) {
25 self.description = description
26 self.website = website
27 self.links = links
28 }
29
30 init(from profile: ProfileViewModel.Profile) {
31 description = profile.description ?? ""
32 website = profile.website ?? ""
33 links = (profile.links ?? []).map { Link(label: $0.label ?? "", url: $0.url) }
34 }
35
36 /// At most 5 links and every link needs a URL — the server enforces
37 /// both, but the form should not let a save reach it that way. A
38 /// label may not contain `|` either: the server splits a link on its
39 /// first pipe, so a label carrying one would silently corrupt the URL
40 /// rather than be rejected.
41 var validationError: String? {
42 if links.count > 5 { return "At most 5 links." }
43 if links.contains(where: { $0.url.trimmingCharacters(in: .whitespaces).isEmpty }) {
44 return "A link needs a URL."
45 }
46 if links.contains(where: { $0.label.contains("|") }) {
47 return "A link label can't contain \"|\" — that's what separates it from the URL."
48 }
49 return nil
50 }
51
52 func flags() -> [String] {
53 var flags = ["--description", description, "--website", website]
54 if links.isEmpty {
55 flags += ["--link", ""]
56 } else {
57 for link in links {
58 let label = link.label.trimmingCharacters(in: .whitespaces)
59 flags += ["--link", label.isEmpty ? link.url : "\(label)|\(link.url)"]
60 }
61 }
62 return flags
63 }
64}