oficina / sheets Public

Clone
git clone https://amadan.net/oficina/sheets

Plain git — no account needed to clone.

Download

Download this file

1import SwiftUI
2
3struct SharedMember: Decodable {
4 let ID: UInt64
5 let Address: String
6}
7struct SharedPerson: Decodable, Identifiable {
8 let Member: SharedMember
9 let Role: String
10 var id: UInt64 { Member.ID }
11}
12struct SharedLink: Decodable, Identifiable {
13 let ID: UInt64
14 let Role: String
15 var id: UInt64 { self.ID }
16}
17struct SharingPage: Decodable {
18 let People: [SharedPerson]?
19 let Links: [SharedLink]?
20 let NewLink: String
21 let Notice: String
22}
23struct SheetSharing: View {
24 @Bindable var model: SheetModel
25 @State private var sharing: SharingPage?
26 @State private var address = ""
27 @State private var role = "viewer"
28 @State private var linkRole = "viewer"
29 var body: some View {
30 Group {
31 Text("People you share with can see your team’s name.").font(.callout)
32 TextField("Email address", text: $address)
33 Picker("Access", selection: $role) {
34 ForEach(["viewer", "commenter", "editor", "owner"], id: \.self) {
35 Text($0.capitalized).tag($0)
36 }
37 }
38 Button("Grant access") {
39 Task {
40 await model.command("/share", ["address": address, "role": role])
41 await load()
42 }
43 }.disabled(address.isEmpty)
44 ForEach(sharing?.People ?? []) { person in
45 LabeledContent(person.Member.Address, value: person.Role)
46 Button("Remove access", role: .destructive) {
47 Task {
48 await model.command("/share/revoke", ["member": String(person.id)])
49 await load()
50 }
51 }
52 }
53 Picker("Link access", selection: $linkRole) {
54 Text("Viewer").tag("viewer")
55 Text("Commenter").tag("commenter")
56 }
57 Button("Create link") {
58 Task {
59 do {
60 sharing = try await model.form(model.base + "/share/link", ["role": linkRole])
61 } catch { model.error = error.localizedDescription }
62 }
63 }
64 if let sharing, !sharing.NewLink.isEmpty {
65 Text(sharing.NewLink).textSelection(.enabled)
66 ShareLink(item: sharing.NewLink)
67 Text("Copy this link now. It is shown only once.").font(.caption)
68 }
69 ForEach(sharing?.Links ?? []) { link in
70 Button("Revoke \(link.Role) link \(link.ID)", role: .destructive) {
71 Task {
72 await model.command("/share/link/revoke", ["link": String(link.ID)])
73 await load()
74 }
75 }
76 }
77 Text(model.notice).font(.callout)
78 }.task { await load() }
79 }
80 private func load() async {
81 do { sharing = try await model.client.request(model.base + "/share") } catch {
82 model.error = error.localizedDescription
83 }
84 }
85}
86