Skip to content

Commit 9f33b68

Browse files
author
Tim Berners-Lee
committed
Try JS wrapped datauri SVG icon
1 parent 0937fcf commit 9f33b68

5 files changed

Lines changed: 102 additions & 38 deletions

File tree

src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ const UI = {
4949
icons: require('./iconBase'),
5050
log: require('./log'),
5151
matrix: require('./matrix'),
52+
media: require('./media-capture'),
5253
messageArea: require('./messageArea'),
5354
infiniteMessageArea: require('./infiniteMessageArea'),
5455
pad: require('./pad'),

src/infiniteMessageArea.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ var UI = {
1010
icons: require('./iconBase'),
1111
log: require('./log'),
1212
ns: require('./ns'),
13+
media: require('./media-capture'),
1314
pad: require('./pad'),
1415
rdf: require('rdflib'),
1516
store: require('./store'),
@@ -200,10 +201,12 @@ module.exports = function (dom, kb, subject, options) {
200201
imageDoc = kb.sym(chatDocument.dir().uri + 'Image_' + Date.now() + '.png')
201202
return imageDoc
202203
}
203-
function tookPicture () {
204-
sendMessage(imageDoc.uri)
204+
function tookPicture (imageDoc) {
205+
if (imageDoc) {
206+
sendMessage(imageDoc.uri)
207+
}
205208
}
206-
rhs.appendChild(UI.media.cameraButton(dom, kb, getImageDoc, tookPicture))
209+
middle.appendChild(UI.media.cameraButton(dom, kb, getImageDoc, tookPicture))
207210

208211
UI.pad.recordParticipation(subject, subject.doc()) // participation =
209212
} // turn on inpuut
@@ -336,7 +339,7 @@ module.exports = function (dom, kb, subject, options) {
336339

337340
var td2 = tr.appendChild(dom.createElement('td'))
338341
let text = content.value.trim()
339-
let isURI = (/^https?:\/\[^ <>]*$/i).test(text)
342+
let isURI = (/^https?:\/[^ <>]*$/i).test(text)
340343
let para = null
341344
if (isURI) {
342345
var isImage = (/\.(gif|jpg|jpeg|tiff|png|svg)$/i).test(text) // @@ Should use content-type not URI

src/media-capture.js

Lines changed: 87 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@
77
// Workflow:
88
// The HTML5 functionality (on mobille) is to prompt for either
99
// a realtime camera capture , OR a selection from images already ont the device
10-
// (eg camera roll). The solid alternative is to either take a phtoto
10+
// (eg camera roll).
11+
//
12+
// The solid alternative is to either take a phtoto
1113
// or access cemra roll (etc) OR to access solid cloud storage of favorite photo almbums.
1214
// (Especially latest taken ones)
1315
//
14-
/* global alert confirm */
16+
/* global alert */
1517

1618
/** @module mediaCapture */
1719

@@ -30,72 +32,125 @@ var UI = {
3032
widgets: require('./widgets')
3133
}
3234

35+
const cameraIcon = require('./noun_Camera_1618446_000000') // load it in JS
36+
// const cameraIcon = UI.icons.iconBase + 'noun_479395.svg' // Get it from github
37+
38+
const canvasWidth = '640'
39+
const canvasHeight = '480'
40+
41+
const controlStyle = `border-radius: 0.5em; margin: 0.8em; width: ${canvasWidth}; height:${canvasHeight};`
42+
// const controlStyle = 'border-radius: 0.5em; margin: 0.8em; width: 320; height:240;'
43+
const contentType = 'image/png'
44+
3345
/** A control to capture a picture using camera
3446
* @param {Docuemnt} dom - The Document object
3547
* @param {IndexedForumla} store - The quadstore to store data in
3648
* @param {NamedNode} getImageDoc() - NN of the image file to be created
3749
* @param {function} doneCallback - Called when a picture has been taken
3850
*/
39-
function cameraCaptureControl (dom, store, getImageDoc, doneCallback) {
51+
module.exports.cameraCaptureControl = function cameraCaptureControl (dom, store, getImageDoc, doneCallback) {
4052
const div = dom.createElement('div')
41-
const player = div.appendChild(dom.createElement('video'))
42-
const controlStyle = 'border-radius: 0.5em; margin: 0.8em; width: 320; height:240;'
43-
const contentType = 'image/png'
44-
// player.setAttribute('controls', '1')
45-
player.setAttribute('autoplay', '1')
46-
const button = div.appendChild(dom.createElement('button'))
47-
button.textContent = 'Capture'
48-
player.setAttribute('style', controlStyle)
49-
var canvas
53+
var destination, imageBlob, player, canvas
54+
55+
const table = div.appendChild(dom.createElement('table'))
56+
const mainTR = table.appendChild(dom.createElement('tr'))
57+
const main = mainTR.appendChild(dom.createElement('td'))
58+
main.setAttribute('colspan', '4')
59+
60+
const buttons = table.appendChild(dom.createElement('tr'))
61+
62+
buttons.appendChild(dom.createElement('td')) // Cancel button
63+
.appendChild(UI.widgets.cancelButton(dom))
64+
.addEventListener('click', e => {
65+
stopVideo()
66+
doneCallback(null)
67+
})
68+
69+
buttons.appendChild(dom.createElement('td')) // Retake button
70+
.appendChild(UI.widgets.button(dom, cameraIcon, 'Retake'))
71+
.addEventListener('click', e => {
72+
retake()
73+
})
74+
75+
buttons.appendChild(dom.createElement('td')) // Trigger capture button
76+
.appendChild(UI.widgets.button(dom, UI.icons.iconBase + 'noun_10636.svg', 'Snap'))
77+
.addEventListener('click', grabCanvas)
78+
79+
buttons.appendChild(dom.createElement('td')) // Confirm and save button
80+
.appendChild(UI.widgets.continueButton(dom)) // @@ or send icon??
81+
.addEventListener('click', e => {
82+
saveBlob(imageBlob, destination)
83+
})
84+
85+
function displayPlayer () {
86+
player = main.appendChild(dom.createElement('video'))
87+
player.setAttribute('controls', '1')
88+
player.setAttribute('autoplay', '1')
89+
player.setAttribute('style', controlStyle)
90+
navigator.mediaDevices.getUserMedia(constraints)
91+
.then((stream) => {
92+
player.srcObject = stream
93+
})
94+
}
5095

5196
const constraints = {
5297
video: true
5398
}
5499

100+
function retake () {
101+
main.removeChild(canvas)
102+
displayPlayer() // Make new one as old one is stuck black
103+
}
104+
55105
function grabCanvas () {
56106
// Draw the video frame to the canvas.
57107
canvas = dom.createElement('canvas')
58-
canvas.setAttribute('width', '320')
59-
canvas.setAttribute('height', '240')
108+
canvas.setAttribute('width', canvasWidth)
109+
canvas.setAttribute('height', canvasHeight)
60110
canvas.setAttribute('style', controlStyle)
61-
player.parentNode.appendChild(canvas)
111+
main.appendChild(canvas)
62112

63113
const context = canvas.getContext('2d')
64114
context.drawImage(player, 0, 0, canvas.width, canvas.height)
65115

66-
// Stop all video streams.
67-
player.srcObject.getVideoTracks().forEach(track => track.stop())
68116
player.parentNode.removeChild(player)
69117

70118
canvas.toBlob(blob => {
71119
let msg = `got blob type ${blob.type} size ${blob.size}`
72120
console.log(msg)
73-
let destination = getImageDoc()
74-
saveBlob(blob, destination)
121+
destination = getImageDoc()
122+
imageBlob = blob // save for review
123+
reviewImage()
75124
// alert(msg)
76125
}, contentType) // toBlob
77126
}
78127

128+
function reviewImage () {
129+
// @@ Enable continue button
130+
// @@ Enable retake button
131+
}
132+
133+
function stopVideo () {
134+
if (player && player.srcObject) {
135+
player.srcObject.getVideoTracks().forEach(track => track.stop())
136+
}
137+
}
79138
function saveBlob (blob, destination) {
80139
let contentType = blob.type
81-
if (!confirm('Save picture to ' + destination + ' ?')) return
140+
// if (!confirm('Save picture to ' + destination + ' ?')) return
82141
console.log('Putting ' + blob.size + ' bytes of ' + contentType + ' to ' + destination)
83142
store.fetcher.webOperation('PUT', destination.uri, {data: blob, contentType: contentType}).then(resp => {
84143
console.log('ok saved ' + destination)
144+
stopVideo()
85145
doneCallback(destination)
86-
alert('saved ok: ' + destination)
87146
}, err => {
147+
stopVideo()
88148
alert(err)
89149
})
90150
}
91151

92-
button.addEventListener('click', grabCanvas)
93-
94152
// Attach the video stream to the video element and autoplay.
95-
navigator.mediaDevices.getUserMedia(constraints)
96-
.then((stream) => {
97-
player.srcObject = stream
98-
})
153+
displayPlayer()
99154
return div
100155
}
101156

@@ -108,9 +163,10 @@ function cameraCaptureControl (dom, store, getImageDoc, doneCallback) {
108163
*
109164
* This expacts the buttton to a large control when it is pressed
110165
*/
111-
function cameraButton (dom, store, getImageDoc, doneCallback) {
166+
167+
module.exports.cameraButton = function cameraButton (dom, store, getImageDoc, doneCallback) {
112168
const div = dom.createElement('div')
113-
const but = UI.widgets.button(dom, UI.icons.iconBase + 'noun_383448.svg', 'Take picture')
169+
const but = UI.widgets.button(dom, UI.icons.iconBase + 'noun_Camera_1618446_000000.svg', 'Take picture')
114170
var control
115171
function restoreButton (imageDoc) {
116172
div.removeChild(control)
@@ -120,15 +176,12 @@ function cameraButton (dom, store, getImageDoc, doneCallback) {
120176
div.appendChild(but)
121177
but.addEventListener('click', event => {
122178
div.removeChild(but)
123-
control = control || cameraCaptureControl(dom, store, getImageDoc, restoreButton)
179+
control = UI.media.cameraCaptureControl(dom, store, getImageDoc, restoreButton)
124180
div.appendChild(control)
125181
})
126182
return div
127183
}
128184

129-
media.cameraButton = cameraButton
130-
media.cameraCaptureControl = cameraCaptureControl
131-
132185
/// /////////////////////////////////////// OLD BROKEN
133186

134187
// Put up a video stream and take a picture
@@ -149,7 +202,7 @@ UI.media.cameraOLD = function (context, gotBlob) {
149202
ctx = canvas.getContext('2d')
150203
ctx.drawImage(video, 0, 0, width, height)
151204

152-
img.src = canvas.toDataURL('image/png') // @@@
205+
img.src = canvas.toDataURL(contentType) // @@@
153206
context.div.appendChild(img)
154207
}
155208

src/noun_Camera_1618446_000000.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/toDataURI.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/bin/sh
2+
# from https://unix.stackexchange.com/questions/247843/how-to-generate-a-data-uri-from-an-image-file
3+
mimetype=$(file -bN --mime-type "$1")
4+
content=$(base64 < "$1")
5+
echo "module.export = ('data:$mimetype;base64,$content'"
6+
# ends

0 commit comments

Comments
 (0)