From 533d4cbf5f636cf99a2a333ffe1825e1c19b2d00 Mon Sep 17 00:00:00 2001 From: shy Date: Fri, 28 Jun 2024 18:39:24 +0800 Subject: [PATCH] add some --- frame.js | 6 +- index.css | 4 +- lib/base.js | 2 +- plugin/input/key.js | 1 + plugin/local/wiki/feel.css | 39 ++++-- plugin/local/wiki/feel.js | 238 ++++++++++++++++++------------------- plugin/state.js | 26 ++-- plugin/table.js | 15 ++- 8 files changed, 179 insertions(+), 152 deletions(-) diff --git a/frame.js b/frame.js index 5a920bc5..64adb09d 100644 --- a/frame.js +++ b/frame.js @@ -326,7 +326,7 @@ Volcanos(chat.ONAPPEND, { _legend: can._legend, _option: can._option, _action: action||can._action, _output: output, _status: status||can._status, Update: can.Update, Option: can.Option, Action: can.Action, Status: can.Status, db: {hash: [""], value: {}}, ui: {layout: function() {}}, }, [display, msg.Option(ice.MSG_DISPLAY_CSS)||undefined, chat.PLUGIN_TABLE_JS], function(sub) { sub.Conf(can.Conf()) - sub.db.hash = can.base.getValid(can.isCmdMode()? can.misc.SearchHash(can): [], can.misc.localStorage(can, [sub.ConfSpace()||can.misc.Search(can, ice.POD), sub.ConfIndex(), "hash"]))||[] + sub.db.hash = can.base.getValid(can.isCmdMode()? can.misc.SearchHash(can): [], can.onexport.storage(can, "hash"))||[] var last = can.sub; last && can.core.CallFunc([last, "onaction.hidden"], {can: last}) sub.run = function(event, cmds, cb, silent) { var msg = sub.request(event)._caller() msg.RunAction(event, sub, cmds) || can.Update(event, can.Input(cmds, !silent), cb, silent) @@ -801,7 +801,7 @@ Volcanos(chat.ONAPPEND, { if (target.innerHTML == "") { return } var h = calc(item, target.offsetHeight, height), w = meta.width||width if (h > _height/2) { h = _height/2, can.page.style(can, target, html.HEIGHT, h) } - can.page.style(can, target, html.WIDTH); if (can.page.isDisplay(target)) { height -= h } + can.page.style(can, target, html.WIDTH, w); if (can.page.isDisplay(target)) { height -= h } if (can.base.isObject(meta) && meta.layout) { meta.layout(h = _height/list.length, w) } } }), can.core.List(list, function(item) { @@ -1070,7 +1070,7 @@ Volcanos(chat.ONMOTION, { }, select: function(can, target, name, which, cb) { var old = can.page.SelectOne(can, target, name+".select") can.base.isUndefined(which) || can.page.SelectChild(can, target, name, function(target, index) { - if (can.page.ClassList.set(can, target, html.SELECT, target == which || index == which)) { can.base.isFunc(cb) && cb(target) } + if (can.page.ClassList.set(can, target, html.SELECT, target == which || index == which || decodeURI(target.src) == which)) { can.base.isFunc(cb) && cb(target) } }); return old }, modify: function(can, target, cb, item) { var back = target.innerHTML, _target = target diff --git a/index.css b/index.css index 63762801..de411e52 100644 --- a/index.css +++ b/index.css @@ -294,7 +294,7 @@ fieldset.input.icons table { width:100%; text-align:center; } fieldset.input.key div.action { display:none; } fieldset.input.key div.action div.item.state { display:none; } fieldset.input.key div.output table.content { font-family:var(--code-font-family); width:100%; } -fieldset.input.key div.output table.content td:first-child { cursor:pointer; } +fieldset.input.key div.output table.content td:first-child { padding-left:24px; cursor:pointer; } fieldset.input.key div.output table.content.checkbox td:nth-child(2) { cursor:pointer; } fieldset.input.key div.output table.content:not(.checkbox) td:not(:first-child) { background-color:unset !important; color:var(--disable-fg-color); cursor:default; } fieldset.input.key>div.output>div.item:not(.hide) { display:flex; align-items:center; } @@ -581,6 +581,7 @@ fieldset.float { box-shadow:var(--float-box-shadow); border:var(--plugin-border) fieldset:not(.panel):hover { box-shadow:var(--notice-box-shadow); } body.light fieldset.plugin>legend { box-shadow:var(--legend-box-shadow); margin-right:var(--legend-margin); } body.light fieldset.story>legend { box-shadow:var(--legend-box-shadow); margin-right:var(--legend-margin); } +body.light fieldset.vimer fieldset.story>legend { margin-right:var(--input-margin); padding:0 var(--input-padding); } fieldset.story>legend { border-top-left-radius:var(--plugin-radius); } fieldset>form.option div.item:not(.icon) { box-shadow:var(--input-box-shadow); } fieldset>form.option div.item.select { border-radius:var(--button-radius); } @@ -701,6 +702,7 @@ fieldset.plugin>form.option>div.item.text.path>input { width:var(--project-width div.item.text.limit>input { width:var(--button-width); } div.item.text.offend>input { width:var(--button-width); } body:not(.width2):not(.mobile) fieldset.plugin>form.option>div.item.text.path>input { width:var(--project-width); } +body:not(.width2):not(.mobile) fieldset.plugin.feel>form.option>div.item.text.file>input { width:var(--project-width); } body:not(.width2) fieldset>div.action>div.item.text.filter>input { width:var(--input-width); height:30px; transition:all 1.2s; } body:not(.width2) fieldset>div.action>div.item.text.filter>input:focus { width:var(--project-width); transition:all 0.5s; } div.item.text.will>input { border:var(--box-notice); } diff --git a/lib/base.js b/lib/base.js index 3571d8b9..de1e57a2 100644 --- a/lib/base.js +++ b/lib/base.js @@ -35,7 +35,7 @@ Volcanos("base", { } return to === from }, - Ext: function(path) { return path.split(nfs.PS).pop().split(nfs.PT).pop().toLowerCase() }, + Ext: function(path) { return path.split("?")[0].split(nfs.PS).pop().split(nfs.PT).pop().toLowerCase() }, Dir: function(path) { return path.endsWith(nfs.PS)? path: path.slice(0, path.lastIndexOf(nfs.PS)+1) }, Path: function(path) { var res = "", arg = arguments; for (var i = 0; i < arg.length; i++) { if (!arg[i]) { continue } diff --git a/plugin/input/key.js b/plugin/input/key.js index 3ff54c71..506e70a0 100644 --- a/plugin/input/key.js +++ b/plugin/input/key.js @@ -64,6 +64,7 @@ Volcanos(chat.ONFIGURE, {key: { meta.msg && meta.msg.Length() > 0? sub._show(sub, meta.msg, cb, target, meta.name): sub._load(event, sub, cb, target, meta.name, target.value) }) }, onblur: function(event, can, sub, cb, target) { if (target._hold) { return } + return can.onengine.signal(can, "onevent", can.request(event, {query: can.page.getquery(can, target)+","+target.value})) sub && can.onmotion.delay(can, sub.close, 300) }, diff --git a/plugin/local/wiki/feel.css b/plugin/local/wiki/feel.css index 7b1273f4..699445cb 100644 --- a/plugin/local/wiki/feel.css +++ b/plugin/local/wiki/feel.css @@ -1,15 +1,30 @@ -fieldset.feel>div.output>div.layout>div.display { position:relative; overflow-y:hidden; } -fieldset.feel>div.output>div.layout>div.display>img:hover { background-color:var(--hover-bg-color); cursor:pointer; } -fieldset.feel>div.output>div.layout>div.display:not(.hide) { height:100px; display:flex; justify-content:center; align-items:normal; gap:10px; } -fieldset.feel>div.output>div.layout>div.display:not(.hide) img { height:100px; } -fieldset.feel>div.output>div.layout>div.display:not(:hover)>div.toggle { display:none; } -fieldset.feel>div.output>div.layout>div.display>div.toggle { font-size:48px; padding:5px; position:absolute; height:100px; padding-top:20px; } +// fieldset.feel>form.option div.item.file input { width:var(--project-width); } +fieldset.feel:not(.cmd)>form.option div.item.file { display:none; } +fieldset.feel>div.output>div.project div.item span.name { flex-grow:1; overflow:hidden; } +fieldset.feel>div.output>div.project div.item span.progress { color:var(--notice-bg-color); margin-left:10px; } +fieldset.feel>div.output>div.project div.item span.size { color:var(--disable-fg-color); font-size:var(--status-font-size); margin-left:10px; } +fieldset.feel>div.output>div.layout>div.display { position:relative; overflow:hidden; } +fieldset.feel>div.output>div.layout>div.display:not(.hide) { height:100px; display:flex; justify-content:center; align-items:center; gap:10px; } +fieldset.feel>div.output>div.layout>div.display>.select { border:var(--box-notice); } +fieldset.feel>div.output>div.layout>div.display>img { height:98px; width:100px; object-fit:cover; } +fieldset.feel>div.output>div.layout>div.display>video { height:98px; width:100px; object-fit:cover; } +fieldset.feel>div.output>div.layout>div.display>div.audio { word-break:break-all; height:100%; width:100px; display:flex; align-items:center; } +fieldset.feel>div.output>div.layout>div.display>div.audio:not(.select) { border:var(--box-border); } +fieldset.feel>div.output>div.layout>div.display>img:hover { cursor:pointer; } +fieldset.feel>div.output>div.layout>div.display>video:hover { cursor:pointer; } +fieldset.feel>div.output>div.layout>div.display>div.audio:hover { background-color:var(--hover-bg-color); cursor:pointer; } +fieldset.feel>div.output>div.layout>div.display>div.toggle { font-size:32px; padding:5px; padding-top:32px; height:100px; position:absolute; } fieldset.feel>div.output>div.layout>div.display>div.toggle.prev { left:0; } fieldset.feel>div.output>div.layout>div.display>div.toggle.next { right:0; } -fieldset.feel>div.output>div.layout>div.layout>div.content { text-align:center; overflow-y:hidden; } -fieldset.feel>div.output>div.layout>div.layout>div.content>img { cursor:pointer; } -fieldset.feel>div.output>div.layout>div.layout>div.content>img:hover { background-color:var(--hover-bg-color); } -fieldset.feel>div.output>div.layout>div.layout>div.content:not(:hover)>div.toggle { display:none; } -fieldset.feel>div.output>div.layout>div.layout>div.content>div.toggle { font-size:48px; padding:5px; padding-top:32px; top:40%; height:120px; } +fieldset.feel>div.output>div.layout>div.layout>div.content { overflow:hidden; padding:0; } +fieldset.feel>div.output>div.layout>div.layout>div.content>img { object-fit:scale-down; cursor:pointer; } +fieldset.feel>div.output>div.layout>div.layout>div.content>img { height:100%; width:100%; } +fieldset.feel>div.output>div.layout>div.layout>div.content>video { height:100%; width:100%; } +fieldset.feel>div.output>div.layout>div.layout>div.content>div.audio { height:100%; width: 100%; display:flex; flex-direction:column; justify-content:center; align-items:center; } +fieldset.feel>div.output>div.layout>div.layout>div.content>div.toggle { font-size:32px; padding:5px; padding-top:32px; height:100px; top:40%; z-index:5; } fieldset.feel>div.output>div.layout>div.layout>div.content>div.toggle.next { right:0; } -body.mobile fieldset.feel>div.output>div.project { overflow-x:hidden; } +fieldset.feel>div.output>div.layout>div.layout>div.content>div.toggle.prev { left:0; } +fieldset.feel>div.output>div.layout>div.layout>div.content>div.progress { background-color:var(--notice-bg-color); height:3px; position:absolute; bottom:2px; } +// body:not(.mobile) fieldset.feel>div.output>div.layout>div.layout>div.content:not(:hover)>div.toggle { display:none; } +// body:not(.mobile) fieldset.feel>div.output>div.layout>div.display:not(:hover)>div.toggle { display:none; } +// body.mobile fieldset.feel>div.output>div.project { overflow-x:hidden; } diff --git a/plugin/local/wiki/feel.js b/plugin/local/wiki/feel.js index 0a22d0bd..8b919a35 100644 --- a/plugin/local/wiki/feel.js +++ b/plugin/local/wiki/feel.js @@ -1,140 +1,126 @@ Volcanos(chat.ONIMPORT, { - _init: function(can, msg) { can.onappend.style(can, html.FLEX, can.ui.display) - can.ui = can.onappend.layout(can), can.onmotion.toggle(can, can.ui.display, true), can.onimport._project(can, msg) - can.onimport.page(can, can.db.list, can.db.begin = parseInt(msg.Option(cli.BEGIN)||"0")) - can.onmotion.hidden(can, can._action), can.onimport.layout(can) + _init: function(can, msg, cb) { + can.ui = can.onappend.layout(can), can.onimport._project(can, msg) + cb && cb(msg), can.onimport.page(can, can.db.list, can.db.begin = 0) + can.onmotion.toggle(can, can.ui.display, true), can.onimport.layout(can) }, _project: function(can, msg) { can.db.list = [], can.db.dir_root = msg.Option(nfs.DIR_ROOT) msg.Table(function(item) { item.name = can.base.trimPrefix(item.path, can.Option(nfs.PATH)) can.base.endWith(item.path, nfs.PS)? can.onimport.item(can, item, function(event) { can.Option(nfs.PATH, item.path) && can.Update(event) }): can.db.list.push(item) }) - var rate = can.misc.localStorage(can, [can.ConfIndex(), "rate"]); rate && can.Action(html.SPEED, rate) - can.core.List(can.db.list, function(item, index) { item._select = item.path == (can.db.hash[0]||"usr/icons/background.jpg") - item.nick = (last? last+lex.SP: "")+item.name - var last = can.misc.localStorage(can, [can.ConfIndex(), "p", can.onimport._file(can, item.path)]) - var target = can.onimport.item(can, item, function(_event, item, show, target) { can.onexport.hash(can, item.path), can.onexport.title(can, item.path.split("/").pop()) - can.ui.cb = function(event) { var next = _event.target.nextSibling - target.innerHTML = parseInt(event.target.currentTime*100/event.target.duration)+"% "+item.name - can.ui.video = event.target, can.Status(item), can.misc.localStorage(can, [can.ConfIndex(), "last"], item.path) - if (event.type == "ratechange") { can.misc.localStorage(can, [can.ConfIndex(), "rate"], event.target.playbackRate) } - if (event.type == "ended" && next) { can.onmotion.delay(can, function() { next.click() }, 3000), can.user.toast(can, "3s 后即将播放下一个", "", 3000) } - } - can.Option(nfs.FILE, can.base.trimPrefix(item.path, can.Option(nfs.PATH))) - can.onimport.layout(can), can.onmotion.scrollIntoView(can, target), can.onmotion.clear(can, can.ui.content) - var _target = can.onimport.file(can, item.path, item, index, can.ui.content, can.ui.content.offsetHeight, true) - _target.focus(), _target.onclick = function() { can.ondetail._init(can, index) } - can.onimport.layout(can) - can.onappend._toggle(can, can.ui.content, function() { - index == 0? can.user.toast(can, "已经是第一页了"): _event.target.previousSibling.click() - }, function() { - try { _event.target.nextSibling.click() } catch (e) { can.user.toast(can, "已经是最后一页了") } - }) - var limit = parseInt(can.Action(mdb.LIMIT)) - if (index < can.db.begin || index >= can.db.begin+limit) { - can.onimport.page(can, can.db.list, can.db.begin = index-index%limit) - } - }); item._target = target - if (can.isCmdMode() && item.path == can.misc.localStorage(can, [can.ConfIndex, "last"])) { - can.Action(html.HEIGHT, html.HIDE), can.onmotion.hidden(can, can.ui.display) - _target = target, can.onmotion.delay(can, function() { can.onaction.full({}, can) }) + can.core.List(can.db.list, function(item, index) { var last = can.onexport.progress(can, "p."+can.onimport._file(can, item.path)) + item.nick = [{text: [item.name, "", mdb.NAME]}, last && {text: [last, "", "progress"]}, {text: [item.size, "", nfs.SIZE]}] + item._hash = item.path, item._title = item.path.split("/").pop() + var target = can.onimport.item(can, item, function(event, item, show, target) { can.onimport._content(can, item, index, target) }); item._target = target + }) + }, + _content: function(can, item, index, target) { var progress + can.Option(nfs.FILE, can.base.trimPrefix(item.path, can.Option(nfs.PATH))) + if (can.onexport.progress(can, "p."+item._path) == "100%") { + can.onexport.progress(can, "p."+item._path, ""), can.onexport.progress(can, item._path, 0) + } + if (!can.onmotion.cache(can, function() { return item.path }, can.ui.content)) { + item._cb = function(event) { can.ui.video = event.target, can.Status(item), can.onexport.storage(can, "last", item.path) + var p = parseInt(event.target.currentTime*100/event.target.duration); item.nick[1] = {text: [p+"%", "", "progress"]}, can.page.Appends(can, target, item.nick) + if (!progress) { progress = can.page.Append(can, can.ui.content, ["progress"])._target } + can.page.style(can, progress, html.WIDTH, can.ui.content.offsetWidth*p/100) } - }) + var _target = can.onimport.file(can, item.path, item, index, can.ui.content, true); _target.focus() + // _target.onclick = function() { can.page.tagis(_target, html.IMG) && can.ondetail._init(can, index) } + can.onappend._toggle(can, can.ui.content, function() { + index == 0? can.user.toast(can, "已经是第一页了"): target.previousSibling.click() + }, function() { + try { target.nextSibling.click() } catch (e) { can.user.toast(can, "已经是最后一页了") } + }) + } + can.Status(item) + if (index < can.db.begin || index >= can.db.begin+can.db.limit) { + can.onimport.page(can, can.db.list, can.db.begin = index-index%can.db.limit) + } can.onmotion.select(can, can.ui.display, "*", item._display) }, - _file: function(can, path) { var p = location.href.indexOf(ice.HTTP) == 0? "": "http://localhost:9020" - return path.indexOf(ice.HTTP) == 0? path: can.misc.Resource(can, can.db.dir_root+path, can.ConfSpace(), p) + _file: function(can, path) { + return (location.href.indexOf(ice.HTTP) == 0? location.origin: "http://localhost:9020")+can.misc.Resource(can, can.db.dir_root+path, can.ConfSpace()) }, - file: function(can, path, item, index, target, height, auto) { path = can.onimport._file(can, path) - var cb = can.onfigure[can.base.Ext(path)]||can.onfigure[wiki.IMAGE]; can.Status(nfs.FILE, path) - return cb && can.page.Append(can, target||can.ui.display, [cb(can, path, item, index, height, auto)])._target + file: function(can, path, item, index, target, auto) { item._path = path = can.onimport._file(can, path) + var cb = can.onfigure[can.base.Ext(path)]||can.onfigure[wiki.IMAGE] + return cb && can.page.Append(can, target||can.ui.display, [cb(can, path, item, index, auto)])._target }, - page: function(can, list, begin, limit) { can.onmotion.clear(can, can.ui.display) - begin = parseInt(begin||can.db.begin), limit = parseInt(limit||can.Action(mdb.LIMIT)) - for (var i = begin; i < begin+limit; i++) { list && list[i] && can.onimport.file(can, list[i].path, list[i], i) } - can.onmotion.orderShow(can, can.ui.display, "*") + page: function(can, list, begin) { can.onmotion.clear(can, can.ui.display) + begin = parseInt(begin||can.db.begin||0), can.db.limit = (parseInt(can.ui.display.offsetWidth/110)||5)-1 + for (var i = begin; i < begin+can.db.limit; i++) { + if (list && list[i]) { + list[i]._display = can.onimport.file(can, list[i].path, list[i], i) + } + } can.onappend._toggle(can, can.ui.display, function(event) { can.onaction.prev(event, can) }, function(event) { can.onaction.next(event, can) }) - can.Status({begin: begin, limit: limit, total: list.length}) + can.Status({begin: begin, limit: can.db.limit, total: list.length}) }, - layout: function(can) { can.ui.layout && can.ui.layout(can.ConfHeight(), can.ConfWidth(), 0, function(height, width) { - can.page.Select(can, can.ui.content, can.page.Keys(html.IMG, html.VIDEO), function(target) { - can.user.isMobile && !can.user.isLandscape()? can.page.style(can, target, html.HEIGHT, "", html.MAX_HEIGHT, height, html.MAX_WIDTH, width): - can.page.style(can, target, html.MAX_HEIGHT, height, html.MAX_WIDTH, width) - }) - }) }, }, [""]) Volcanos(chat.ONFIGURE, { - png: function(can, path, item, index, height) { return can.onfigure.image(can, path, item, index, height) }, - jpg: function(can, path, item, index, height) { return can.onfigure.image(can, path, item, index, height) }, - jpeg: function(can, path, item, index, height) { return can.onfigure.image(can, path, item, index, height) }, - image: function(can, path, item, index, height) { return {img: path, - onmouseover: function(event) { can.Status(nfs.FILE, path), can.Status(item) }, - onclick: function(event) { item._target.click() }, - } }, - video: function(can, path, item, index, height, auto) { var total = 0, cb = can.ui.cb||function cb(event) { } - var init, last = can.misc.localStorage(can, can.onexport.key(can, path))||0 - return {type: html.VIDEO, style: {height: height||can.onexport.height(can)}, - data: {src: path, controls: "controls", autoplay: auto, playbackRate: parseFloat(can.Action(html.SPEED))}, - oncanplay: cb, onplay: cb, onpause: cb, oncontextmenu: cb, onratechange: cb, onseeked: cb, - onmouseover: function(event) { can.Status(nfs.FILE, path), can.Status(item) }, - onloadedmetadata: function(event) { total = event.timeStamp - event.target.currentTime = can._msg.currentTime || 0 - }, onloadeddata: cb, ontimeupdate: function(event) { cb(event) - can.misc.localStorage(can, can.onexport.key(can, path), event.target.currentTime) - can.misc.localStorage(can, can.onexport.key(can, "p", path), parseInt(event.target.currentTime*100/event.target.duration)+"%") + png: function(can, path, item, index) { return can.onfigure.image(can, path, item, index) }, + jpg: function(can, path, item, index) { return can.onfigure.image(can, path, item, index) }, + jpeg: function(can, path, item, index) { return can.onfigure.image(can, path, item, index) }, + image: function(can, path, item, index) { return {img: path, onclick: function(event) { item._target.click() }} }, + audio: function(can, path, item, index, auto) { + var meta = can.onfigure.video(can, path, item, index, auto); meta.type = html.AUDIO; + return {view: html.AUDIO, list: [{text: item.name}, meta], onclick: meta.onclick} + }, + video: function(can, path, item, index, auto) { + var cb = item._cb||function cb(event) {} + var init, last = can.onexport.progress(can, path)||0 + // preload: auto? "auto": "metadata", + return {type: html.VIDEO, data: {src: path, controls: auto? "controls": "", autoplay: auto, playbackRate: 1}, + onclick: function(event) { item._target.click(), can.onkeymap.prevent(event) }, + onratechange: function(event) { can.onexport.storage(can, "rate", event.target.playbackRate) }, + onvolumechange: function(event) { can.onexport.storage(can, "volume", event.target.volume) }, + onloadedmetadata: function(event) { + event.target.volume = can.onexport.storage(can, "volume")||1 + event.target.playbackRate = can.onexport.storage(can, "rate")||1 + }, + ontimeupdate: function(event) { if (event.target.currentTime == 0) { return } cb(event) + can.Status("position", can.onexport.position(can, event.target.currentTime-1, event.target.duration)) + can.onexport.progress(can, "p."+path, parseInt(event.target.currentTime*100/event.target.duration)+"%") + can.onexport.progress(can, path, event.target.currentTime) if (!init) { init = true, event.target.currentTime = last } - can.Status("position", can.onexport.position(can, (can._msg.currentTime=event.target.currentTime)-1, event.target.duration)) - }, onended: function(event) { cb(event), can.misc.localStorage(can, can.onexport.key(can, path), "") }, + }, + onended: function(event) { var next = item._target.nextSibling + if (next) { can.onmotion.delay(can, function() { next.click() }, 3000), can.user.toast(can, "3s 后即将播放下一个", "", 3000) } + }, } }, - mp4: function(can, path, item, index, height, auto) { return can.onfigure.video(can, path, item, index, height, auto) }, - m4v: function(can, path, item, index, height, auto) { return can.onfigure.video(can, path, item, index, height, auto) }, - mov: function(can, path, item, index, height, auto) { return can.onfigure.video(can, path, item, index, height, auto) }, - webm: function(can, path, item, index, height, auto) { return can.onfigure.video(can, path, item, index, height, auto) }, + webm: function(can, path, item, index, auto) { return can.onfigure.video(can, path, item, index, auto) }, + mov: function(can, path, item, index, auto) { return can.onfigure.video(can, path, item, index, auto) }, + m4v: function(can, path, item, index, auto) { return can.onfigure.video(can, path, item, index, auto) }, + mp4: function(can, path, item, index, auto) { return can.onfigure.video(can, path, item, index, auto) }, + mp3: function(can, path, item, index, auto) { return can.onfigure.audio(can, path, item, index, auto) }, }) -Volcanos(chat.ONACTION, {list: ["full", - [html.HEIGHT, 100, 200, 400, 600, 800, "max", html.HIDE, ice.AUTO], - [mdb.LIMIT, 6, 1, 3, 6, 9, 12, 15, 20, 30, 50], - [html.SPEED, 1, 0.25, 0.5, 0.75, 1, 1.25, 1.5, 2, 3, 5, 10], -], -height: function(event, can, key, value) { can.Action(key, value), can.onimport.page(can, can.db.list) }, -limit: function(event, can, key, value) { can.Action(key, value), can.onimport.page(can, can.db.list) }, -speed: function(event, can, key, value) { can.Action(key, value), can.onimport.page(can, can.db.list) }, -prev: function(event, can) { if (can.db.begin > 0) { can.db.begin -= parseInt(can.Action(mdb.LIMIT)), can.onimport.page(can, can.db.list) } else { can.user.toast(can, "已经是第一页了") } }, -next: function(event, can) { if (can.db.begin + parseInt(can.Action(mdb.LIMIT)) < can.db.list.length) { can.db.begin += parseInt(can.Action(mdb.LIMIT)), can.onimport.page(can, can.db.list) } else { can.user.toast(can, "已经是最后一页了") } }, -full: function(event, can) { - var show = can.onmotion.toggle(can, can.ui.project); can.onmotion.toggle(can, can.ui.display), can.onimport.layout(can, can.ConfHeight(), can.ConfWidth()) - can.page.ClassList.set(can, can.ui.content, html.FLOAT, !show), can.page.Select(can, can.ui.content, "*", function(target) { target.focus() - can.page.style(can, target, html.HEIGHT, can.ConfHeight()+(!show? 2*html.ACTION_HEIGHT: 0)-can.ui.display.offsetHeight) - }) -}, -onkeydown: function(event, can) { try { - if (event.target != can.ui.video) { - if (event.key == "ArrowLeft") { can.ui.video.currentTime -= 15 } - if (event.key == "ArrowRight") { can.ui.video.currentTime += 15 } - } - if (event.key == "Escape") { can.onaction.full(event, can) } - if (event.key == "ArrowUp") { can.user.toast(can, parseInt((can.ui.video.volume += 0.1)*100)) } - if (event.key == "ArrowDown") { can.user.toast(can, parseInt((can.ui.video.volume -= 0.1)*100)) } -} catch (e) {} }, -record0: function(event, can, name, cb) { can.user.input(event, can, [{name: nfs.FILE, value: name}], function(list) { var height = window.innerHeight - navigator.mediaDevices.getDisplayMedia({video: {height: height}}).then(function(stream) { - can.core.Next([3, 2, 1], function(item, next) { can.user.toast(can, item + "s 后开始截图"), can.onmotion.delay(can, next, 1000) }, function() { can.user.toast(can, "现在开始截图") - cb(stream, function(blobs, ext) { var msg = can.request(event); msg._upload = new File(blobs, list[0]+nfs.PT+ext) - can.runAction(msg, html.UPLOAD, [], function() { can.user.toast(can, "上传成功"), can.Update() }) - can.core.List(stream.getTracks(), function(item) { item.stop() }) +Volcanos(chat.ONACTION, { + record0: function(event, can, name, cb) { can.user.input(event, can, [{name: nfs.FILE, value: name}], function(list) { var height = window.innerHeight + navigator.mediaDevices.getDisplayMedia({video: {height: height}}).then(function(stream) { + can.core.Next([3, 2, 1], function(item, next) { can.user.toast(can, item + "s 后开始截图"), can.onmotion.delay(can, next, 1000) }, function() { can.user.toast(can, "现在开始截图") + cb(stream, function(blobs, ext) { var msg = can.request(event); msg._upload = new File(blobs, list[0]+nfs.PT+ext) + can.runAction(msg, html.UPLOAD, [], function() { can.user.toast(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(function(blob) { cb([blob], nfs.PNG) }) - } -}) }, -record2: function(event, can) { can.onaction.record0(event, can, "shot", function(stream, cb) { - var recorder = new MediaRecorder(stream, {mimeType: 'video/webm'}), blobs = []; recorder.ondataavailable = function(res) { blobs.push(res.data) } - recorder.onstop = function() { cb(blobs, nfs.WEBM) }, recorder.start(1) -}) }, + }).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(function(blob) { cb([blob], nfs.PNG) }) + } + }) }, + record2: function(event, can) { can.onaction.record0(event, can, "shot", function(stream, cb) { + var recorder = new MediaRecorder(stream, {mimeType: 'video/webm'}), blobs = []; recorder.ondataavailable = function(res) { blobs.push(res.data) } + recorder.onstop = function() { cb(blobs, nfs.WEBM) }, recorder.start(1) + }) }, + fullscreen: function(event, can) { + var show = can.onmotion.toggle(can, can.ui.project); can.onmotion.toggle(can, can.ui.display, show), can.onimport.layout(can) + can.page.ClassList.set(can, can.ui.content, html.FLOAT, !show) + }, + prev: function(event, can) { if (can.db.begin > 0) { can.db.begin -= can.db.limit, can.onimport.page(can, can.db.list) } else { can.user.toast(can, "已经是第一页了") } }, + next: function(event, can) { if (can.db.begin + can.db.limit < can.db.list.length) { can.db.begin += can.db.limit, can.onimport.page(can, can.db.list) } else { can.user.toast(can, "已经是最后一页了") } }, }) Volcanos(chat.ONDETAIL, {list: ["关闭", "上一个", "下一个", "设置头像", "设置背景", "复制链接", "下载", "删除"], _init: function(can, index) { @@ -157,8 +143,18 @@ Volcanos(chat.ONDETAIL, {list: ["关闭", "上一个", "下一个", "设置头 "下载": function(event, can) { can.user.download(can, path = can.onimport._file(can, can.db.list[can.order].path)) }, "删除": function(event, can) { can.runAction(event, nfs.TRASH, [can.db.list[can.order].path], function(msg) { can.user.toastSuccess(can, "删除成功") }, true) }, }) -Volcanos(chat.ONEXPORT, {list: [cli.BEGIN, mdb.LIMIT, mdb.TOTAL, nfs.FILE, nfs.SIZE, "position"], - height: function(can) { var height = can.Action(html.HEIGHT); return parseInt(height == html.HIDE? 0: height == "max"? can.ConfHeight(): height == ice.AUTO? can.base.Min(can.ConfHeight()/4, 200): height) }, +Volcanos(chat.ONEXPORT, {list: [cli.BEGIN, mdb.LIMIT, mdb.TOTAL, mdb.NAME, nfs.SIZE, mdb.TIME, "position"], + progress: function(can, path, time) { return can.onexport.storage(can, path.split("?")[0], time) }, position: function(can, index, total) { total = total || can.max; return parseInt((index+1)*100/total)+"%"+" = "+(parseInt(index)+1)+nfs.PS+parseInt(total) }, - key: function(can) { return [can.Conf(ctx.INDEX)].concat(can.core.List(arguments).slice(1)).join(":") }, +}) +Volcanos(chat.ONKEYMAP, { + _mode: { + plugin: { + Escape: function(event, can) { can.onaction.full(event, can) }, + ArrowLeft: function(event, can) { can.ui.video.currentTime -= 15 }, + ArrowRight: function(event, can) { can.ui.video.currentTime += 15 }, + ArrowDown: function(event, can) { try { can.user.toast(can, "volume: "+parseInt((can.ui.video.volume -= 0.1)*100)) } catch (e) {} }, + ArrowUp: function(event, can) { try { can.user.toast(can, "volume: "+parseInt((can.ui.video.volume += 0.1)*100)) } catch (e) {} }, + }, + }, }) diff --git a/plugin/state.js b/plugin/state.js index 5bcdc6ac..bea6b5df 100644 --- a/plugin/state.js +++ b/plugin/state.js @@ -1,7 +1,8 @@ Volcanos(chat.ONIMPORT, { _process: function(can, msg) { if (msg.IsErr()) { can.onappend.style(can, "warn", can.user.toastFailure(can, msg.Result())._target) } - if (can.onimport[msg.OptionProcess()]) { return can.core.CallFunc([can.onimport, msg.OptionProcess()], {can: can, sub: can.sub, msg: msg, arg: msg.Option("_arg")}), true } }, + if (can.onimport[msg.OptionProcess()]) { return can.core.CallFunc([can.onimport, msg.OptionProcess()], {can: can, sub: can.sub, msg: msg, arg: msg.Option("_arg")}), true } + }, _location: function(can, msg, arg) { can.user.jumps(arg) }, _replace: function(can, msg, arg) { location.replace(arg) }, _history: function(can, msg) { history.length == 1? can.user.close(): history.back() }, @@ -17,8 +18,7 @@ Volcanos(chat.ONIMPORT, { _cookie: function(can, msg) { can.misc.Cookie(can, msg._arg[0], msg._arg[1]), can.Update() }, _session: function(can, msg) { can.misc.sessionStorage(can, msg._arg[0], msg._arg[1]), can.Update() }, _field: function(can, msg, cb) { - can.page.style(can, can._target, "visibility", "") - can.page.style(can, can._output, "visibility", "") + can.page.style(can, can._target, "visibility", ""), can.page.style(can, can._output, "visibility", "") var height = can.ConfHeight()-can.onexport.actionHeight(can)-(can.onexport.statusHeight(can)||1), width = can.ConfWidth() var tabs = false, tabHash = msg.Option("field.tabs"); if (tabHash) { can.sub && can.sub.onimport.tabs(can.sub, [{name: tabHash.slice(0, 6)}], function() { can.onmotion.cache(can, function() { return tabHash }) }), tabs = true @@ -126,10 +126,13 @@ Volcanos(chat.ONIMPORT, { var _height = can.base.Max(sub._target.offsetHeight+border, can.ConfHeight()/2) sub.onimport.size(sub, _height-border, can.ConfWidth()-(can.ui && can.ui.project? can.ui.project.offsetWidth: 0), true) }, - back: function(event, can) { can._history.pop(); for (var i = 0, his = can._history.pop(); his; his = can._history.pop()) { if (his[0] == ctx.ACTION) { continue } - can.page.SelectArgs(can, can._option, "", function(target) { target.value = his[i++]||"", can.page.Select(can, target.parentNode, "span.value", function(target) { target.innerText = target.value||"" }) }) - can.page.SelectArgs(can, can._action, "", function(target) { target.value = his[i++]||"" }); break - } can.Update(event) }, + back: function(event, can) { can._history.pop() + for (var i = 0, his = can._history.pop(); his; his = can._history.pop()) { if (his[0] == ctx.ACTION) { continue } + can.page.SelectArgs(can, can._option, "", function(target) { target.value = his[i++]||"", can.page.Select(can, target.parentNode, "span.value", function(target) { target.innerText = target.value||"" }) }) + can.page.SelectArgs(can, can._action, "", function(target) { target.value = his[i++]||"" }); break + } + can.onexport.hash(can, ""), can.Update(event) + }, }) Volcanos(chat.ONACTION, { list: ["刷新数据", @@ -340,6 +343,13 @@ Volcanos(chat.ONEXPORT, { session: function(can, key, value) { if (value) { value = JSON.stringify(value) } return can.misc.sessionStorage(can, [can.ConfSpace()||can.misc.Search(can, ice.POD), can.ConfIndex(), key, location.pathname], value) }, + storage: function(can, key, value) { if (value) { value = JSON.stringify(value) } + return can.misc.localStorage(can, [can.ConfSpace()||can.misc.Search(can, ice.POD), can.ConfIndex(), key, location.pathname], value) + }, + hash: function(can, hash) { + can.misc.SearchHash(can, hash), can.onexport.storage(can, "hash", hash) + return hash + }, title: function(can, title) { if (!can.isCmdMode()) { return } var list = []; function push(p) { p && list.indexOf(p) == -1 && list.push(p) } if (!can.base.isIn(can.ConfIndex(), web.PORTAL)) { @@ -353,7 +363,7 @@ Volcanos(chat.ONEXPORT, { // if (can.sub && can.sub.onexport.link) { return can.sub.onexport.link(can.sub) } var args = can.Option(); args.pod = can.ConfSpace()||can.misc.Search(can, ice.POD), args.cmd = can.ConfIndex() can.core.Item(args, function(key, value) { key != ice.POD && !value && delete(args[key]) }) - var hash = can.misc.localStorage(can, [args.pod, args.cmd, "hash"])||"" + var hash = can.onexport.storage(can, "hash")||"" can.base.isArray(hash) && (hash = hash.join(":")) hash && (hash = "#"+hash) return can.misc.MergePodCmd(can, args, true)+hash diff --git a/plugin/table.js b/plugin/table.js index 63b71e33..eec61393 100644 --- a/plugin/table.js +++ b/plugin/table.js @@ -113,6 +113,8 @@ Volcanos(chat.ONIMPORT, { return icon && (can.base.contains(icon, ice.HTTP, ".ico", ".png", ".jpg")? {img: can.misc.Resource(can, icon)}: {icon: icon}) }, _nick: function(can, item) { + if (can.base.isArray(item.nick)) { return item.nick } + if (can.base.isObject(item.nick)) { return item.nick } return {text: [item.nick||item.name||item.zone||item.sess, "", html.NAME], className: html.NAME} }, _menu: function(event, can, item, cbs, target) { target = target||event.currentTarget @@ -124,8 +126,10 @@ Volcanos(chat.ONIMPORT, { item._title = item._title||item.name||item.path||item.path||item.hash item._select == undefined && can.db.hash[0] && (item._select = can.db.hash[0] == item._hash) return {view: [[html.ITEM, item.type, item.role, item.status]], title: item.title||item.nick, list: [ - can.onimport._icons(can, item), can.onimport._nick(can, item), - ].concat(item._label||[], [ + can.onimport._icons(can, item), + ].concat( + can.onimport._nick(can, item), + item._label||[], [ item.action && {icon: "bi bi-three-dots", onclick: function(event) { can.onimport._menu(event, can, item, cbs) }}, ]), _init: function(target) { target._item = item, item._item = target, can.ui[item.path] = target item._select && can.onmotion.delay(can, function() { target.click() }) @@ -140,8 +144,7 @@ Volcanos(chat.ONIMPORT, { return can.page.Append(can, _target||can.ui.project||can._output, [can.onimport._item(can, item, function(event) { var target = event.currentTarget can.onmotion.select(can, target.parentNode, html.DIV_ITEM, target) can.onengine.signal(can, "onproject", can.request(event, {type: "item", query: can.page.getquery(can, can._fields)+","+item.path})) - var show = target._list && can.onmotion.toggle(can, target._list); - if (show === false) { return } cb(event, item, show, target) + var show = target._list && can.onmotion.toggle(can, target._list); if (show === false) { return } cb(event, item, show, target) }, cbs)])._target }, _itemselect: function(can, target) { @@ -283,10 +286,10 @@ Volcanos(chat.ONEXPORT, { tabs: function(can) {}, tool: function(can) { can.misc.sessionStorage(can, [can.ConfIndex(), "tool"], JSON.stringify(can.page.Select(can, can._status, html.LEGEND, function(target) { return target._meta }))) }, hash: function(can, hash) { hash = typeof hash == code.STRING? hash.split(":").concat(can.core.List(arguments).slice(2)||[]): hash || can.core.Item(can.Option(), function(key, value) { return value||"" }) - can.misc.SearchHash(can, hash), can.misc.localStorage(can, [can.ConfSpace()||can.misc.Search(can, ice.POD), can.ConfIndex(), "hash"], hash) - return hash + return can.sup.onexport.hash(can.sup, hash) }, session: function(can, key, value) { return can.sup.onexport.session(can.sup, key, value) }, + storage: function(can, key, value) { return can.sup.onexport.storage(can.sup, key, value) }, table: function(can) { var msg = can._msg; if (msg.Length() == 0) { return } var res = [msg.append && msg.append.join(mdb.FS)] msg.Table(function(line, index, array) { res.push(can.core.Item(line, function(key, value) { return value }).join(ice.FS)) }) return res.join(lex.NL)