git ssb

16+

Dominic / patchbay



Tree: 8dfd53f6b3b313f0e6bf9db8230c208c1f91937c

Files: 8dfd53f6b3b313f0e6bf9db8230c208c1f91937c / modules_basic / avatar / edit.js

5668 bytesRaw
1'use strict'
2const fs = require('fs')
3const dataurl = require('dataurl-')
4const hyperfile = require('hyperfile')
5const hypercrop = require('hypercrop')
6const hyperlightbox = require('hyperlightbox')
7const h = require('../../h')
8const {
9 Value, Array: MutantArray, Dict: MutantObject, Struct,
10 map, computed, when, dictToCollection
11} = require('@mmckegg/mutant')
12const pull = require('pull-stream')
13const getAvatar = require('ssb-avatar')
14const ref = require('ssb-ref')
15const visualize = require('visualize-buffer')
16const self_id = require('../../keys').id
17
18function crop (d, cb) {
19 var canvas = hypercrop(h('img', {src: d}))
20
21 return h('div.column.avatar_pic', [
22 canvas,
23 //canvas.selection,
24 h('div.row.avatar_pic__controls', [
25 h('button', {'ev-click': () => cb(null, canvas.selection.toDataURL()) }, 'okay'),
26 h('button', {'ev-click': () => cb(new Error('canceled')) }, 'cancel')
27 ])
28 ])
29}
30
31exports.needs = {
32 message_confirm: 'first',
33 sbot_blobs_add: 'first',
34 blob_url: 'first',
35 sbot_links: 'first',
36 avatar_name: 'first'
37}
38
39exports.gives = {
40 avatar_edit: true,
41 mcss: true
42}
43
44exports.create = function (api) {
45 return {
46 avatar_edit,
47 mcss: () => fs.readFileSync(__filename.replace(/js$/, 'mcss'), 'utf8')
48 }
49
50 function avatar_edit (id) {
51
52 var avatar = Struct({
53 original: Value(visualize(new Buffer(id.substring(1), 'base64'), 256).src),
54 new: MutantObject()
55 })
56
57 getAvatar({links: api.sbot_links}, self_id, id, (err, _avatar) => {
58 if (err) return console.error(err)
59 //don't show user has already selected an avatar.
60 if(ref.isBlob(_avatar.image))
61 avatar.original.set(api.blob_url(_avatar.image))
62 })
63
64 var name = Struct({
65 original: Value(api.avatar_name(id)),
66 new: Value()
67 })
68
69 var images = MutantArray()
70 pull(
71 api.sbot_links({dest: id, rel: 'about', values: true}),
72 pull.map(e => e.value.content.image),
73 pull.filter(e => e && 'string' == typeof e.link),
74 pull.unique('link'),
75 pull.drain(image => images.push(image) )
76 )
77
78 var namesRecord = MutantObject()
79 // TODO constrain query to one name per peer?
80 pull(
81 api.sbot_links({dest: id, rel: 'about', values: true}),
82 pull.map(e => e.value.content.name),
83 pull.filter(Boolean),
84 pull.drain(name => {
85 var n = namesRecord.get(name) || 0
86 namesRecord.put(name, n+1)
87 })
88 )
89 var names = dictToCollection(namesRecord)
90
91 var lb = hyperlightbox()
92
93 // TODO load this in, make this editable
94 var description = ''
95
96 var isPossibleUpdate = computed([name.new, avatar.new], (name, avatar) => {
97 return name || avatar.link
98 })
99
100 var avatarSrc = computed([avatar], avatar => {
101 if (avatar.new.link) return api.blob_url(avatar.new.link)
102 else return avatar.original
103 })
104
105 var displayedName = computed([name], name => {
106 if (name.new) return '@'+name.new
107 else return name.original
108 })
109
110 return h('ProfileEdit', [
111 h('section.lightbox', lb),
112 h('section.avatar', [
113 h('section', [
114 h('img', { src: avatarSrc }),
115 ]),
116 h('footer', displayedName),
117 ]),
118 h('section.description', description),
119 h('section.aliases', [
120 h('header', 'Aliases'),
121 h('section.avatars', [
122 h('header', 'Avatars'),
123 map(images, image => h('img', {
124 'src': api.blob_url(image),
125 'ev-click': () => avatar.new.set(image)
126 })),
127 h('div.file-upload', [
128 hyperfile.asDataURL(dataUrlCallback)
129 ])
130 ]),
131 h('section.names', [
132 h('header', 'Names'),
133 h('section', [
134 map(names, n => h('div', { 'ev-click': () => name.new.set(n.key()) }, [
135 h('div.name', n.key),
136 h('div.count', n.value)
137 ])),
138 h('input', {
139 placeholder: ' + another name',
140 'ev-keyup': e => name.new.set(e.target.value)
141 })
142 ])
143 ]),
144 when(isPossibleUpdate, h('section.action', [
145 h('button.cancel', { 'ev-click': clearNewSelections }, 'cancel'),
146 h('button.confirm', { 'ev-click': handleUpdateClick }, 'confirm changes')
147 ]))
148 ])
149 ])
150
151 function dataUrlCallback (data) {
152 var el = crop(data, (err, data) => {
153 if(data) {
154 var _data = dataurl.parse(data)
155 pull(
156 pull.once(_data.data),
157 api.sbot_blobs_add((err, hash) => {
158 //TODO. Alerts are EVIL.
159 //I use them only in a moment of weakness.
160
161 if(err) return alert(err.stack)
162 avatar.new.set({
163 link: hash,
164 size: _data.data.length,
165 type: _data.mimetype,
166 width: 512,
167 height: 512
168 })
169 })
170 )
171 }
172 lb.close()
173 })
174 lb.show(el)
175 }
176
177 function clearNewSelections () {
178 name.new.set(null)
179 avatar.new.set({})
180 }
181
182 function handleUpdateClick () {
183 const newName = name.new()
184 const newAvatar = avatar.new()
185
186 const msg = {
187 type: 'about',
188 about: id
189 }
190
191 if (newName) msg.name = newName
192 if (newAvatar.link) msg.image = newAvatar
193
194 api.message_confirm(msg, (err, data) => {
195 if (err) return console.error(err)
196
197 if (newName) name.original.set('@'+newName)
198 if (newAvatar.link) avatar.original.set(api.blob_url(newAvatar.link))
199
200 clearNewSelections()
201
202 // TODO - update aliases displayed
203 })
204 }
205 }
206
207}
208
209

Built with git-ssb-web