git ssb

16+

Dominic / patchbay



Tree: 53a40a01e1a3a5de5ac78d70f8a0318f38ae0fcb

Files: 53a40a01e1a3a5de5ac78d70f8a0318f38ae0fcb / modules_basic / avatar / edit.js

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

Built with git-ssb-web