1+ <!DOCTYPE html>
2+ < html >
3+
4+ < head >
5+ < meta http-equiv ="content-type " content ="text/html; charset=utf-8 " />
6+ < link rel ="stylesheet " href ="./index.css ">
7+ </ head >
8+
9+ < body >
10+ < h2 > Scuttle Shell Browser example</ h2 >
11+ < h1 > Review our product</ h1 >
12+ < p > The #6 BunaB is a quality product meeting and exceeding the highest requirements in
13+ regards to quality and long term user satisfaction.
14+ </ p >
15+ < p >
16+ However, don't just take our word for it, read the following reviews. To guarantee that the
17+ reviews are genuine and from people you can trust we use Scuttlebut so that the reviews are
18+ stored on the decentralized Secure Scuttlebutt network outside our control.
19+ </ p >
20+ < img src ="images/BunaB.jpg " style ="width: 50% " />
21+ < div id ="output ">
22+ < div style ="background-color: yellow; " class ="after_wait ">
23+ This Page needs to access Scuttlebut. Make sure that Scuttle Shell Browser is installed and that "SSB access" is
24+ switched on for this page.
25+ </ div >
26+ </ div >
27+ < script src ="https://cdn.jsdelivr.net/npm/marked/marked.min.js "> </ script >
28+ < script src ="connect-ssb.js "> </ script >
29+ < script type ="module ">
30+ import daysPosts from './source/days-posts.js'
31+ import getName from './async/get-name.js'
32+ import getAvatar from './async/get-avatar.js'
33+
34+ const outElem = document . getElementById ( 'output' )
35+
36+ connectSsb ( ) . then ( server => {
37+ outElem . innerHTML = 'Loading reviews from Scuttlebutt...'
38+ console . time ( 'get posts' )
39+ const item = 'No. 6 BunaB'
40+ const opts = {
41+ limit : 5 ,
42+ reverse : true ,
43+ query : [
44+ {
45+ $filter : {
46+ value : {
47+ content : {
48+ type : 'post' ,
49+ 'channel' : 'reviews' ,
50+ item
51+ }
52+ }
53+ }
54+ } , {
55+ $map : {
56+ author : [ 'value' , 'author' ] ,
57+ timestamp : [ 'value' , 'timestamp' ] ,
58+ text : [ 'value' , 'content' , 'text' ] ,
59+ root : [ 'value' , 'content' , 'root' ] // the root messages of a thread, this is present if this post is a reply to another message
60+ }
61+ }
62+ ]
63+ }
64+ pull (
65+ server . query . read ( opts ) ,
66+ pull . paraMap ( addName , 50 ) , // run up to 50 asynchronous maps in parallel
67+ pull . paraMap ( addAvatar , 50 ) , // run up to 50 asynchronous maps in parallel
68+ pull . collect ( onDone )
69+ )
70+
71+ function addName ( data , cb ) {
72+ console . log ( 'adding name' , data )
73+ getName ( server ) ( data . author , ( err , name ) => {
74+ if ( err ) cb ( err )
75+ else {
76+ data . authorName = name
77+ console . log ( 'added name' , name )
78+ cb ( null , data )
79+ }
80+ } )
81+ }
82+ function addAvatar ( data , cb ) {
83+ getAvatar ( server ) ( data . author , ( err , avatar ) => {
84+ if ( err ) cb ( err )
85+ else {
86+ data . avatar = avatar
87+ console . log ( 'added avatar' , avatar )
88+ cb ( null , data )
89+ }
90+ } )
91+ }
92+
93+ function onDone ( err , data ) {
94+ console . log ( 'finally' )
95+ if ( err ) {
96+ console . error ( 'oh noes' , err )
97+ return
98+ }
99+
100+ outElem . innerHTML = Messages ( data )
101+
102+ addForm ( )
103+
104+ console . log ( `${ data . length } messages` )
105+ console . timeEnd ( 'get posts' )
106+
107+ }
108+
109+
110+ function Messages ( data ) {
111+ return `
112+ <div style="font-family: arial;">
113+ ${ data . map ( Message ) }
114+ </div>
115+ `
116+ }
117+
118+ function Message ( msgData ) {
119+ const { avatar, authorName, timestamp, text, root } = msgData
120+
121+ return `
122+ <div style="margin: 2rem;">
123+ ${ avatar ? Avatar ( avatar ) : '' }
124+ <strong>${ authorName } </strong> - ${ new Date ( timestamp ) . toLocaleString ( ) }
125+ <p>${ text ? window . marked ( text ) : '' } </p>
126+ </div>
127+ `
128+ }
129+
130+ function Avatar ( blobId ) {
131+ if ( ! blobId ) return
132+
133+ const url = `http://localhost:8989/blobs/get/${ blobId } `
134+ // this may be patchbay specific
135+
136+ return `
137+ <img src=${ url } style="width: 2rem; height: 2rem;"/>
138+ `
139+ }
140+
141+ function addForm ( ) {
142+ const form = `
143+ <h2>Publish your own review of ${ item } </h2>
144+ <textarea id="review" style="width: 80%">
145+ # Review of ${ item }
146+
147+ </textarea>
148+ <br/>
149+ <button id="publish">Publish</button>
150+ `
151+ outElem . innerHTML += form
152+ document . getElementById ( 'publish' ) . addEventListener ( 'click' , ( ) => publishReview ( document . getElementById ( 'review' ) . value ) )
153+ }
154+
155+ function publishReview ( review ) {
156+ const text = review + `\n\n---\n\nPublished on ${ window . location } with Scuttle Shell Browser`
157+ server . publish ( {
158+ type : 'post' ,
159+ 'channel' : 'reviews' ,
160+ item,
161+ text
162+ } , function ( err , msg ) {
163+ console . log ( msg ) ;
164+ window . location . reload ( )
165+ } ) ;
166+ }
167+
168+ } )
169+ setTimeout ( ( ) => document . body . classList . add ( 'waited' ) , 1000 )
170+ </ script >
171+ </ body >
172+
173+ </ html >
0 commit comments