Skip to content

Commit e8e8b53

Browse files
committed
before heavy refactoring
1 parent 83eef22 commit e8e8b53

20 files changed

+5161
-1858
lines changed

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ To run the minimal UI use:
3535
$ npm run ui
3636
```
3737

38+
> The minimal UI is not meant for general use. It is there just to aid development.
39+
>
40+
> Remember to replace the _token_ in `./minimal-ui/index.html` with a valid token for your instalation.
41+
3842

3943
## Setup inside Patchfox
4044

bun.lockb

281 KB
Binary file not shown.

minimal-ui/app.js

+263
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
const root = document.body
2+
3+
let server = "http://localhost:3000/jsonrpc"
4+
let token = "85b2ae37-0be4-4faa-b1f0-d02189a31cfa" // replace with your token.
5+
let identity = "@fu9wRz7+UwjDcvW6TZrvbNDT0cEPgWBh/ZZq5dKGEyY=.ed25519"
6+
7+
function md(content) {
8+
let opts = {
9+
html: true,
10+
linkify: true,
11+
typographer: true
12+
}
13+
let markdown = window.markdownit(opts)
14+
let result = markdown.render(content)
15+
16+
function replaceMsgID(match, id, offset, string) {
17+
let eid = encodeURIComponent(`%${id}`);
18+
19+
return `<a class="thread-link" href="#!/thread/${eid}`;
20+
}
21+
22+
function replaceChannel(match, id, offset, string) {
23+
let eid = encodeURIComponent(id);
24+
25+
return `<a class="channel-link" href="#!/channel/${eid}`;
26+
}
27+
28+
function replaceFeedID(match, id, offset, string) {
29+
let eid = encodeURIComponent(`@${id}`);
30+
return (
31+
'<a class="profile-link" href="#!/profile/' + eid
32+
);
33+
}
34+
35+
function replaceImageLinks(match, id, offset, string) {
36+
return (
37+
`<a class="image-link" target="_blank" href="http://127.0.0.1:8989/blobs/get/` + encodeURIComponent(id) + `"`
38+
);
39+
}
40+
41+
function replaceImages(match, id, offset, string) {
42+
return (
43+
`<img class="is-image-from-blob" src="http://127.0.0.1:8989/blobs/get/&` + (id) + `" `
44+
);
45+
}
46+
47+
function replaceVideos(match, id, offset, string) {
48+
return (
49+
`<video controls class="is-video-from-blob" src="http://127.0.0.1:8989/blobs/get/&` + encodeURIComponent(id) + `"`
50+
);
51+
}
52+
53+
function replaceAudios(match, id, offset, string) {
54+
return (
55+
`<audio controls class="is-audio-from-blob" src="http://127.0.0.1:8989/blobs/get/&` + encodeURIComponent(id)+ `"`
56+
);
57+
}
58+
59+
result = result
60+
.replace(/<pre>/gi, '<pre class="code">')
61+
.replace(/<a href="#([^"]*)/gi, replaceChannel)
62+
.replace(/<a href="@([^"]*)/gi, replaceFeedID)
63+
.replace(/target="_blank"/gi, "")
64+
.replace(/<a href="%([^"]*)/gi, replaceMsgID)
65+
.replace(/<img src="&([^"]*)/gi, replaceImages)
66+
.replace(/<video controls src="&([^"]*)/gi, replaceVideos)
67+
.replace(/<audio controls src="&([^"]*)/gi, replaceAudios)
68+
.replace(/<a href="&([^"]*)/gi, replaceImageLinks);
69+
70+
return result
71+
}
72+
73+
async function callMethod(method, params) {
74+
const obj = {
75+
jsonrpc: "2.0",
76+
method: method,
77+
id: "1",
78+
params: [token, params],
79+
}
80+
81+
const response = await fetch(server, {
82+
method: "POST", // *GET, POST, PUT, DELETE, etc.
83+
mode: "cors", // no-cors, *cors, same-origin
84+
cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
85+
credentials: "same-origin", // include, *same-origin, omit
86+
headers: {
87+
"Content-Type": "application/json",
88+
// 'Content-Type': 'application/x-www-form-urlencoded',
89+
},
90+
redirect: "follow", // manual, *follow, error
91+
referrerPolicy: "no-referrer", // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
92+
body: JSON.stringify(obj), // body data type must match "Content-Type" header
93+
})
94+
return response.json() // parses JSON response into native JavaScript objects
95+
}
96+
97+
const makeInput = ({ type = "text", id, label, value, events }) => {
98+
return m("label", { for: id }, [`${label}: `, m("input", { type, value, id, ...events })])
99+
}
100+
101+
const header = {
102+
view: vnode => {
103+
return m("header", [
104+
m("h3", "Minimal Debugging UI"),
105+
m("section.tool-bar", [
106+
makeInput({
107+
id: "server-address",
108+
label: "RPC Server",
109+
value: server,
110+
events: {
111+
oninput: e => {
112+
server = e.target.value
113+
console.log(server)
114+
},
115+
},
116+
}),
117+
makeInput({
118+
id: "text",
119+
value: token,
120+
label: "Token",
121+
}),
122+
makeInput({
123+
id: "identity",
124+
label: "identity",
125+
value: identity,
126+
events: {
127+
oninput: e => {
128+
identity = e.target.value
129+
console.log(identity)
130+
},
131+
},
132+
}),
133+
m("hr", {"aria-orientation": "vertical"}),
134+
m(m.route.Link, {selector: "a.<button>", href: "/new"}, "new post"),
135+
m(m.route.Link, {selector: "a.<button>", href: "/"}, "public"),
136+
m(m.route.Link, {selector: "a.<button>", href: "/private"}, "private"),
137+
m(m.route.Link, {selector: "a.<button>", href: "/mentions"}, "mentions"),
138+
m(m.route.Link, {selector: "a.<button>", href: "/profile"}, "profile"),
139+
m("hr", {"aria-orientation": "vertical"}),
140+
m(m.route.Link, {selector: "a.<button>", href: "/rpc"}, "raw RPC"),
141+
142+
]),
143+
])
144+
},
145+
}
146+
147+
const timeline = {
148+
fetchTimeline: vnode => {
149+
callMethod("ssb.timeline.public", { identity: "@fu9wRz7+UwjDcvW6TZrvbNDT0cEPgWBh/ZZq5dKGEyY=.ed25519" })
150+
.then(data => {
151+
console.dir(data)
152+
vnode.state.state = "loaded"
153+
vnode.state.messages = data.result
154+
m.redraw()
155+
})
156+
.catch(err => {
157+
console.log("error", err)
158+
vnode.state.state = "error"
159+
vnode.state.messages = []
160+
m.redraw()
161+
})
162+
},
163+
oninit: function(vnode) {
164+
vnode.state.messages = []
165+
vnode.state.state = "loading"
166+
this.fetchTimeline(vnode)
167+
},
168+
view: vnode => {
169+
let r
170+
switch (vnode.state.state) {
171+
case "loading":
172+
r = m(".box.plain", m("strong", "Loading messages..."))
173+
174+
case "error":
175+
r = m(".box.bad", m("strong", `an error has happened, check the console`))
176+
case "loaded":
177+
r = [
178+
vnode.state.messages.map(data => {
179+
let msg = data.messages[0]
180+
let content
181+
182+
if (msg.text) {
183+
content = m.trust(md(msg.text))
184+
} else {
185+
content = m("pre", m("code", JSON.stringify(msg,null, " ")))
186+
}
187+
return m(".box.info", [m("strong.block.titlebar", `from: ${msg.author}`), content])
188+
}),
189+
]
190+
}
191+
return [m(header), m("main", r)]
192+
},
193+
}
194+
195+
const rpc = {
196+
view: vnode => {
197+
let result = vnode.state.result ?? {}
198+
let content = vnode.state.content ?? {}
199+
let method = vnode.state.method ?? "ping"
200+
201+
function callRPC() {
202+
callMethod(method, { identity, ...content })
203+
.then(data => {
204+
console.dir(data)
205+
vnode.state.state = "ok"
206+
vnode.state.result = data
207+
m.redraw()
208+
})
209+
.catch(err => {
210+
console.log("error", err)
211+
vnode.state.state = "error"
212+
vnode.state.result = err
213+
m.redraw()
214+
})
215+
}
216+
217+
218+
let ui = m("main", [
219+
m("form.table.rows", [
220+
m("p",[
221+
m("label", {
222+
for: "method"
223+
},`method`),
224+
m("input", {
225+
type: "text",
226+
style: {width: "100%"},
227+
value: method,
228+
id: "method",
229+
onchange: e => vnode.state.method = e.target.value
230+
})
231+
]),
232+
m("p",[
233+
m("label", {
234+
for: "payload"
235+
},"json payload"),
236+
m("textarea", {
237+
style: {width: "100%"},
238+
rows: 10,
239+
value: JSON.stringify(content,null," "),
240+
id: "payload",
241+
onchange: e => vnode.state.content = JSON.parse(e.target.value)
242+
})
243+
]),
244+
m("p", m("button", {
245+
onclick: e => {
246+
callRPC()
247+
}
248+
}, "Send request")),
249+
]),
250+
m(".box.info", [
251+
m("strong.block.titlebar", `Result ${new Date()}`),
252+
m("code", m("pre", JSON.stringify(result,true," ")))
253+
])
254+
])
255+
256+
return [m(header), ui]
257+
}
258+
}
259+
260+
m.route(root, "/", {
261+
"/": timeline,
262+
"/rpc": rpc
263+
})

minimal-ui/index.html

+5-65
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,12 @@
11
<html>
22
<head>
33
<title>Minimal Debugging UI</title>
4-
<link rel="stylesheet" href="https://the.missing.style/v1.0.6/missing.min.css">
5-
6-
<script src="https://unpkg.com/mithril/mithril.js"></script>
4+
<link rel="stylesheet" href="missing.min.css">
5+
<script src="mithril.js"></script>
6+
<script src="https://cdnjs.cloudflare.com/ajax/libs/markdown-it/13.0.1/markdown-it.js" integrity="sha512-yucm4wm2T2mZNzxtKGWQLTsMAGI+KNFRLsfFDNO9SqdMn9eauAORCybt1UnXRAAlrxJoFpdLSR9lhfuCKx22kQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
7+
<script defer src="app.js"></script>
78
</head>
89
<body>
9-
<script>
10-
var root = document.body
11-
12-
const server = "http://localhost:3000/jsonrpc"
13-
const token = "85b2ae37-0be4-4faa-b1f0-d02189a31cfa"
14-
15-
async function callMethod(method, params) {
16-
const obj = {
17-
jsonrpc: "2.0",
18-
method: method,
19-
id: "1",
20-
params: [token, params],
21-
}
22-
23-
const response = await fetch(server, {
24-
method: "POST", // *GET, POST, PUT, DELETE, etc.
25-
mode: "cors", // no-cors, *cors, same-origin
26-
cache: "no-cache", // *default, no-cache, reload, force-cache, only-if-cached
27-
credentials: "same-origin", // include, *same-origin, omit
28-
headers: {
29-
"Content-Type": "application/json",
30-
// 'Content-Type': 'application/x-www-form-urlencoded',
31-
},
32-
redirect: "follow", // manual, *follow, error
33-
referrerPolicy: "no-referrer", // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url
34-
body: JSON.stringify(obj), // body data type must match "Content-Type" header
35-
})
36-
return response.json() // parses JSON response into native JavaScript objects
37-
}
38-
39-
callMethod("examples.getStateName", [12]).then(data => {
40-
console.log(data) // JSON data parsed by `data.json()` call
41-
})
42-
43-
callMethod("ssb.post", {
44-
identity: "@fu9wRz7+UwjDcvW6TZrvbNDT0cEPgWBh/ZZq5dKGEyY=.ed25519",
45-
content: {
46-
text: `Now it will work`,
47-
root: "%sUJg+n7aIiDXPWQPrEMi4Tg82KhyF4gpI0TaQt0Z8Vc=.sha256"
48-
}
49-
})
50-
.then(data => {
51-
console.log(data)
52-
})
53-
.catch(err => {
54-
console.log("error", err)
55-
})
56-
57-
// callMethod("ssb.timeline.public", {identity: "@fu9wRz7+UwjDcvW6TZrvbNDT0cEPgWBh/ZZq5dKGEyY=.ed25519"})
58-
// .then(data => {
59-
// console.log(data)
60-
// })
61-
// .catch(err => {
62-
// console.log("error", err)
63-
// })
64-
65-
66-
/* Live reload */
67-
document.write('<script src="http://' + (location.host || 'localhost').split(':')[0] +
68-
':35729/livereload.js?snipver=1"></' + 'script>')
69-
</script>
70-
10+
7111
</body>
7212
</html>

minimal-ui/missing.min.css

+126
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)