diff --git a/frame.js b/frame.js index ce3885b2..23d31218 100644 --- a/frame.js +++ b/frame.js @@ -35,7 +35,8 @@ Volcanos(chat.ONENGINE, { names = can.base.MergeURL(names, ice.MSG_INDEX, sub.ConfIndex()), can.page.exportValue(sub, msg) can.onengine.signal(panel, chat.ONREMOTE, can.request({}, {_follow: panel._follow, _msg: msg, _cmds: cmds, names: names})) can.misc.Run(event, can, {names: names}, cmds, function(msg) { - toast && can.user.toastSuccess(msg._can, _toast), toast && toast.close && toast.close(), toast = true, delete(sub._toast), delete(sub.__toast) + toast && can.user.toastSuccess(msg._can, _toast), toast && toast.close && toast.close(), toast = true + // delete(sub._toast), delete(sub.__toast) can.base.isFunc(cb) && cb(msg), Volcanos.meta.pack[can.core.Keys(panel._name, cmds.join(mdb.FS))] = msg }) }, @@ -218,8 +219,9 @@ Volcanos(chat.ONAPPEND, { }[item.name||item||""]; if (!icon) { return } item.style = "icons" can.page.Append(can, option, [{view: [[html.ITEM, html.ICON, icon.name, item.name], html.DIV, can.page.unicode[icon.name]], title: can.user.trans(can, item.name), onclick: function(event) { can.onengine.signal(can, "onevent", can.request(event, {_type: html.OPTION})) + var msg = can.request(event, {_toast: can.base.isIn(item.name, "list", "back")? "reload": item.name}), cmds = [ctx.ACTION, item.name]; if (icon.cb) { return icon.cb(event) } - var msg = can.request(event), cmds = [ctx.ACTION, item.name]; msg.RunAction(event, can.sub, cmds) || msg.RunAction(event, can, cmds) || can.Update(event, cmds) + msg.RunAction(event, can.sub, cmds) || msg.RunAction(event, can, cmds) || can.Update(event, cmds) }}]) }) while (args.length > 0) { if (args[args.length-1] != "") { break } args.pop() } @@ -768,6 +770,8 @@ Volcanos(chat.ONAPPEND, { var sup = can._fields? can.sup: can; if (sup.onimport._process(sup, msg)) { return } }) } + var style = can.page.buttonStyle(can, target.name) + can.onappend.style(can, style, target) }) } 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) }, @@ -1394,6 +1398,8 @@ Volcanos(chat.ONKEYMAP, { } }), can.onkeymap._engine[mode] = engine }) }, _parse: function(event, can, mode, target, list) { mode = mode||mdb.PLUGIN, target = target||can._output; if (!list) { list = target._key_list||[], target._key_list = list } + delete(event._msg) + var msg = can.request(event) if (event.metaKey && !can.user.isWebview) { return list } if ([code.SHIFT, code.CONTROL, code.META, code.ALT].indexOf(event.key) > -1) { return list } list.push(event.key); for (var pre = 0; pre < list.length; pre++) { if ("0" <= list[pre] && list[pre] <= "9") { continue } break } var count = parseInt(list.slice(0, pre).join(""))||1, map = can.onkeymap._mode[mode] diff --git a/index.css b/index.css index 2bcbd07b..30ed3799 100644 --- a/index.css +++ b/index.css @@ -212,7 +212,7 @@ div.item.card div.status { font-size:12px; color:gray; } div.item.card div.status span { margin-right:5px; } div.item.card div.action { max-width:100%; display:flex; align-items:center; } div.item.card div.action { position:absolute; right:0; } -div.item.card div.action input[type=button] { border:none; color:var(--notice-bg-color); margin-left:5px; } +div.item.card div.action input[type=button] { background-color:transparent; border:none; color:var(--notice-bg-color); margin-left:5px; } div.item.card div.action input[type=button].danger { color:var(--danger-bg-color) } div.item.card div.action input[type=button]:last-child { margin-right:5px; } div.item.card div.output { padding:10px 0; display:flex; transition:left .2s; } @@ -438,8 +438,8 @@ body div.input.float select { width:var(--form-width) !important; } body div.input.float input.select[type=button] { width:var(--form-width) !important; } body div.input.float input:not([type=button]) { width:var(--form-width) !important; padding-left:24px; } body div.input.float input[type=text] { width:var(--form-width) !important; padding-left:24px; } -body div.input.float input[name=cancel] { border:var(--box-danger); } -body div.input.float input[name=submit] { border:var(--box-notice); } +body div.input.float input[name=cancel] { border:var(--box-danger); background-color:transparent; color:var(--danger-bg-color); } +body div.input.float input[name=submit] { border:var(--box-notice); background-color:var(--notice-bg-color); color:var(--notice-fg-color); } body div.input.float input[name=submit]:hover { background-color:var(--notice-bg-color); color:var(--notice-fg-color); } body div.input.float input[name=cancel]:hover { background-color:var(--danger-bg-color); color:var(--danger-fg-color); } body div.input.float div.action { padding:var(--table-padding); width:100%; position:sticky; bottom:0; flex-direction:row-reverse; cursor:move; } diff --git a/lib/page.js b/lib/page.js index 814c20f3..0a9632de 100644 --- a/lib/page.js +++ b/lib/page.js @@ -505,7 +505,7 @@ Volcanos("page", { return action }, buttonStyle: function(can, name) { - return can.core.Value(can.onaction, ["_trans", "style", name])||(can.base.isIn(name, mdb.CREATE, mdb.INSERT, mdb.IMPORT, nfs.CLONE, cli.START, ctx.RUN, web.UPLOAD, web.CONFIRM, aaa.LOGIN, code.AUTOGEN, "sso", "add", "pull", "push", "commit", "preview", "auto-preview", ice.APP)? html.NOTICE: + return can.Conf("_style."+name)||can.core.Value(can.onaction, ["_trans", "style", name])||(can.base.isIn(name, mdb.CREATE, mdb.INSERT, mdb.IMPORT, nfs.CLONE, cli.START, ctx.RUN, web.UPLOAD, web.CONFIRM, aaa.LOGIN, code.AUTOGEN, "sso", "add", "pull", "push", "submit", "commit", "preview", "auto-preview", ice.APP)? html.NOTICE: can.base.isIn(name, mdb.REMOVE, "rename", mdb.DELETE, mdb.PRUNES, mdb.PRUNE, nfs.TRASH, cli.RESTART, cli.STOP, cli.CLOSE, cli.REBOOT, web.CANCEL, code.UPGRADE, "reject", "del", "drop", "access", "kill", "prockill")? html.DANGER: "") }, exportValue: function(can, msg, target) { target = target||can._output diff --git a/lib/user.js b/lib/user.js index 336579d0..f5928717 100644 --- a/lib/user.js +++ b/lib/user.js @@ -97,56 +97,72 @@ Volcanos("user", { var carte = can.user.toast(can, {content: content, title: title, action: action||[cli.CLOSE], duration: -1}) can.page.style(can, carte._target, html.TOP, 200, html.BOTTOM, ""); return carte }, - toastProcess: function(can, content, title, progress) { return can.user.toast(can, {content: "🕑 "+(content||ice.PROCESS)+(can.user.isEnglish(can)? "": "中..."), title: title, duration: -1, progress: progress}) }, - toastFailure: function(can, content, title) { return can.user.toast(can, {content: "❌ "+(content||ice.FAILURE), title: title, duration: -1}) }, + toastProcess: function(can, content, title, progress) { + content = can.user.trans(can, content||""), content += can.user.trans(can, " process", "中...") + return can.user.toast(can, {content: "🕑 "+content, title: title, duration: -1, progress: progress}) + }, + toastFailure: function(can, content, title) { + content = can.user.trans(can, content||""), content += can.user.trans(can, " failure", "失败") + return can.user.toast(can, {content: "❌ "+content, title: title, duration: -1}) + }, toastSuccess: function(can, content, title, duration) { - if (!can.user.isEnglish(can)) { - content && (content += " success"); var list = can.core.Split(content, " ", " ") - content = can.core.List(list, function(text) { return can.user.trans(can, text) }).join("") - } + content = can.user.trans(can, content||""), content += can.user.trans(can, " success", "成功") return can.user.toast(can, {content: "✅ "+content, title: title, duration: duration||1000}) }, toast: function(can, content, title, duration, progress, hash) { can = can._fields? can.sup: can - if (title == can.ConfIndex()) { title = can.user.trans(can, title, can.Conf("help")) } var meta = can.base.isObject(content)? content: {content: content, title: title, duration: duration, progress: progress, hash: hash} - meta.title = meta.title||can.user.trans(can, can.core.Keys(can.ConfSpace(), can.ConfIndex()), can.Conf("help"))||can._name.split(nfs.PS).slice(-2).join(nfs.PS) + // var list = can.core.Split(content, " ", " ") + // content = can.core.List(list, function(text) { return can.user.trans(can, text) }).join("") + if (meta.title == can.ConfIndex()) { meta.title = can.user.trans(can, meta.title, can.ConfHelp()) } + meta.title = meta.title||can.user.trans(can, can.core.Keys(can.ConfSpace(), can.ConfIndex()), can.ConfHelp())||can._name.split(nfs.PS).slice(-2).join(nfs.PS) + meta.title = can.base.replaceAll(can.user.trans(can, meta.title||""), "%2F", "/") meta.hash && can.misc.isDebug(can) && (meta.title += " "+meta.hash.slice(0, 6)), meta.action = meta.action||[""] var width = meta.width||(html.QRCODE_WIDTH+2*html.PLUGIN_PADDING+10); if (width < 0) { width = can.page.width() + width } if (can.user.isMobile && !can.user.isLandscape()) { width = window.innerWidth } - meta.title = can.base.replaceAll(meta.title||"", "%2F", "/") - var ui = can.page.Append(can, meta.action.list || meta.action.length > 1 || !can._root || !can._root.Action || !can._root.Action._toast ? document.body: can._root.Action._toast, [{view: [[chat.TOAST, can.Conf(ctx.INDEX)||can.ConfIndex(), meta.style, chat.FLOAT]], style: {width: width}, list: [ - {view: [wiki.TITLE, "", can.user.trans(can, meta.title||"")], title: "点击复制", onclick: function(event) { can.user.copy(event, can, meta.title) }}, - {view: [cli.CLOSE, "", can.page.unicode.close], title: "点击关闭", onclick: function() { action.close() }}, - {view: "duration", title: "点击关闭", onclick: function() { action.close() }}, - can.base.isObject(meta.content)? meta.content: {view: [[nfs.CONTENT, html.FLEX], "", meta.content||""]}, - html.ACTION, !can.base.isUndefined(meta.progress) && {view: "progress", style: {width: width-2*html.PLUGIN_PADDING}, list: [ - {view: "current", style: {width: (meta.progress||0)*(width-2*html.PLUGIN_PADDING-2)/100}}, - ]}, - ] }]); can.onengine.signal(can, chat.ONTOAST, can.request({}, {time: can.misc._time(), title: meta.title, content: meta.content})) - meta.action.meta && can.core.Item(meta.action.meta, function(key, cb) { cb.help && can.core.Value(meta.action.meta, ["_trans", key], cb.help) }) + var ui = can.page.Append(can, meta.action.list||meta.action.length > 1 || !can._root||!can._root.Action||!can._root.Action._toast? document.body: can._root.Action._toast, + [{view: [[chat.TOAST, can.ConfIndex(), meta.style, html.FLOAT]], style: {width: width}, list: [ + {view: [html.TITLE, "", meta.title], title: "点击复制", onclick: function(event) { can.user.copy(event, can, meta.title) }}, + {view: [cli.CLOSE, "", can.page.unicode.close], title: "点击关闭", onclick: function() { action.close() }}, + {view: "duration", title: "点击关闭", onclick: function() { action.close() }}, + can.base.isObject(meta.content)? meta.content: {view: [[nfs.CONTENT, html.FLEX], "", meta.content||""]}, + html.ACTION, !can.base.isUndefined(meta.progress) && {view: "progress", style: {width: width-2*html.PLUGIN_PADDING}, list: [ + {view: "current", style: {width: (meta.progress||0)*(width-2*html.PLUGIN_PADDING-2)/100}}, + ]}, + ]}] + ); + can.onengine.signal(can, chat.ONTOAST, can.request({}, {time: can.misc._time(), title: meta.title, content: meta.content})) + // meta.action.meta && can.core.Item(meta.action.meta, function(key, cb) { cb.help && can.core.Value(meta.action.meta, ["_trans", key], cb.help) }) var action = can.onappend._action(can, meta.action.list? meta.action.list.reverse(): meta.action, ui.action, {_trans: meta.action.meta? meta.action.meta._trans: {}, _engine: function(event, button) { can.core.CallFunc(meta.action.meta? meta.action.meta[button]: meta.action, [event, button]), action.close(event) }, open: function(event) { meta.content.indexOf(ice.HTTP) == 0 && can.user.open(meta.content), meta.title.indexOf(ice.HTTP) == 0 && can.user.open(meta.title) }, - close: function(event) { event && event.isTrusted && can.onengine.signal(can, "onevent", can.request(event, {_type: "close"})) - action.timer.stop = true, can.page.Remove(can, ui._target) }, - cancel: function(event) { action.timer.stop = true, can.page.Remove(can, ui._target) }, + close: function() { + // event && event.isTrusted && can.onengine.signal(can, "onevent", can.request(event, {_type: "close"})) + action.timer.stop = true, can.page.Remove(can, ui._target), delete(can.__toast) + can._toast && (typeof can._toast.close == code.FUNCTION) && delete(can._toast) + }, + cancel: function() { action.close() }, timer: can.core.Timer({interval: 100, length: (meta.duration||1000)/100}, function(event, interval, index) { if (index > 30) { ui.duration.innerHTML = index/10+(index%10==0?".0":"")+"s..." } - }, function() { can.page.style(can, ui._target, "margin-right", "-400px"), delete(can.__toast) - can.onmotion.delay(can, function() { can.page.Remove(can, ui._target) }, 1000) + }, function() { + can.page.style(can, ui._target, "margin-right", "-400px") + can.onmotion.delay(can, function() { action.close() }, 1000) }), _target: ui._target, }); can.onmotion.story.auto(can, ui._target) + if (meta.action && meta.action.length == 1 && meta.action[0] === "") { + can.page.Select(can, action._target, html.DIV_ACTION, function(target) { can.onmotion.hidden(can, target) }) + } if (action._target.parentNode == document.body) { can.onmotion.delay(can, function() { can.page.style(can, action._target, html.TOP, (can.page.height() - action._target.offsetHeight)/2, html.LEFT, (can.page.width()-action._target.offsetWidth)/2) }) } - if (meta.action && meta.action.length == 1 && meta.action[0] === "") { - can.page.Select(can, action._target, html.DIV_ACTION, function(target) { can.onmotion.hidden(can, target) }) - } can._toast && (typeof can._toast.close == code.FUNCTION && can._toast.close(), delete(can._toast)) + can._toast && (typeof can._toast.close == code.FUNCTION && can._toast.close(), delete(can._toast)) can._root && can._root.Action && can._root.Action._toast && (can._root.Action._toast.scrollTop += 10000) if (meta.hash) { var list = can._root.Action._toastList = can._root.Action._toastList||{} list[meta.hash] && can.page.insertBefore(can, action._target, list[meta.hash]._target), can.__toast = action list[meta.hash] && (can.page.Remove(can, list[meta.hash]._target), list[meta.hash].close(), delete(list[meta.hash])), list[meta.hash] = action - } else { can._toast = action } return action + } else { + can._toast = action + } + return action }, space: function(can) { return can.Conf(web.SPACE)||can.Conf(ice.POD)||can.misc.Search(can, ice.POD) }, template: function(can, file) { return can.base.MergeURL(can.base.Path(nfs.SRC_TEMPLATE, can.Conf(ctx.INDEX), file), ice.POD, can.user.space(can)) }, diff --git a/plugin/local/code/inner.js b/plugin/local/code/inner.js index f7ac25a6..70ca99d1 100644 --- a/plugin/local/code/inner.js +++ b/plugin/local/code/inner.js @@ -220,7 +220,7 @@ Volcanos(chat.ONIMPORT, { }} }, target), can.onappend.board(can, msg, target), msg.Option(ice.MSG_STATUS) && can.onappend._status(can, msg.Option(ice.MSG_STATUS), can.page.Append(can, target, [html.STATUS])._target) } else { return can.onmotion.toggle(can, target, false), can.onimport.layout(can), can.user.toastFailure(can, "nothing to display") - } return can.onmotion.toggle(can, target, true), can.onmotion.delay(can, function() { can.onimport.layout(can), can.user.toastSuccess(can) }, 0) + } return can.onmotion.toggle(can, target, true), can.onimport.layout(can) }, toolkit: function(can, meta, cb) { can.base.isString(meta) && (meta = {index: meta}) var key = [meta.index].concat(meta.args).join(","), sub = can.db.toolkit[key]; if (sub) { sub.select(); return } @@ -459,8 +459,8 @@ Volcanos(chat.ONACTION, { msg.Append(nfs.FILE)? can.onimport.tabview(can, msg.Append(nfs.PATH), msg.Append(nfs.FILE), msg.Append(nfs.LINE)): can.user.toastFailure(can, "not found "+value) }) }), can.page.Select(can, tr, "td.text", function(td) { offset += td.innerText.length+1 }) }) }, - show: function(event, can) { can._msg._profile_hidden = false, can.runAction(can.request(event, {_toast: "渲染中...", args: can.onexport.session(can, PROFILE_ARGS+can.Option(nfs.PATH)+can.Option(nfs.FILE))}), mdb.RENDER, [can.onexport.parse(can), can.Option(nfs.FILE), can.Option(nfs.PATH)], function(msg) { can.onimport.profile(can, msg) }) }, - exec: function(event, can) { can.runAction(can.request(event, {_toast: "执行中...", args: can.onexport.session(can, DISPLAY_ARGS+can.Option(nfs.PATH)+can.Option(nfs.FILE))}), mdb.ENGINE, [can.onexport.parse(can), can.Option(nfs.FILE), can.Option(nfs.PATH)], function(msg) { can.onimport.display(can, msg) }) }, + show: function(event, can) { can._msg._profile_hidden = false, can.runAction(can.request(event, {_toast: "渲染", args: can.onexport.session(can, PROFILE_ARGS+can.Option(nfs.PATH)+can.Option(nfs.FILE))}), mdb.RENDER, [can.onexport.parse(can), can.Option(nfs.FILE), can.Option(nfs.PATH)], function(msg) { can.onimport.profile(can, msg) }) }, + exec: function(event, can) { can.runAction(can.request(event, {_toast: "执行", args: can.onexport.session(can, DISPLAY_ARGS+can.Option(nfs.PATH)+can.Option(nfs.FILE))}), mdb.ENGINE, [can.onexport.parse(can), can.Option(nfs.FILE), can.Option(nfs.PATH)], function(msg) { can.onimport.display(can, msg) }) }, plug: function(event, can, button) { function show(index, args) { input.cancel({}, can, "cancel"); can.onimport.toolkit(can, {index: index, args: can.core.Split(args||"")}, function(sub) { sub.select() }) } var input = can.user.input(can.request(event, {type: button}), can, [{type: html.TEXT, name: ctx.INDEX, run: function(event, cmds, cb) { can.run(event, cmds, function(msg) { diff --git a/plugin/table.js b/plugin/table.js index dfe70772..d7cbdc70 100644 --- a/plugin/table.js +++ b/plugin/table.js @@ -431,7 +431,13 @@ Volcanos(chat.ONIMPORT, { return value[key] && value[key] != "finish" && {text: [can.user.transValue(can, value, key), "", [type, value[key], can.Conf("_trans.value."+key+".style."+value[key])||""]]} }, authView: function(can, value) { return can.base.isIn(value.auth_status, "issued", "2") && {view: [aaa.AUTH, html.SPAN], list: [{icon: "bi bi-patch-check-fill", style: {color: "var(--notice-bg-color)"}}]} }, - timeView: function(can, value) { return {text: [can.base.TimeTrim(value.updated_at||value.created_at), "", mdb.TIME]} }, + timeView: function(can, value, key) { + if (key) { return {text: [can.user.trans(can, key, null, html.INPUT)+": "+can.base.TimeTrim(value[key]), "", mdb.TIME]} } + return {text: [can.base.TimeTrim(value[key]||value.updated_at||value.created_at), "", mdb.TIME]} + }, + unitView: function(can, value, key, unit) { if (!value[key]) { return } + return {text: [[can.user.trans(can, key, null, html.INPUT)+":", value[key]].concat(unit? [unit]: []).join(" "), "", key]} + }, typeStyle: function(can, value, key) { return can.Conf("_trans.value."+key+".style."+value[key])||"" }, roleStyle: function(can, value, key) { return can.Conf("_trans.value."+key+".style."+value[key])||"" }, shareTitle: function(can, msg, title, content) { if (msg.IsDetail()) { var value = msg.TableDetail()