all repos — underbbs @ 9dc27a4b9a016a92b6ab8f0041e3c5319e147913

decentralized social media client

ts/settings-element.ts (raw)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
import util from "./util"
import websocket from "./websocket"

var $ = util.$
var _ = util._

export class SettingsElement extends HTMLElement {
  static observedAttributes = [ "data-adapters" ]
  
  private _adapters: string[] = [];
  
  constructor() {
    super();
  }
  
  connectedCallback() {
    this.attributeChangedCallback();
  }
  
  attributeChangedCallback() {
    this._adapters = this.getAttribute("data-adapters")?.split(",") ?? [];
    this.showSettings(this)();
  }

  showSettings(self: SettingsElement): ()=>void {
    return ()=>{
    let html = "";
    html += "<button id='settings_adapter_create_btn'>New</button>";
    html += self._adapters.reduce((self: string, a: string) => {
      self += `<li><a id='settings_adapter_edit_${a}' href='#editadapter'>${a}</a></li>`
      return self;
    }, "<ul id='settings_adapterlist'>");
    html += "</ul>";
    html += "<button id='settings_connect_btn'>connect</button>";
    self.innerHTML = html;
    
    let create = $("settings_adapter_create_btn");
    if (create) {
      create.addEventListener("click", self.showCreateAdapter(self), false);
    }
    for (let a of this._adapters) {
      let edit = $(`settings_adapter_edit_${a}`);
      if (edit) {
        edit.addEventListener("click", self.showEditAdapterFunc(a, self), false);
      }
    }
    let connect = $("settings_connect_btn");
    if (connect) {
      connect.addEventListener("click", websocket.connect, false);
    }
    }
  }
  
  showCreateAdapter(self: SettingsElement): ()=>void {
  return ()=>{
    // dropdown for protocol
    let html = "<select id='settings_newadapter_protocolselect'>";
    html += [ "nostr", "mastodon", "misskey" ].reduce((self, p)=>{
      self += `<option value='${p}'>${p}</option>`;
      return self;
    }, "");
    html += "</select>";
    
    // nostr is the first protocol, so show its options by default
    html += "<div id='settings_newadapter_protocoloptions'>";
    html += "  <label>nickname<input id='settings_newadapter_nickname'/></label>";
    html += "  <label>privkey<input id='settings_newadapter_nostr_privkey'/></label>";
    html += "  <label>default relays<input id='settings_newadapter_nostr_default_relays'/></label>";
    html += "</div>";
    
    html += "<button id='settings_adapter_create_save_btn'>add</button>";
    html += "<button id='settings_adapter_create_back_btn'>back</button>";
  
    self.innerHTML = html;
    
    let protocolSelect = $("settings_newadapter_protocolselect");
    if (protocolSelect) {
      protocolSelect.addEventListener("change", self.fillAdapterProtocolOptions, false);
    }
    
    let save = $("settings_adapter_create_save_btn");
    if (save) {
      save.addEventListener("click", self.saveAdapter(self), false);
    }
    
    let back = $("settings_adapter_create_back_btn");
    if (back) {
      back.addEventListener("click", self.showSettings(self), false);
    }
    }
  }
  
  saveAdapter(self: SettingsElement): ()=>void {
    return ()=>{
    let adapterdata: any = {};
    // get selected adapter protocol
    const proto = $("settings_newadapter_protocolselect") as HTMLSelectElement;
   
    const nickname = ($("settings_newadapter_nickname") as HTMLInputElement)?.value ?? "" ;
  
    // switch protocol
    switch (proto.options[proto.selectedIndex].value) {
      case "nostr":
        const privkey = ($("settings_newadapter_nostr_privkey") as HTMLInputElement)?.value ?? "";
        const relays = ($("settings_newadapter_nostr_default_relays") as HTMLInputElement)?.value ?? "";
        adapterdata = { nickname: nickname, protocol: "nostr", privkey: privkey, relays: relays.split(",").map(r=>r.trim()) };
        break;
      case "mastodon":
      case "misskey":
        const server = ($("settings_newadapter_masto_server") as HTMLInputElement)?.value ?? "";
        const apiKey = ($("settings_newadapter_masto_apikey") as HTMLInputElement)?.value ?? "";
        adapterdata = { nickname: nickname, protocol: proto.options[proto.selectedIndex].value, server: server, apiKey: apiKey };
        break;
    }
    const settings = _("settings");
    if (settings) {
      if (!settings.adapters) {
        settings.adapters = [];
      }
      settings.adapters.push(adapterdata);
      self._adapters.push(adapterdata.nickname);
      localStorage.setItem("settings", JSON.stringify(settings));
      
      self.setAttribute("adapters", self._adapters.join(","));
    }
    }
  }
  
  fillAdapterProtocolOptions() { 
    const proto = $("settings_newadapter_protocolselect") as HTMLSelectElement;
  
    let html = "";
  
    switch(proto?.options[proto.selectedIndex].value) {
      case "nostr":
        html += "  <label>nickname<input id='settings_newadapter_nickname'/></label>";
        html += "  <label>privkey<input id='settings_newadapter_nostr_privkey'/></label>";
        html += "  <label>default relays<input id='settings_newadapter_nostr_default_relays'/></label>";
        break;
      case "mastodon":
      case "misskey":
        html += "  <label>nickname<input id='settings_newadapter_nickname'/></label>";
        html += "  <label>server<input id='settings_newadapter_masto_server'/></label>";
        html += "  <label>API key<input id='settings_newadapter_masto_apikey'/></label>";
        break;
    }
  
    const div = $("settings_newadapter_protocoloptions");
    if (div) {
      div.innerHTML = html;
    }
  }

  
  showEditAdapterFunc(adapter: string, self: SettingsElement): ()=>void {
    // this UI has to be able to edit an exiting adapter or delete it
    return ()=>{};
  }
}