diff --git a/frame.js b/frame.js index 1145f698..b56f6c74 100644 --- a/frame.js +++ b/frame.js @@ -11,7 +11,7 @@ Volcanos(chat.ONENGINE, {_init: function(can, meta, list, cb, target) { can.core.CallFunc([sub.onaction, chat._INIT], {can: sub, cb: next, target: sub._target}) }, target) }, function() { can.onmotion._init(can, target), can.onkeymap._init(can, target), can.misc.Info(can.user.title(), ice.RUN, can) - can.onengine.listen(can, chat.ONSEARCH, function(msg, word) { word[0] == ctx.COMMAND && can.run(msg, ["can.command"]) }) + can.onengine.listen(can, chat.ONSEARCH, function(msg, arg) { arg[0] == ctx.COMMAND && can.run(msg, ["can.command"]) }) can.onengine.signal(can, chat.ONMAIN, can.request()), can.base.isFunc(cb) && cb(can) }) }, @@ -250,6 +250,13 @@ Volcanos(chat.ONAPPEND, {_init: function(can, meta, list, cb, target, field) { }); return code.scrollBy && code.scrollBy(0, 10000), code }, tools: function(can, msg, cb, target) { can.onimport.tool(can, can.base.Obj(msg.Option(ice.MSG_TOOLKIT), []), cb, target) }, + tabview: function(can, meta, list, target) { var ui = can.page.Append(can, target, [html.ACTION, html.OUTPUT]) + can.core.List(can.base.getValid(list, can.core.Item(meta)), function(name, index) { + ui[name] = can.page.Append(can, ui.action, [{text: name, onclick: function(event) { + if (can.onmotion.cache(can, function() { return name }, ui.output)) { return } meta[name](ui.output) + }, _init: function(target) { index == 0 && can.onmotion.delay(can, function() { target.click() }) }}])._target + }); return ui._target = target, ui + }, _plugin: function(can, value, meta, cb, target, field) { can.base.Copy(meta, value, true) meta.name = meta.name||value&&value.meta&&value.meta.name||"" @@ -272,7 +279,7 @@ Volcanos(chat.ONAPPEND, {_init: function(can, meta, list, cb, target, field) { _float: function(can, index, args) { can.onappend.plugin(can, {mode: chat.FLOAT, index: index, args: args}, function(sub) { can.getActionSize(function(left, top, width, height) { sub.onimport.size(sub, sub.ConfHeight(height/2), sub.ConfWidth(width), true) - can.onmotion.move(can, sub._target, {left: left||0, top: (top||0)+height/4}), can.onmotion.delay(can, function() { sub.Focus() }) + can.onmotion.move(can, sub._target, {left: left||0, top: (top||0)+height/4}) // , can.onmotion.delay(can, function() { sub.Focus() }) }), sub.onaction.close = function() { can.page.Remove(can, sub._target) } }, can._root._target) }, @@ -379,6 +386,11 @@ Volcanos(chat.ONMOTION, {_init: function(can, target) { }) }, }, + clearCarte: function(can) { + can.page.Select(can, can._root._target, "div.carte", function(target) { + can.page.Remove(can, target) + }) + }, hidden: function(can, target, show) { target = target||can._target if (target.length > 0) { return can.core.List(target, function(target) { can.onmotion.hidden(can, target, show) }) } diff --git a/lib/misc.js b/lib/misc.js index ca140d0c..34d9eafe 100644 --- a/lib/misc.js +++ b/lib/misc.js @@ -86,6 +86,7 @@ Volcanos("misc", {Message: function(event, can) { var msg = {} }; return kit.proto(msg, proto) }, concat: function(can, to, from) { to = to||[], from = from||[] + if (arguments.length > 3) { for (var i = 2; i < arguments.length; i++) { to = can.misc.concat(can, to, arguments[i]) } return to } if (from[0] == ctx.ACTION && from[1] == ice.RUN && can.onengine.plugin(can, from[2])) { return from } if (can.onengine.plugin(can, from[0])) { return from } if (from[0] == "_search") { return from } @@ -109,7 +110,10 @@ Volcanos("misc", {Message: function(event, can) { var msg = {} POST: function(can, msg, url, form, cb) { var xhr = new XMLHttpRequest(), begin = new Date(); msg._xhr = xhr xhr.open(msg._method||web.POST, url), xhr.onreadystatechange = function() { if (xhr.readyState != 4) { return } try { var res = JSON.parse(xhr.responseText) } catch (e) { var res = {result: [xhr.responseText]} } msg.Option("_cost", new Date() - begin) - if (xhr.status == 200) { return can.base.isFunc(cb) && cb(msg.Copy(res)) } can.misc.Warn(xhr.status, res, url, form) + if (xhr.status == 200) { return can.base.isFunc(cb) && cb(msg.Copy(res)) } + if (xhr.status == 401) { return can.user.toastFailure(can, xhr.response) } + if (xhr.status == 403) { return can.user.toastFailure(can, xhr.response) } + can.misc.Warn(xhr.status, res, url, form) }, xhr.setRequestHeader(web.Accept, msg._accept||web.ContentJSON) if (msg._upload) { @@ -162,7 +166,7 @@ Volcanos("misc", {Message: function(event, can) { var msg = {} MergeCache: function(can, hash) { return can.misc.MergeURL(can, {_path: can.base.Path(web.SHARE_CACHE, hash)}, true) }, MergePodCmd: function(can, objs) { objs.pod = can.core.Keys(can.misc.Search(can, ice.POD), objs.pod) - objs.topic = can.misc.Search(can, chat.TOPIC) + objs.topic = objs.topic||can.misc.Search(can, chat.TOPIC) return can.misc.MergeURL(can, objs, true) }, MergeURL: function(can, objs, clear) { var pod = "" @@ -192,6 +196,7 @@ Volcanos("misc", {Message: function(event, can) { var msg = {} return search? location.search = search: location.href = location.pathname }, CookieSessid: function(can, value, path) { + return can.misc.Cookie(can, ice.MSG_SESSID+"_"+can.base.replaceAll(location.port, ice.PT, "_", ice.DF, "_"), value, path) return can.misc.Cookie(can, ice.MSG_SESSID+"_"+can.base.replaceAll(location.host, ice.PT, "_", ice.DF, "_"), value, path) }, Cookie: function(can, key, value, path) { diff --git a/lib/user.js b/lib/user.js index d0db5e67..d03fbec1 100644 --- a/lib/user.js +++ b/lib/user.js @@ -11,6 +11,7 @@ Volcanos("user", {info: {}, agent: { +"/@12958750.085,4825785.55,16z?querytype=s&da_src=shareurl&wd="+encodeURIComponent(msg.Option(mdb.TEXT))) }, }, + isTesla: navigator.userAgent.indexOf("Tesla") > -1, isWeiXin: navigator.userAgent.indexOf("MicroMessenger") > -1, isIPhone: navigator.userAgent.indexOf("iPhone") > -1, isMobile: navigator.userAgent.indexOf("Mobile") > -1, @@ -66,11 +67,12 @@ Volcanos("user", {info: {}, agent: { toastConfirm: function(can, content, title, action) { return can.user.toast(can, {content: content, title: title, action: action||[cli.CLOSE], duration: -1, width: -300}) }, toastProcess: function(can, content, title) { return can.user.toast(can, content||ice.PROCESS, title||can._name.split(ice.PS).slice(-2).join(ice.PS), -1) }, - toastSuccess: function(can, content, title) { return can.user.toast(can, content||ice.SUCCESS, title||can._name.split(ice.PS).slice(-2).join(ice.PS)) }, + toastSuccess: function(can, content, title) { return can.user.toast(can, "\u2705 "+(content||ice.SUCCESS), (title||can._name.split(ice.PS).slice(-2).join(ice.PS))) }, + toastFailure: function(can, content, title) { return can.user.toast(can, "\u274C "+(content||ice.FAILURE), (title||can._name.split(ice.PS).slice(-2).join(ice.PS)), 5000) }, toast: function(can, content, title, duration, progress) { var meta = can.base.isObject(content)? content: {content: content, title: title||can._help, duration: duration, progress: progress} var width = meta.width||400; if (width < 0) { width = window.innerWidth + width } - var ui = can.page.Append(can, can._root._target, [{view: [[chat.TOAST, chat.FLOAT]], style: {left: (window.innerWidth-width)/2, width: width, bottom: 100}, list: [ + var ui = can.page.Append(can, document.body, [{view: [[chat.TOAST, chat.FLOAT]], style: {left: (window.innerWidth-width)/2, width: width, bottom: 100}, list: [ {text: [meta.title||"", html.DIV, html.TITLE], title: "点击复制", onclick: function(event) { can.user.copy(event, can, meta.title) }}, {view: "duration", title: "点击关闭", onclick: function() { action.close() }}, can.base.isObject(meta.content)? meta.content: {text: [meta.content||"", html.DIV, nfs.CONTENT]}, @@ -185,10 +187,10 @@ Volcanos("user", {info: {}, agent: { downloads: function(can, text, name, ext) { if (!text) { return } return can.user.download(can, URL.createObjectURL(new Blob([text])), name, ext) }, - toimage: function(event, can, name, target, silent) { - can.require(["https://cdn.jsdelivr.net/npm/html2canvas@1.0.0-rc.5/dist/html2canvas.min.js"], function() { + toimage: function(can, name, target, silent) { var toast = can.user.toastProcess(can, "生成中...") + can.require(["https://cdn.jsdelivr.net/npm/html2canvas@1.0.0-rc.5/dist/html2canvas.min.js"], function() { toast.close() html2canvas(target||can._target).then(function (canvas) { var url = canvas.toDataURL("image/png") - silent? can.user.download(can, url, name, nfs.PNG): can.user.toastImage(can, url) + silent? (can.user.download(can, url, name, nfs.PNG), can.user.toastSuccess(can)): can.user.toastImage(can, name, url) }) }) }, @@ -199,35 +201,56 @@ Volcanos("user", {info: {}, agent: { can.user.download(can, canvas, name, nfs.PNG) }}) }, - toastImage: function(can, url) { url = can.base.isString(url)? url: url.toDataURL("image/png") - var toast = can.user.toast(can, {content: {img: url, style: {"max-height": window.innerHeight/2, display: html.BLOCK}}, title: can._name, duration: -1, - action: shy({}, [cli.CLOSE, web.DOWNLOAD], function(event, button) { can.user.download(can, url, name, nfs.PNG) }), + toastImage: function(can, name, url) { url = can.base.isString(url)? url: url.toDataURL("image/png") + var toast = can.user.toast(can, {content: {img: url, style: {"max-height": window.innerHeight/2, display: html.BLOCK}}, title: name, duration: -1, + action: shy({}, [cli.CLOSE, web.DOWNLOAD], function(event, button) { + can.user.input(event, can, [{name: mdb.NAME, value: name}], function(list) { + can.user.download(can, url, list[0], nfs.PNG) + }) + }), }) can.onmotion.delay(can, function() { can.page.Select(can, toast._target, html.IMG, function(target) { can.page.style(can, toast._target, html.WIDTH, target.offsetWidth, html.LEFT, (window.innerWidth-target.offsetWidth)/2) }) }) }, - login: function(can, cb, method, auto) { method = can.base.Obj(method, ["登录", "扫码"]) - var meta = { - "登录": function(event, button, data) { can.run({}, [aaa.LOGIN, data[html.USERNAME], data[html.PASSWORD]], function(msg) { - if (!msg.Option(ice.MSG_USERNAME)) { return can.user.toast(can, "用户名或密码错误") } - can.page.Remove(can, ui._target), can.base.isFunc(cb) && cb() - }); return true }, - "扫码": function() { can.misc.WSS(can, {type: html.CHROME, cmd: "pwd"}, function(event, msg, cmd, arg) { if (!msg) { return } - if (cmd == "pwd") { return can.user.toast(can, arg[2], arg[1], -1), msg.Reply() } - if (cmd == ice.MSG_SESSID) { return can.misc.CookieSessid(can, arg[0]), msg.Reply(), can.user.reload(true) } - can.search(event, msg[ice.MSG_DETAIL]||[], function(msg) { msg.Reply() }) - }) }, - "授权": function() { can.misc.WSS(can, {type: html.CHROME, cmd: chat.SSO, back: location.href}, function(event, msg, cmd, arg) { if (!msg) { return } - if (cmd == "pwd") { return location.href = arg[1] } - if (cmd == ice.MSG_SESSID) { return can.misc.CookieSessid(can, arg[0]), msg.Reply(), can.user.reload(true) } - can.search(event, msg[ice.MSG_DETAIL]||[], function(msg) { msg.Reply() }) - }) }, - }; if (auto) { return meta["授权"]() } else if (method.length == 1) { meta[method[0]](); return } + login: function(can, cb, method, auto) { + function layout() { can.onmotion.delay(can, function() { can.page.Modify(can, ui._target, {className: "input login", style: {left: (window.innerWidth-ui._target.offsetWidth)/2, top: window.innerHeight/6}}) }) } - var ui = can.user.input({}, can, [{type: html.USERNAME}, {type: html.PASSWORD}], function(event, button, data) { return meta[button](event, button, data) }, method) - can.page.Modify(can, ui._target, {className: "input login", style: {left: (window.innerWidth-ui._target.offsetWidth)/2, top: window.innerHeight/6}}) + function input(name, type) { return {view: [html.ITEM, html.TR], list: [{type: html.TD, list: [{text: can.user.trans(can, name, { + "username": "用户", "password": "密码", + })}]}, {type: html.TD, list: [{type: html.INPUT, name: name, data: {type: type||html.TEXT}}]}]} } + + function button(name, cb) { + return {view: [html.ITEM, html.TR], list: [{type: "td"}, {type: "td", list: [{type: "input", value: can.user.trans(can, "login", "登录"), data: {type: "button"}, onclick: cb}] }]} + } + + var ui = can.onappend.tabview(can, { + "扫码授权": function(target) { + can.misc.WSS(can, {type: html.CHROME, cmd: cli.PWD}, function(event, msg, cmd, arg) { + if (cmd == ice.MSG_SESSID) { return can.misc.CookieSessid(can, arg[0]), msg.Reply(), can.user.reload(true) } + if (cmd == cli.PWD) { layout() + return can.page.Modify(can, target, arg[2]), can.page.Append(can, target, [{text: "
请授权: "+arg[0]}]) + } + }) + }, + "密码登录": function(target) { + var _ui = can.page.Append(can, target, [input("username"), input("password", "password"), + button("login", function(event) { + can.runAction(event, aaa.LOGIN, [_ui.username.value, _ui.password.value], function(msg) { + if (!msg.Option(ice.MSG_USERNAME)) { return can.user.toast(can, "用户名或密码错误") } + can.page.Remove(can, ui._target), can.base.isFunc(cb) && cb() + }) + }), + ]) + }, + "网关授权": function(target) { + can.misc.WSS(can, {type: html.CHROME, cmd: chat.SSO, back: location.href}, function(event, msg, cmd, arg) { + if (cmd == cli.PWD) { return location.href = arg[1] } + }) + }, + }, auto? ["网关授权"]: can.base.Obj(method, can.user.isMobile? ["密码登录"]: ["扫码授权"]), can.page.Append(can, document.body, [{view: "input login"}])._target) + layout() }, logout: function(can, force) { if (force||can.user.confirm("logout?")) { can.runAction({}, aaa.LOGOUT, [], function(msg) { can.misc.Search(can, chat.SHARE)? can.misc.Search(can, chat.SHARE, ""): can.user.reload(true) diff --git a/page/index.css b/page/index.css index 74e453e6..136e5d95 100644 --- a/page/index.css +++ b/page/index.css @@ -3,7 +3,7 @@ body { background-color:black; color:cyan; font-size:16px; overflow:hidden; } legend { background-color:cadetblue; color:white; padding:0 20px; margin-right:2px; float:left; } select { background-color:black; color:cyan; padding:0 10px; margin:0 2px; border:0; } textarea { background-color:cyan; width:400px; padding:5px; border:0; margin:2px; } -input[type=password] { background-color:cyan; color:black; padding:0 5px; border:0; width:90px; } +input[type=password] { background-color:cyan; color:black; padding:0 5px; margin:0 2px; border:0; width:90px; } input[type=text] { background-color:cyan; color:black; padding:0 5px; margin:0 2px; border:0; width:90px; } input[name=cmd] { background-color:black; color:white; width:320px; } input[name=url] { width:320px; } @@ -31,6 +31,7 @@ table.layout td.content div.toggle.project { padding-top:50px; height:100px; wid table.layout td.content div.toggle.profile { padding-top:50px; height:100px; width:15px; top:20%; right:0px; border-top-left-radius:10px; border-bottom-left-radius:10px; } table.layout td.content div.toggle.display { margin-top:-15px; height:15px; width:100px; position:sticky; left:40%; border-top-left-radius:10px; border-top-right-radius:10px; overflow:hidden; } table.layout td.content div.toggle.display>div { text-align:center; width:100px; transform: rotate(-90deg) translate(5px, 0px); } +table.content { width:-webkit-fill-available;} table.content thead { position:sticky; top:2px; } table.content th { background-color:steelblue; padding:2px 6px; } table.content td { padding:2px 6px; } @@ -97,10 +98,11 @@ body>div.input div.content { overflow:auto; } body>div.input td { padding:5px; } body>div.input select { width:181px; } body>div.input input[type=text] { width:171px; } -body>div.input input[name=password] { padding:5px; border:0; width:171px; background-color:white; } +body>div.input input[name=password] { padding:5px; border:0; width:171px; } body>div.input input[name=username] { padding:5px; border:0; width:171px; } body>div.input textarea { height:120px; width:171px; } -body>div.input.login { padding:10px; background-color:steelblue; } +body>div.input.login { padding:10px; background-color:steelblue; min-width:240px; } +body>div.input.login input[type=button] { width:90px; } body>div.upload div.item { float:left; } body>div.upload div.output { border:solid 1px red; } body>div.upload div.progress { background-color:red; height:10px; width:0; } @@ -113,7 +115,7 @@ body>div.upload input[type=file] { width:320px; } * { tab-size:4; } textarea { tab-size:2; height:60px; } legend { font-size:1.2rem; height:31px; } -select, input { font-size:1.1rem; height:31px; } +select, input { font-size:1.0rem; height:31px; } table.content th, table.content td, div.zone>div.name, div.item, div.code, code.story, div.story[data-type=spark] { font-size:1.1rem; font-family:monospace; } div.action>div.tabs { padding:5px 10px; height:21px; } div.status>div.item { padding:4px; height:22px; } @@ -220,6 +222,7 @@ body.mobile.simple { overflow:hidden; } body.mobile legend { font-size:1.6rem; height:38px; } body.mobile select { font-size:1.4rem; height:38px; border-radius:0; margin-right:10; } body.mobile textarea { font-size:1.2rem; border-radius:0; } +body.mobile input[type=password] { font-size:1.2rem; height:38px; border-radius:0; margin-right:5px; } body.mobile input[type=text] { font-size:1.2rem; height:38px; border-radius:0; margin-right:5px; } body.mobile input[type=button] { font-size:1.2rem; height:38px; border-radius:0; } body.mobile fieldset.float input[type=button] { font-size:1.4rem; height:38px; } diff --git a/panel/action.js b/panel/action.js index 6d95767d..ffb8b49a 100644 --- a/panel/action.js +++ b/panel/action.js @@ -3,7 +3,7 @@ Volcanos(chat.ONIMPORT, {_init: function(can, msg) { can.onmotion.clear(can) var river = can.Conf(chat.RIVER), storm = can.Conf(chat.STORM); can.core.Next(msg.Table(), function(item, next) { item.type = chat.PLUGIN, item.inputs = can.base.Obj(item.inputs||item.list), item.feature = can.base.Obj(item.feature||item.meta) can.onappend.plugin(can, item, function(sub, meta, skip) { can.onimport._run(can, sub, function(event, cmds, cb) { - return can.run(event, can.misc.concat(can, [river, storm, meta.id||meta.index], cmds), cb) + return can.run(event, can.misc.concat(can, river == web.SHARE? [ctx.ACTION]: [], [river, storm, meta.id||meta.index], cmds), cb) }), can.onimport._tabs(can, sub, meta), skip || next() }) }, function() { can.onaction.layout(can, can.misc.SearchOrConf(can, html.LAYOUT), true) }) }, @@ -35,7 +35,16 @@ Volcanos(chat.ONIMPORT, {_init: function(can, msg) { can.onmotion.clear(can) }, }) Volcanos(chat.ONKEYMAP, {_init: function(can, target) { can.onkeymap._build(can) - can.onengine.listen(can, chat.ONKEYDOWN, function(msg, model) { can._keylist = can.onkeymap._parse(msg._event, can, model, can._keylist||[], can._output) }) + can.onengine.listen(can, chat.ONKEYDOWN, function(msg, model) { + if (event.ctrlKey && event.key >= "1" && event.key <= "9") { + var sub = can._plugins[parseInt(event.key)-1]; if (sub) { + can._output.scrollTop = sub._target.offsetTop-html.PLUGIN_MARGIN + sub._header_tabs.click() + // can.onmotion.delay(can, function() { sub.Focus() }) + } + } + can._keylist = can.onkeymap._parse(msg._event, can, model, can._keylist||[], can._output) + }) }, _mode: { normal: { j: function(event, can, target) { target.scrollBy(0, event.ctrlKey? 300: 30) }, @@ -43,7 +52,12 @@ Volcanos(chat.ONKEYMAP, {_init: function(can, target) { can.onkeymap._build(can) b: function(event, can) { can.search(event, ["Header.onaction.black"]) }, w: function(event, can) { can.search(event, ["Header.onaction.white"]) }, - c: function(event, can) { can.user.toimage(event, can, can.user.title(), can._target.parentNode, true) }, + p: function(event, can) { can.search(event, ["Header.onaction.print"]) }, + c: function(event, can) { can.user.toimage(can, can.user.title(), can._target.parentNode, true) }, + + t: function(event, can) { can.onaction.layout(can, can.Conf(chat.LAYOUT) == TABVIEW? ice.AUTO: TABVIEW, true) }, + h: function(event, can) { can.onaction.layout(can, can.Conf(chat.LAYOUT) == HORIZON? ice.AUTO: HORIZON, true) }, + v: function(event, can) { can.onaction.layout(can, can.Conf(chat.LAYOUT) == VERTICAL? ice.AUTO: VERTICAL, true) }, ":": function(event, can) { can.onengine.signal(can, chat.ONCOMMAND_FOCUS), can.onkeymap.prevent(event) }, " ": function(event, can) { can.onengine.signal(can, chat.ONSEARCH_FOCUS), can.onkeymap.prevent(event) }, @@ -124,7 +138,7 @@ Volcanos(chat.ONACTION, {_init: function(can, target) { if (button == ice.AUTO) { button = "" } else { can.page.ClassList.add(can, can._target, can.Conf(html.LAYOUT, button)) } can.user.isMobile || can.Mode() || (can.onmotion.toggle(can, can._root.River._target, true), can.onmotion.toggle(can, can._root.Footer._target, true)) can.user.isMobile && can.Mode() && can.page.style(can, can._target, html.WIDTH, "", html.HEIGHT, "") - can.onlayout._init(can), can._header_tabs && can.onmotion.hidden(can, can._header_tabs) + can.onlayout._init(can), can._header_tabs && can.onmotion.hidden(can, can._header_tabs), can.Conf(chat.LAYOUT, button) var cb = can.onlayout[button]; can.base.isFunc(cb) && cb(can, silent) || can.onlayout._plugin(can, button) }, help: function(can, button) { can.user.open("/help/"+button+".shy") }, @@ -175,7 +189,10 @@ Volcanos(chat.ONEXPORT, { cb(can.page.SelectArgs(can, sub._option, "", function(target) { return target.value }), sub, next, index, array) }) }, plugin: function(can, msg, arg, fields) { can.core.List(can._plugins, function(sub) { var meta = sub.Conf(); if (meta.index.indexOf(arg[1]) == -1) { return } - var data = {ctx: ice.CAN, cmd: can._name, type: mdb.PLUGIN, name: sub._legend.innerHTML, text: shy("跳转", function(event) { sub.Focus() })} + var data = {ctx: ice.CAN, cmd: can._name, type: mdb.PLUGIN, name: sub._legend.innerHTML, text: shy("跳转", function(event) { + can._output.scrollTop = sub._target.offsetTop-html.PLUGIN_MARGIN + // sub.Focus() + })} if (meta.index) { data.context = "", data.command = meta.index } else if (meta.cmd) { data.context = meta.ctx, data.command = meta.cmd } else { return } msg.Push(data, fields) }) }, @@ -201,7 +218,11 @@ Volcanos(chat.ONENGINE, {_engine: function(event, sup, msg, can, cmds, cb) { }}) Volcanos(chat.ONPLUGIN, { plugin: shy("默认插件", [mdb.NAME, ice.LIST, ice.BACK]), - layout: shy("界面布局", ["layout:select=auto,tabs,tabview,horizon,vertical,free,grid,flow,page", ice.RUN], function(can, msg, arg) { can.onaction.layout(can, arg[0], true) }), + layout: shy("界面布局", { + _init: function(can) { + can.Option(chat.LAYOUT, can.getAction(chat.LAYOUT)) + }, + }, ["layout:select=auto,tabs,tabview,horizon,vertical,free,grid,flow,page", ice.RUN], function(can, msg, arg) { can.onaction.layout(can, arg[0], true) }), "parse": shy("生成网页", { "show": function(can, msg, arg) { var name = arg[1]||ice.CAN; can.isCmdMode() && can.user.title(name) diff --git a/panel/footer.js b/panel/footer.js index cccef197..56a9a920 100644 --- a/panel/footer.js +++ b/panel/footer.js @@ -4,7 +4,6 @@ Volcanos(chat.ONIMPORT, {_init: function(can, msg, target) { can.onimport._state(can, msg, target) can.onimport._toast(can, msg, target) can.onimport._command(can, msg, target) - can["cli"] = {} }, _title: function(can, msg, target) { can.user.isMobile || can.core.List(msg.result, function(item) { can.page.Append(can, target, [{view: [chat.TITLE, html.DIV, item], title: "联系站长"}]) }) }, _state: function(can, msg, target) { can.core.List(can.base.Obj(can.Conf(chat.STATE)||msg.Option(chat.STATE), [NTIP, NCMD, NLOG]).reverse(), function(item) { @@ -17,7 +16,7 @@ Volcanos(chat.ONIMPORT, {_init: function(can, msg, target) { case cli.CLOSE: can.cli && can.cli.close(); break case cli.CLEAR: can.cli && can.cli.close(); break default: - can.runAction(event, ice.RUN, can.core.Split(event.target.value, ice.SP), function(msg) { can.cli && can.cli.close && can.cli.close(); var ui = can.onexport.float(can, msg, "cli") + can.runAction(event, ice.RUN, can.core.Split(event.target.value, ice.SP), function(msg) { can.cli && can.cli.close && can.cli.close(), can["cli"] = {}; var ui = can.onexport.float(can, msg, "cli") can.getActionSize(function(left) { can.page.style(can, ui._target, html.LEFT, left, html.RIGHT, "", html.BOTTOM, can.onexport.height(can)) }) }) } }}, "", target, [chat.TITLE, ice.CMD]) }, diff --git a/panel/header.css b/panel/header.css index b7e7c77b..175bfbae 100644 --- a/panel/header.css +++ b/panel/header.css @@ -7,4 +7,6 @@ fieldset.Header>div.output div.state { float:right; } fieldset.Header>div.output div.state.avatar { padding:0; height:31px; } fieldset.Header>div.output div.state.avatar>img { height:31px; } fieldset.Header>div.output div.search { margin-left:20px; float:left; } -fieldset.Header>div.output div.search>input { margin-top:-5px; border-radius:0; } \ No newline at end of file +fieldset.Header>div.output div.search>input { margin-top:-5px; border-radius:0; } + +fieldset.Header>div.output river { margin-right:100px; } \ No newline at end of file diff --git a/panel/header.js b/panel/header.js index 362c7a8e..cfcfb5a3 100644 --- a/panel/header.js +++ b/panel/header.js @@ -46,7 +46,7 @@ Volcanos(chat.ONIMPORT, {_init: function(can, msg, target) { background: function(event, can, background) { if (can.user.isExtension || can.user.isLocalFile) { return } can.runAction(event, aaa.BACKGROUND, [background], function(msg) { can.user.info.background = background, can.onimport._background(can, msg), can.user.toastSuccess(can) }) }, - topic: function(can, topic) { topic && (can._topic = topic), can.user.topic(can, can.onexport.topic(can)) }, + topic: function(can, topic) { topic && (can._topic = can.base.Obj(topic).join(ice.SP)), can.user.topic(can, can.onexport.topic(can)) }, menu: function(can, cmds, cb, trans) { can.base.isString(cmds) && (cmds = [cmds]) return can.page.Append(can, can._output, [{type: cmds[0], list: can.core.List(can.base.getValid(cmds.slice(1), [cmds[0]]), function(item) { if (can.base.isString(item)) { return {view: [html.MENU, html.DIV, can.user.trans(can, item, trans)], onclick: function(event) { can.base.isFunc(cb) && cb(event, item, [item]) }} } @@ -64,20 +64,20 @@ Volcanos(chat.ONACTION, { "setting", "设置", chat.BLACK, "黑色主题", chat.WHITE, "白色主题", chat.PRINT, "打印主题", code.WEBPACK, "打包页面", web.TOIMAGE, "生成图片", "shareuser", "共享用户", "setnick", "设置昵称", aaa.PASSWORD, "修改密码", aaa.LANGUAGE, "语言地区", aaa.CHINESE, "中文", web.CLEAR, "清除背景", aaa.LOGOUT, "退出登录", ), - onmain: function(can, msg) { can.onimport.topic(can) + onmain: function(can) { can.onimport.topic(can) can.run({}, [], function(msg) { if (!can.Conf(aaa.USERNICK, msg.Option(aaa.USERNICK)||msg.Option(ice.MSG_USERNICK)||msg.Option(ice.MSG_USERNAME))) { - return msg.Option(chat.SSO)? can.user.jumps(msg.Option(chat.SSO)): can.user.login(can, function() { can.onengine.signal(can, chat.ONMAIN, msg) }, msg.Option(aaa.LOGIN), msg.Option("login.dev")) + return msg.Option(chat.SSO)? can.user.jumps(msg.Option(chat.SSO)): can.user.login(can, function() { can.onengine.signal(can, chat.ONMAIN, msg) }, msg.Option(aaa.LOGIN), msg.Option(ice.DEV)) } can.user.info.usernick = can.Conf(aaa.USERNICK), can.user.info.language = can.misc.Search(can, aaa.LANGUAGE)||msg.Option(aaa.LANGUAGE) can.user.info.background = msg.Option(aaa.BACKGROUND), can.user.info.avatar = msg.Option(aaa.AVATAR) msg.Option(nfs.SCRIPT) && can.require(can.base.Obj(msg.Option(nfs.SCRIPT)), function(can) { can.onaction.source(can, msg) }) can.onmotion.clear(can), can.onimport._init(can, msg, can._output), can.ondaemon._init(can), can.onengine.signal(can, chat.ONLOGIN, msg) }) }, - onsize: function(can, msg) { can.onimport.topic(can) }, - onstorm_select: function(can, msg, river, storm) { can.Conf(chat.RIVER, river), can.Conf(chat.STORM, storm) }, - onaction_cmd: function(can, msg) { can.onmotion.hidden(can) }, + onsize: function(can) { can.onimport.topic(can) }, + onstorm_select: function(can, river, storm) { can.Conf(chat.RIVER, river), can.Conf(chat.STORM, storm) }, + onaction_cmd: function(can) { can.onmotion.hidden(can) }, onsearch_focus: function(can) { can._search && can._search.focus() }, - onshare: function(can, msg, args) { can.user.share(can, can.request(event), [ctx.ACTION, chat.SHARE].concat(args||[])) }, + onshare: function(can, msg, args) { can.user.share(can, msg, [ctx.ACTION, chat.SHARE].concat(args||[])) }, onwebpack: function(can, msg) { can.user.input(msg._event, can, [{name: mdb.NAME, value: can.user.title()}], function(data) { can.core.Item(Volcanos.meta.pack, function(key, msg) { can.core.List(["_event", "_can", "_xhr", ice.MSG_SESSID, ""], function(key) { delete(msg[key]) }) }) @@ -88,11 +88,11 @@ Volcanos(chat.ONACTION, { }, title: function(event, can) { var args = {}; can.core.List([chat.TITLE, chat.TOPIC], function(key) { var value = can.misc.Search(can, key); value && (args[key] = value) }); can.user.jumps(can.misc.MergeURL(can, args, true)) }, - black: function(event, can, button) { can.onimport.topic(can, button), can.onlayout._init(can) }, - white: function(event, can, button) { can.onimport.topic(can, button), can.onlayout._init(can) }, + black: function(event, can, button) { can.onimport.topic(can, button) }, + white: function(event, can, button) { can.onimport.topic(can, button) }, print: function(event, can, button) { can.onimport.topic(can, [chat.WHITE, button]), can.onengine.signal(can, chat.ONPRINT) }, webpack: function(event, can) { can.onengine.signal(can, "onwebpack", can.request(event)) }, - toimage: function(event, can) { can.user.toimage(event, can, can.user.title(), can._target.parentNode) }, + toimage: function(event, can) { can.onmotion.clearCarte(can), can.user.toimage(can, can.user.title(), can._target.parentNode) }, carte: function(event, can, list, cb) { can.user.carte(event, can, can.onaction, list, cb) }, share: function(event, can, args) { can.user.share(can, can.request(event), [ctx.ACTION, chat.SHARE].concat(args||[])) }, @@ -129,8 +129,8 @@ Volcanos(chat.ONPLUGIN, { location: shy("请求地址", { copy: function(can) { can.user.copy(msg._event, can, location.href) }, }, [mdb.LINK, ice.LIST, ice.COPY], function(can, msg, cb) { - can.run(can.request({}, kit.Dict(mdb.LINK, location.href)), [web.SHARE], function(res) { - msg.Echo(res.Append(mdb.TEXT)).Echo(ice.NL).Echo(can.page.Format(html.A, res.Append(mdb.NAME))), can.base.isFunc(cb) && cb(msg) + can.runAction(can.request({}, kit.Dict(mdb.LINK, location.href)), web.SHARE, [], function(res) { + msg.Echo(res.Append(mdb.TEXT)).Status(kit.Dict(mdb.LINK, res.Append(mdb.NAME))), can.base.isFunc(cb) && cb(msg) }) }), cookie: shy("请求参数", [mdb.NAME, mdb.VALUE, ice.LIST, ice.BACK], function(can, msg, arg) { diff --git a/panel/river.js b/panel/river.js index b6a6a9c1..f152d4e5 100644 --- a/panel/river.js +++ b/panel/river.js @@ -24,7 +24,7 @@ Volcanos(chat.ONIMPORT, {_init: function(can, msg) { var select; can.page.Append can.onaction.carte(event, can, list, function(event, button, meta) { meta[button](event, can, button, river, storm) }) }, }) -Volcanos(chat.ONACTION, {list: [mdb.CREATE, web.REFRESH, web.SHARE], _init: function(can) { can.onmotion.hidden(can) }, +Volcanos(chat.ONACTION, {list: [mdb.CREATE, web.REFRESH], _init: function(can) { can.onmotion.hidden(can) }, onlogin: function(can, msg) { can.run({}, [], function(msg) { if (msg.Option(ice.MSG_RIVER) == "_share") { return } can.onmotion.clear(can), can.onimport._main(can, msg), can.onimport._init(can, msg), can.onimport._menu(can, msg) can.user.isMobile ||can.user.isExtension || can.user.mod.isPod || can.onmotion.toggle(can, can._target, true) @@ -83,7 +83,9 @@ Volcanos(chat.ONDETAIL, {list: ["添加应用", "重命名群组", "删除群组 }) Volcanos(chat.ONEXPORT, {width: function(can) { return can._target.offsetWidth }, storm: function(can, msg, arg) { can.core.Item(can._root.river, function(river, value) { can.core.Item(value.storm, function(storm, item) { if (arg[1] != "" && storm.indexOf(arg[1]) == -1 && item.name.indexOf(arg[1]) == -1) { return } - msg.Push({ctx: ice.CAN, cmd: can._name, type: river, name: storm, text: shy("跳转", function(event) { can.onaction.action(event, can, river, storm) })}) + msg.Push({ctx: ice.CAN, cmd: can._name, type: river, name: storm, text: shy("跳转", function(event) { + can.onaction.action(event, can, river, storm) + })}) }) }) }, }) Volcanos(chat.ONENGINE, {_engine: function(event, can, msg, panel, cmds, cb) { var list = can.river diff --git a/plugin/input.js b/plugin/input.js index 79b7ba67..f3caaa93 100644 --- a/plugin/input.js +++ b/plugin/input.js @@ -14,7 +14,7 @@ Volcanos(chat.ONACTION, { switch (event.key) { case "b": can.CloneInput(); break case "m": can.CloneField(); break - default: return + default: can.onkeymap.selectOutput(event, can.sup); return } can.onkeymap.prevent(event) }, }) diff --git a/plugin/input/date.js b/plugin/input/date.js index e3cad3d4..e6a9fdd4 100644 --- a/plugin/input/date.js +++ b/plugin/input/date.js @@ -50,7 +50,7 @@ Volcanos(chat.ONFIGURE, {date: { } show(now), can._show = function(d) { _cb(show(new Date(now.getTime()+d*24*3600*1000))) } })}, - onkeydown: function(event, can, meta, cb, target, sub, last) { if (sub.hidden()) { return } switch (event.key) { + onkeydown: function(event, can, meta, cb, target, sub, last) { if (sub && sub.hidden()) { return last(event) } switch (event.key) { case "n": can.page.SelectInput(can, sub._action, mdb.NEXT, function(target) { target.click() }); break case "p": can.page.SelectInput(can, sub._action, mdb.PREV, function(target) { target.click() }); break case "t": can.page.SelectInput(can, sub._action, "today", function(target) { target.click() }); break @@ -58,6 +58,6 @@ Volcanos(chat.ONFIGURE, {date: { case "k": sub._show(-7); break case "h": sub._show(-1); break case "l": sub._show(1); break - default: return + default: last(event); return } can.onkeymap.prevent(event) }, } }) diff --git a/plugin/local/code/vimer.js b/plugin/local/code/vimer.js index 1e5cf3b6..d21c6673 100644 --- a/plugin/local/code/vimer.js +++ b/plugin/local/code/vimer.js @@ -39,16 +39,17 @@ Volcanos(chat.ONFIGURE, { } list[path] = item }) } - can.runAction({}, code.FAVOR, ["_recent_cmd"], function(msg) { - show(msg, function(item) { return [{text: [item.name||item.file, html.DIV, html.ITEM], onclick: function(event) { - can.onimport.tabview(can, can.Option(nfs.PATH), item.file, ctx.INDEX) - }}] }) - }) can.runAction({}, code.FAVOR, ["_recent_file"], function(msg) { show(msg, function(item, path) { return [{text: [path.split(ice.PS).slice(-2).join(ice.PS), html.DIV, html.ITEM], onclick: function(event) { can.onimport.tabview(can, item.path, item.file) }}] }) }) + return + can.runAction({}, code.FAVOR, ["_recent_cmd"], function(msg) { + show(msg, function(item) { return [{text: [item.name||item.file, html.DIV, html.ITEM], onclick: function(event) { + can.onimport.tabview(can, can.Option(nfs.PATH), item.file, ctx.INDEX) + }}] }) + }) }, source: function(can, target, zone, path) { var total = 0 function show(target, path) { can.run(can.request({}, {dir_root: path, dir_deep: true}), [nfs.PWD], function(msg) { var list = msg.Table() @@ -59,12 +60,10 @@ Volcanos(chat.ONFIGURE, { if (path.length == 1) { return show(target, path[0]) } can.page.Remove(can, target.previousSibling) can.onimport.zone(can, can.core.List(path, function(path) { return {name: path, _init: function(target) { show(target, path) }} }), target) - }, - website: function(can, target, zone) { - can.run(can.request({}, {dir_root: "src/website/", dir_deep: true}), [nfs.PWD], function(msg) { var list = msg.Table() - can.onimport.tree(can, list, nfs.PATH, ice.PS, function(event, item) { can.onimport.tabview(can, "src/website/", item.path) }, target) - zone._total(msg.Length()) - }, true) + can.sup.onexport.link = function(can) { var meta = can.Conf(), args = can.Option() + args.cmd = meta.index||can.core.Keys(meta.ctx, meta.cmd), args.path = path.join(ice.FS), args.topic = chat.BLACK + return can.misc.MergePodCmd(can, args, true) + } }, dream: function(can, target, zone) { var call = arguments.callee can.runAction({}, ice.RUN, [web.DREAM], function(msg) { msg.Table(function(item) { var color = item.status == cli.START? "": "gray" @@ -82,11 +81,6 @@ Volcanos(chat.ONFIGURE, { code.PUBLISH, function(event, can, button) { can.runAction(event, button, [], function(msg) { can.user.toastConfirm(can, msg.Result(), button) }) }, )) }, - xterm: function(can, target, zone) { - can.runAction({}, ice.RUN, [code.XTERM], function(msg) { msg.Table(function(item) { - can.onimport.item(can, item, function(event) { can.onimport.tabview(can, can.Option(nfs.PATH), item.hash, code.XTERM) }, function(event) {}, target) - }), zone._total(msg.Length()) }) - }, plugin: function(can, target, zone) { var total = 0 can.onimport.tree(can, can.core.Item(can.onengine.plugin.meta, function(key) { return total++, {index: key} }), ctx.INDEX, ice.PT, function(event, item) { can.onimport.tabview(can, can.Option(nfs.PATH), can.core.Keys("can", item.index), ctx.INDEX) diff --git a/plugin/local/wiki/draw.js b/plugin/local/wiki/draw.js index 06c6eb8f..667a8b97 100644 --- a/plugin/local/wiki/draw.js +++ b/plugin/local/wiki/draw.js @@ -179,7 +179,7 @@ Volcanos(chat.ONDETAIL, {list: [cli.START, ice.COPY, html.LABEL, "toimage", mdb. target.Value(mdb.TEXT, can.onexport._pid(can, can.onimport.block(can, html.TEXT, can.onexport._text(can, target, can.onfigure._get(can, target), {inner: list[0]}), target.Group()) )) }) }, - toimage: function(event, can) { can.user.toimage(event, can, can.Option(nfs.PATH).split(ice.PS).pop().split(ice.PT)[0], can.svg) }, + toimage: function(event, can) { can.user.toimage(can, can.Option(nfs.PATH).split(ice.PS).pop().split(ice.PT)[0], can.svg) }, remove: function(event, can) { if (target == can.svg) { return } var target = event.target can.core.List(target.Value(ice.SHIP), function(item) { can.ondetail._select(can, item.pid, function(target) { can.page.Remove(can, target) }) }) can.ondetail._select(can, target.Value(mdb.TEXT), function(target) { can.page.Remove(can, target) }), can.page.Remove(can, target) diff --git a/plugin/local/wiki/word.js b/plugin/local/wiki/word.js index fa826206..bc0e399d 100644 --- a/plugin/local/wiki/word.js +++ b/plugin/local/wiki/word.js @@ -102,7 +102,7 @@ Volcanos(chat.ONIMPORT, {_init: function(can, msg, target) { can.onmotion.clear( target.onclick = function(event) { can.runActionCommand(can.request(event, meta), meta.index, [nfs.FIND, event.target.innerHTML]) } target.oncontextmenu = function(event) { var ui = can.user.carte(event, can, kit.Dict(mdb.EXPORT, function(event, can, button) { - can.user.toimage(event, can, "hi", target) + can.user.toimage(can, "hi", target) })); can.page.style(can, ui._target, {left: event.clientX, top: event.clientY}) } }, diff --git a/plugin/state.js b/plugin/state.js index 62b5115d..8bf08933 100644 --- a/plugin/state.js +++ b/plugin/state.js @@ -141,7 +141,7 @@ Volcanos(chat.ONACTION, {list: [ ] can.user.copy(event, can, list[0]) }, - "生成图片": function(event, can) { can.user.toimage(event, can, can._name) }, + "生成图片": function(event, can) { can.user.toimage(can, can._name) }, "打包页面": function(event, can) { can.onengine.signal(can, "onwebpack", can.request(event)) }, "保存参数": function(event, can) { can.search(event, ["River.ondetail.保存参数"]) }, diff --git a/proto.js b/proto.js index e6c3d311..e77fe80c 100644 --- a/proto.js +++ b/proto.js @@ -12,6 +12,7 @@ var ice = { VIEW: "view", MODE: "mode", SHIP: "ship", EXEC: "exec", POD: "pod", CTX: "ctx", CMD: "cmd", ARG: "arg", OPT: "opt", + DEV: "dev", CAN: "can", RUN: "run", RES: "res", ERR: "err", CAN_PLUGIN: "can.plugin", @@ -65,6 +66,7 @@ var cli = { COLOR: "color", WHITE: "white", BLACK: "black", RED: "red", GREEN: "green", BLUE: "blue", YELLOW: "yellow", CYAN: "cyan", PURPLE: "purple", MAGENTA: "magenta", GLASS: "#0000", MAKE: "make", MAIN: "main", EXEC: "exec", DONE: "done", COST: "cost", FROM: "from", CLEAR: "clear", + PWD: "pwd", } var aaa = { LOGIN: "login", LOGOUT: "logout", INVITE: "invite", TOKEN: "token",