diff --git a/frame.js b/frame.js index b126ad5e..a4715db7 100644 --- a/frame.js +++ b/frame.js @@ -75,8 +75,14 @@ Volcanos(chat.ONDAEMON, {_init: function(can, name) { if (can.user.isLocalFile) toast: function(can, sub, arg) { can.core.CallFunc(can.user.toast, [sub].concat(arg)) }, refresh: function(can, sub) { can.base.isFunc(sub.Update) && sub.Update() }, action: function(can, msg, sub, arg) { - if (can.page.SelectInput(can, sub._option, arg[0], function(target) { return arg[1] && (target.value = arg[1]), target.focus(), target })) { return } - (can.core.Value(sub, chat._OUTPUTS_CURRENT)||sub).runAction(can.request({}, msg), arg[0], arg.slice(1)) + if (can.page.SelectInput(can, sub._option, arg[0], function(target) { + // can.onmotion.delay(can, function() { + target.type == html.BUTTON? target.click(): arg[1] && (target.value = arg[1], target.focus()) + // }) + return target })) { return } + var _sub = can.core.Value(sub, chat._OUTPUTS_CURRENT) + if (_sub && _sub.onaction && _sub.onaction[arg[0]]) { return _sub.onaction[arg[0]]({}, _sub, arg[0]) } + if (sub && sub.onaction && sub.onaction[arg[0]]) { return sub.onaction[arg[0]]({}, sub, arg[0], _sub) } }, input: function(can, msg, sub, arg) { can.page.Select(can, sub._target, "input:focus", function(target) { target.value += arg[0] }) }, grow: function(can, msg, sub, arg) { if (sub.sup && sub.sup.onimport._grow) { return sub.sup.onimport._grow(sub.sup, msg, can.page.Color(arg.join(""))) } }, @@ -217,7 +223,7 @@ Volcanos(chat.ONAPPEND, {_init: function(can, meta, list, cb, target, field) { input: function(can, item, value, target, style) { if (item.type == html.SPACE) { return can.page.Append(can, target, [{view: can.base.join([html.ITEM, html.SPACE])}]) } var input = can.page.input(can, can.base.Copy({}, item), value) - if (item.type == html.SELECT && item.value) { input._init = function(target) { target.value = item.value } } + if (item.type == html.SELECT && item.value) { input._init = function(target) { target.value = value||item.value } } if (item.type == html.TEXT) { input.onkeydown = item.onkeydown||function(event) { can.onkeymap.input(event, can), can.onkeymap.selectOutput(event, can), event.key == lang.ENTER && can.onkeymap.prevent(event) } } diff --git a/page/index.css b/page/index.css index ecf9f61a..935cebbd 100644 --- a/page/index.css +++ b/page/index.css @@ -299,6 +299,7 @@ body.simple fieldset.Action>div.output>fieldset.plugin.inner>div.action { displa body.simple div.output.card div.item { border-radius:5px; box-shadow:2px 2px 6px 1px gray; } body.simple div.output.card div.item>div.title { border-bottom:solid 1px #e7e7e7; } body.simple fieldset.feel.float { top:0; } +body.simple div.code { padding:0px; border:none; } body.white.simple div.profile { background-color:whitesmoke; } body.white.simple div.profile { color:black; } diff --git a/plugin/local/chat/keyboard.css b/plugin/local/chat/keyboard.css new file mode 100644 index 00000000..b7961a72 --- /dev/null +++ b/plugin/local/chat/keyboard.css @@ -0,0 +1,3 @@ +fieldset.keyboard div.output div.item { + float:left; +} diff --git a/plugin/local/chat/keyboard.js b/plugin/local/chat/keyboard.js index 5a31078e..b31bb668 100644 --- a/plugin/local/chat/keyboard.js +++ b/plugin/local/chat/keyboard.js @@ -1,9 +1,40 @@ -Volcanos(chat.ONIMPORT, {_init: function(can, msg) { +Volcanos(chat.ONIMPORT, {_init: function(can, msg) { can.onmotion.clear(can) + var data = msg.TableDetail(), list = can.base.Obj(data.list), meta = can.base.Obj(data.meta) + can.user.trans(can, meta._trans), can.core.List(list, function(item) { + item._init = function(target) { + switch (target.type) { + case html.BUTTON: + target.onclick = function(event) { can.request(event, data) + can.runAction(event, web.SPACE, [ctx.ACTION, item.name], function() {}) + } + break + case html.TEXT: + target.onkeydown = function(event) { can.request(event, data) + if (event.key == lang.ENTER) { + can.runAction(event, web.SPACE, [ctx.ACTION, item.name, target.value], function() {}) + } + } + break + } + } + can.onappend.input(can, item, "", can._output) + }) + can.onimport._button(can, can.sup.onaction.list, data) + return can.onappend.table(can, msg), can.onappend.board(can, msg) - var meta = {}; msg.Table(function(value, key) { meta[value.key] = value.value }) can.require(["/plugin/input/keyboard.js"], function() { can.onfigure.keyboard._show(can, function(value) { can.runAction(can.request({}, meta, can.Option()), "input", [value]) }) }) -}}) +}, + _button: function(can, item, data) { item = can.base.isObject(item)? item: {type: html.BUTTON, name: item} + if (can.base.isArray(item)) { return can.core.List(item, function(item) { can.onimport._button(can, item, data) }) } + item._init = item._init||function(target) { + target.onclick = function(event) { can.request(event, data) + can.runAction(event, web.SPACE, [ctx.ACTION, item.name], function() {}) + } + } + can.onappend.input(can, item, "", can._output) + }, +}, [""]) diff --git a/plugin/local/chat/media.js b/plugin/local/chat/media.js deleted file mode 100644 index 92fbf4b5..00000000 --- a/plugin/local/chat/media.js +++ /dev/null @@ -1,33 +0,0 @@ -Volcanos(chat.ONIMPORT, {_init: function(can, msg, cb, target) { - can.ui = can.onlayout.display(can, target) - can.ui.canvas = can.page.Append(can, can.ui.display, [{type: "canvas", width: 320, height: 240, style: {display: "none"}}])._target - - can.onappend.table(can, msg, function(value, key, index, line, array) { - return {text: [value, "td"], onclick: function(event) { - can.sup.onimport.change(event, can.sup, key, value, function(msg) { - can.run(event) - }) - }} - }, can.ui.content) - - can.onappend.board(can, msg.Result(), can.ui.display) - can.base.isFunc(cb) && cb(msg) - }, -}) -Volcanos(chat.ONACTION, {_init: function(can, msg, cb, target) { - }, - - open: function(event, can) { - navigator.getUserMedia({video: {width: 320, height: 240}}, function(stream) { - var video = can.page.Append(can, can.ui.content, "video") - video.srcObject = stream, video.play() - can.ui.video = video - }, function(error) { - can.misc.Log("open camera", error) - }) - }, - snapshot: function(event, can) { - can.ui.canvas.getContext("2d").drawImage(can.ui.video, 0, 0) - can.page.Append(can, can.ui.display, [{type: "img", src: can.ui.canvas.toDataURL('image/webp')}]) - }, -}) diff --git a/plugin/state.js b/plugin/state.js index 6277679a..6fe5258c 100644 --- a/plugin/state.js +++ b/plugin/state.js @@ -180,14 +180,6 @@ Volcanos(chat.ONACTION, {list: [ full: function(event, can) { can.onaction["切换全屏"](event, can, "切换全屏", can.core.Value(can, chat._OUTPUTS_CURRENT)) }, next: function(event, can) { can.Update(event, [ctx.ACTION, mdb.NEXT, can.Status(mdb.TOTAL)||0, can.Option(mdb.LIMIT)||can.Action(mdb.LIMIT)||"", can.Option(mdb.OFFEND)||can.Action(mdb.OFFEND)||""]) }, prev: function(event, can) { can.Update(event, [ctx.ACTION, mdb.PREV, can.Status(mdb.TOTAL)||0, can.Option(mdb.LIMIT)||can.Action(mdb.LIMIT)||"", can.Option(mdb.OFFEND)||can.Action(mdb.OFFEND)||""]) }, - keyboard: function(event, can) { - can.base.isUndefined(can._daemon) && can.ondaemon._list[0] && (can._daemon = can.ondaemon._list.push(can)-1) - can.request(event, kit.Dict(ctx.INDEX, can._index, ice.MSG_DAEMON, can.core.Keys(can.ondaemon._list[0], can._daemon))) - can.runAction(event, "keyboard", [], function(msg) { - can.user.toast(can, {title: msg.Append(mdb.NAME), duration: -1, content: msg.Append(mdb.TEXT), action: [cli.CLOSE, cli.OPEN]}) - can.user.copy(msg._event, can, msg.Append(mdb.NAME)) - }) - }, actions: function(event, can) { can.onmotion.toggle(can, can._action) }, upload: function(event, can) { can.user.upload(event, can) }, @@ -196,25 +188,47 @@ Volcanos(chat.ONACTION, {list: [ navigator.clipboard? navigator.clipboard.readText().then(add).catch(function(err) { can.misc.Log(err) }): can.user.input(event, can, [{type: html.TEXTAREA, name: mdb.TEXT}], function(list) { add(list[0]) }) }, - scanQRCode0: function(event, can, button) { can.user.agent.scanQRCode(can) }, - scanQRCode: function(event, can, button) { - can.user.agent.scanQRCode(can, function(data) { - can.runAction(event, button, can.base.Simple(data), function() { can.Update() }) + getLocation: function(event, can, button) { can.user.agent.getLocation(can, function(data) { + can.user.input(can.request(event, data), can, [mdb.TYPE, mdb.NAME, mdb.TEXT, "latitude", "longitude"], function(args) { + can.runAction(event, button, args, function() { can.Update() }) }) - }, + }) }, openLocation: function(event, can) { can.user.agent.openLocation(can, can.request(event)) }, - getLocation: function(event, can, button) { - can.user.agent.getLocation(can, function(data) { can.request(event, data) - can.user.input(event, can, [mdb.TYPE, mdb.NAME, mdb.TEXT, "latitude", "longitude"], function(args) { - can.runAction(event, button, args, function() { can.Update() }) + scanQRCode0: function(event, can, button) { can.user.agent.scanQRCode(can) }, + scanQRCode: function(event, can, button) { can.user.agent.scanQRCode(can, function(data) { + can.runAction(event, button, can.base.Simple(data), function() { can.Update() }) + }) }, + record0: function(event, can, name, cb) { can.user.input(event, can, [{name: nfs.FILE, value: name}], function(list) { + navigator.mediaDevices.getDisplayMedia({video: {height: window.innerHeight}}).then(function(stream) { var toast + can.core.Next([3, 2, 1], function(item, next) { toast = can.user.toast(can, item + "s 后开始截图"), can.onmotion.delay(can, next, 1000) }, function() { toast.close() + cb(stream, function(blobs, ext) { var msg = can.request(event); msg._upload = new File(blobs, list[0]+ice.PT+ext) + can.runAction(msg, html.UPLOAD, [], function() { can.user.toastSuccess(can), can.Update() }) + can.core.List(stream.getTracks(), function(item) { item.stop() }) + }) }) + }).catch(function(err) { can.user.toast(can, err.name + ": " + err.message) }) + }) }, + record1: function(event, can) { can.onaction.record0(event, can, "shot", function(stream, cb) { var height = window.innerHeight + var video = can.page.Append(can, document.body, [{type: html.VIDEO, height: height}])._target; video.srcObject = stream, video.onloadedmetadata = function() { video.play(), width = video.offsetWidth + var canvas = can.page.Append(can, document.body, [{type: html.CANVAS, height: height, width: width}])._target; canvas.getContext("2d").drawImage(video, 0, 0, width, height) + canvas.toBlob((blob) => { cb([blob], nfs.PNG) }) + } + }) }, + record2: function(event, can) { can.onaction.record0(event, can, "shot", function(stream, cb) { + var recorder = new MediaRecorder(stream, {mimeType: web.VIDEO_WEBM}), blobs = []; recorder.ondataavailable = function(res) { blobs.push(res.data) } + recorder.onstop = function() { cb(blobs, nfs.WEBM) }, recorder.start(1) + }) }, + keyboard: function(event, can) { + can.base.isUndefined(can._daemon) && can.ondaemon._list[0] && (can._daemon = can.ondaemon._list.push(can)-1) + can.request(event, kit.Dict(ctx.INDEX, can._index, ice.MSG_DAEMON, can.core.Keys(can.ondaemon._list[0], can._daemon))) + can.runAction(event, "keyboard", [], function(msg) { can.user.copy(msg._event, can, msg.Append(mdb.NAME)) + can.user.toast(can, {title: msg.Append(mdb.NAME), duration: -1, content: msg.Append(mdb.TEXT), action: [cli.CLOSE, cli.OPEN]}) }) }, }) -Volcanos(chat.ONEXPORT, { +Volcanos(chat.ONEXPORT, {record: function(can, line) {}, statusHeight: function(can) { return can._status.style.display == html.NONE || can._status.innerHTML == "" || can._status.offsetHeight == 0? 0: html.ACTION_HEIGHT }, actionHeight: function(can) { return can._action.style.display == html.NONE || can._action.innerHTML == ""? 0: html.ACTION_HEIGHT }, - record: function(can, line) {}, link: function(can) { var meta = can.Conf(), args = can.Option() args.cmd = meta.index||can.core.Keys(meta.ctx, meta.cmd), args.cmd == web.WIKI_WORD && (args.cmd = args.path) return can.misc.MergePodCmd(can, args, true) diff --git a/plugin/story/media.js b/plugin/story/media.js deleted file mode 100644 index 37582796..00000000 --- a/plugin/story/media.js +++ /dev/null @@ -1,92 +0,0 @@ -Volcanos(chat.ONIMPORT, {_init: function(can, msg, cb, target) { - can.onmotion.clear(can, target), can.base.isFunc(cb) && cb(msg) - can.requireModules(["gifshot/dist/gifshot.js"], function() { - - }) - var height = can.ConfHeight() - can.ui = can.page.Append(can, can._output, [{view: html.OUTPUT}, {view: html.DISPLAY, style: {height: height/4}}]) - msg.Table(function(value) { - can.onimport._video(can, "/chat/media/"+value.path) - }) - }, - - _action: function(can, list) { - can.onappend._action(can, list||can.onaction.list, can._action, can.onaction) - }, - _layout: function(can, cb) { var height = can.ConfHeight() - can.ui.video = can.page.Appends(can, can.ui.output, [{type: html.VIDEO, data: {controls: "controls"}, style: {height: height*3/4}, _init: function(target) { - can.onmotion.delay(can, function() { cb(target) }) - }}])._target, can.onimport._action(can, ["抓拍", "录制", "取消"]) - }, - _image: function(can, src) { - can.page.insertBefore(can, [{img: src, style: {height: can.ConfHeight()/4}}], can.ui.display.firstChild, can.ui.display) - return src - }, - _video: function(can, src) { - can.page.insertBefore(can, [{type: html.VIDEO, src: src, data: {controls: "controls"}, style: {height: can.ConfHeight()/4}}], can.ui.display.firstChild, can.ui.display) - return src - }, -}) -Volcanos(chat.ONACTION, {list: ["录屏", "摄像"], - "录屏": function(event, can) { - can.onimport._layout(can, function(target) { - navigator.mediaDevices.getDisplayMedia({video: {height: can.ConfHeight()*3/4}}).then(function(stream) { can.stream = stream - target.srcObject = stream, target.onloadedmetadata = function(e) { target.play() } - }).catch(function(err) { can.misc.Log(err.name + ": " + err.message) }) - }) - }, - "摄像": function(event, can) { - can.onimport._layout(can, function(target) { - navigator.mediaDevices.getUserMedia({video: {height: can.ConfHeight()*3/4}}).then(function(stream) { can.stream = stream - target.srcObject = stream, target.onloadedmetadata = function(e) { target.play() } - }).catch(function(err) { can.misc.Log(err.name + ": " + err.message) }) - }) - }, - "抓拍": function(event, can) { var width = can.ui.video.offsetWidth, height = can.ui.video.offsetHeight - var canvas = can.page.Append(can, can.ui.display, [{type: html.CANVAS, height: height, width: width}])._target - canvas.getContext("2d").drawImage(can.ui.video, 0, 0, width, height, 0, 0, width, height) - can.onimport._image(can, canvas.toDataURL('image/png')), can.page.Remove(can, canvas) - }, - "录制": function(event, can) { can.ui.blobs = [] - var recorder = new MediaRecorder(can.stream, {mimeType: 'video/webm'}) - recorder.ondataavailable = function(res) { can.ui.blobs.push(res.data), can.Status("total", can.ui.blobs.length) } - recorder.onstop = function() { - can.onimport._layout(can, function(target) { - target.src = can.onimport._video(can, URL.createObjectURL(new Blob(can.ui.blobs, {type: 'video/webm'}))) - }), can.onimport._action(can, ["上传", "取消"]) - } - recorder.start(10), can.ui.recorder = recorder - can.onimport._action(can, ["结束"]) - }, - "结束": function(event, can) { - can.core.List(can.stream.getTracks(), function(track) { track.stop() }) - }, - "上传": function(event, can) { var msg = can.request(event) - can.user.input(event, can, [{type: "text", name: "file", value: "some"}], function(list) { - msg._upload = new File(can.ui.blobs, (list[0]||"some")+".webm") - can.runAction(event, html.UPLOAD) - }) - }, - "取消": function(event, can) { - can.onmotion.clear(can, can.ui.output), can.onimport._action(can) - }, -}) -Volcanos(chat.ONDETAIL, {list: ["关闭", "抓拍", "录制"], - "成图": function(event, can) { - gifshot.createGIF({ - 'video': [URL.createObjectURL(new Blob(can.ui.blobs, {type : 'video/webm'}))], - },function(obj) { - if(!obj.error) { - can.user.download(can, obj.image, "some", "gif") - } - }); - }, - "回放": function(event, can) { - var video = can.page.Append(can, can.ui.output, [{type: html.VIDEO, style: {width: can.ConfWidth()}}]).video - video.src = URL.createObjectURL(new Blob(can.ui.blobs, {type : 'video/webm'})), video.play() - }, - "下载": function(event, can) { - can.user.download(can, URL.createObjectURL(new Blob(can.ui.blobs, {type: "video/webm"})), "record.webm") - }, -}) -Volcanos(chat.ONEXPORT, {list: ["total"]}) diff --git a/proto.js b/proto.js index 350c7949..5351381c 100644 --- a/proto.js +++ b/proto.js @@ -84,6 +84,7 @@ var web = { ContentJSON: "application/json", ContentFORM: "application/x-www-form-urlencoded", CODE_INNER: "web.code.inner", WIKI_WORD: "web.wiki.word", + VIDEO_WEBM: "video/webm", } var mdb = { DICT: "dict", META: "meta", HASH: "hash", LIST: "list",