(function() { const PROJECT_HIDE = "web.code.inner:project", TABVIEW_HIDE = "web.code.inner:tabview" const CURRENT_FILE = "web.code.inner:currentFile", SELECT_LINE = "web.code.inner:selectLine" const VIEW_CREATE = "tabview.view.create", VIEW_REMOVE = "tabview.view.remove", LINE_SELECT = "tabview.line.select" Volcanos(chat.ONIMPORT, {_init: function(can, msg, cb, target) { can.onmotion.clear(can), can.onappend.style(can, code.INNER) if (msg.Option(nfs.FILE)) { can.Option(nfs.FILE, msg.Option(nfs.FILE)) msg.Option(nfs.PATH) && can.Option(nfs.PATH, msg.Option(nfs.PATH)) msg.Option(nfs.LINE) && can.Option(nfs.LINE, msg.Option(nfs.LINE)) } if (msg.Result() == "" && can.Option(nfs.LINE) == "1") { return } var files = can.core.Split(can.Option(nfs.FILE), ice.FS); can.Option(nfs.FILE, files[0]) var paths = can.core.Split(can.Option(nfs.PATH), ice.FS); can.Option(nfs.PATH, paths[0]) can.core.List(paths.concat(can.core.Split(msg.Option(nfs.REPOS))), function(p) { if (can.base.endWith(p, "-story/", "-dict/")) { return } if (p && paths.indexOf(p) == -1 && p[0] != ice.PS) { paths.push(p) } }) can.db = {paths: paths, tabview: {}, history: [], _history: [], toolkit: {}}, can.onengine.plugin(can, can.onplugin), can.sup.onimport._process = function() {} can.ui = can.onappend.layout(can, [html.PROJECT, [html.TABS, nfs.PATH, [html.CONTENT, html.PROFILE], html.DISPLAY, html.PLUG]]) can.onmotion.clear(can, can.ui.project) can.ui._content = can.ui.content, can.ui._profile = can.ui.profile, can.ui._display = can.ui.display, can.onmotion.hidden(can, can.ui.plug) switch (can.Mode()) { case chat.SIMPLE: // no break case chat.FLOAT: can.onmotion.hidden(can, can.ui.project); break case chat.CMD: can.onmotion.hidden(can, can._status), can.onkeymap._build(can) can.misc.sessionStorage(can, PROJECT_HIDE) == html.HIDE && can.onmotion.hidden(can, can.ui.project) if (can.misc.sessionStorage(can, TABVIEW_HIDE) == html.HIDE) { can.onmotion.hidden(can, can.ui.project), can.onmotion.hidden(can, can.ui.tabs) } case chat.FULL: // no break default: can.onimport.project(can, paths), can.onimport._tabs(can) var last = can.misc.localStorage(can, CURRENT_FILE); can.onmotion.delay(can, function() { can.core.Next(files.slice(1), function(file, next) { can.onimport._tabview(can, paths[0], file, "", next) }, function() { if (can.user.isWebview && last) { var ls = can.core.Split(last, ice.DF); ls.length > 0 && can.onimport._tabview(can, ls[0], ls[1], ls[2]) } }) }) can.user.isMobile && can.onmotion.hidden(can, can.ui.project) } var args = can.misc.SearchHash(can); can.db.tabview[can.onexport.keys(can)] = msg can.onimport.tabview(can, can.Option(nfs.PATH), can.Option(nfs.FILE), can.Option(nfs.LINE), function() { if (!can.user.isWebview && args.length > 0 && can.isCmdMode()) { can.onimport._tabview(can, args[args.length-3], args[args.length-2]||can.Option(nfs.FILE), args[args.length-1]) } }), can.base.isFunc(cb) && cb(msg) can.ui.profile.onclick = function(event) { if (event.target.tagName == "A") { var link = can.misc.ParseURL(can, event.target.href); if (!link.cmd) { return } can.onkeymap.prevent(event); if (link.cmd == web.CODE_VIMER) { can.onimport.tabview(can, link.path, link.file, link.line) } else { can.onimport.tabview(can, link.path, link.cmd, ctx.INDEX) } } } }, _tabs: function(can) { if (!can.isCmdMode()) { return can.ui.tabs = can._action } can.page.Append(can, can.ui.tabs, can.core.List([ {name: can.page.unicode.menu, onclick: function() { can.user.carte(event, can, can.onaction, can.onaction.list.concat(can.user.isWebview? ["全屏", "录屏", "编辑器", "浏览器"]: [])) }}, {name: can.page.unicode.refresh, style: {"font-size": "24px", "padding-top": 0}, onclick: function() { location.reload() }}, ], function(item) { return can.base.Copy(item, {view: [[html.ITEM, html.ICON], "", item.name]}) })), can.page.Append(can, can.ui.tabs, can.user.header(can)) }, __tabPath: function(can, cache) { can.onimport._tabPath(can, ice.PS, nfs.PATH, can.base.Path(can.Option(nfs.PATH), can.Option(nfs.FILE)), function(p) { var ls = can.onexport.split(can, p); can.onimport.tabview(can, ls[0], ls[1]) }, can.ui.path), can.onimport._tabFunc(can, can.ui.path, cache), can.onimport._tabMode(can), can.onimport._tabIcon(can) can.ui.path.ondblclick = function(event) { var show = can.onmotion.toggle(can, can.ui.tabs); can.onmotion.toggle(can, can.ui.project, show), can.onimport.layout(can) can.isCmdMode() && can.misc.sessionStorage(can, TABVIEW_HIDE, show? "": html.HIDE) } }, _tabPath: function(can, ps, key, value, cb, target) { can.onmotion.clear(can, can.ui.path), can.core.List(can.core.Split(value.split(ice.FS)[0], ps), function(value, index, list) { can.page.Append(can, target, [{text: [value+(index 10? [web.FILTER]: []).concat(msg.Table(function(value) { var p = can.core.Split(value[key], ps).pop()+(can.base.endWith(value[key], ps)? ps: ""); return _trans[p] = value[key], p })), function(event, button) { can.base.endWith(button, ps)? can.onimport.tabPath(event, can, ps, key, pre+button, cb, carte): cb(_trans[button], pre) }, parent)._target, file = can.core.Split(event.target.innerHTML.trim(), ice.PT)[0] can.page.Select(can, carte, html.DIV_ITEM, function(target) { target.innerHTML.trim() != event.target.innerHTML.trim() && can.base.beginWith(target.innerHTML, file+ice.PT) && carte.insertBefore(target, carte.firstChild) }) function remove(p) { if (p && p._sub) { remove(p._sub), can.page.Remove(can, p._sub), delete(p._sub) } } if (parent) { remove(parent), parent._sub = carte } }) }, _tabFunc: function(can, target, cache) { if (cache) { var func = can.db._func||{list: []} } else { var func = can.onexport.func(can); can.db._func = func } if (func.list.length > 0) { can.db.tabFunc = can.db.tabFunc||{} var last = can.db.tabFunc[can.Option(nfs.PATH)+can.Option(nfs.FILE)]||{}; can.db.tabFunc[can.Option(nfs.PATH)+can.Option(nfs.FILE)] = last var carte, list = [web.FILTER]; can.core.Item(last, function(key) { list.push(key) }), list = list.concat(func.list) } can.page.Append(can, target, [{view: [[html.ITEM, "func"], html.SPAN, (func.current||"func")+ice.PS+can.db.max+func.percent+ice.SP+can.base.Size(can._msg.result[0].length)], onclick: function(event) { carte = can.user.carte(event, can, {_style: nfs.PATH}, list, function(ev, button) { last[button] = true, carte.close() can.onimport.tabview(can, "", can.Option(nfs.FILE), can.core.Split(button, ice.DF)[1]) }) }}]) }, _tabMode: function(can) { var mode = can.db.mode||"", target = can.ui.current; if (target && mode != mdb.PLUGIN) { mode += ice.SP+target.selectionStart+ice.PS+target.value.length } can.page.Append(can, can.ui.path, [{text: [mode, "", [ice.MODE, can.db.mode||""]], onclick: function(event) { var list = {}; can.core.Item(can.onkeymap._mode[can.db.mode], function(k, cb) { list[cb.help+ice.TB+k] = function(event, can, button) { can.core.CallFunc(cb, {event: event, can: can}) } }) can.core.Item(can.onkeymap._mode[can.db.mode+"_ctrl"], function(k, cb) { list[cb.help+ice.TB+"C-"+k] = function(event, can, button) { can.core.CallFunc(cb, {event: event, can: can}) } }) can.user.carte(event, can, list, []) }}]) }, _tabIcon: function(can) { can.user.isWindows || can.page.Append(can, can.ui.path, can.core.Item({ "\u25E8 ": function(event) { if (can.page.isDisplay(can.ui.profile)) { return can.onmotion.hidden(can, can.ui.profile), can.onimport.layout(can) } can.onaction.show(event, can) }, "\u25E8": shy({"font-size": "23px", rotate: "90deg", translate: "1px 1px"}, function(event) { if (can.page.isDisplay(can.ui.display)) { return can.onmotion.hidden(can, can.ui.display), can.onimport.layout(can) } can.onaction.exec(event, can) }), "\u25E7": function(event) { var show = can.onmotion.toggle(can, can.ui.project); can.onimport.layout(can) can.isCmdMode() && can.misc.sessionStorage(can, PROJECT_HIDE, show? "": html.HIDE) }, "\u2756": shy({"font-size": "20px", translate: "0 2px"}, function(event) { can.onaction.plug(event, can) }), "\u271A": shy({"font-size": "20px", translate: "0 2px"}, function(event) { can.onaction.open(event, can) }), }, function(text, cb) { return cb && {text: [text, html.SPAN, html.VIEW], style: cb.meta, onclick: cb} })) }, _tabview: function(can, path, file, line, cb) { var key = can.onexport.keys(can, path, file) if (!can.user.isWebview) { return can.onimport.tabview(can, path, file, line, cb) } if (!can.db.tabview[key]) { return can.onimport.tabview(can, path, file, line, cb), can.db.tabview[key] = true } }, tabview: function(can, path, file, line, cb) { path = path||can.Option(nfs.PATH); var key = can.onexport.keys(can, path, file) function isIndex() { return line == ctx.INDEX } function isSpace() { return line == web.SPACE } function show(skip) { can._msg && can._msg.Option(nfs.LINE, can.Option(nfs.LINE)), can._msg = can.db.tabview[key] can.Option(can.onimport.history(can, {path: path, file: file, line: line||can.misc.sessionStorage(can, SELECT_LINE+ice.DF+path+file)||can._msg.Option(nfs.LINE)||1})) can.onsyntax._init(can, can._msg, function(content) { var msg = can._msg; can.onexport.hash(can) can.isCmdMode() && can.onexport.title(can, path+file), can.onmotion.select(can, can.ui.tabs, html.DIV_TABS, msg._tab), can.isCmdMode() && msg._tab.scrollIntoView() if (isSpace()) { can.ui.path.innerHTML = can.page.Format(html.A, can.misc.MergePodCmd(can, {pod: can.Option(nfs.FILE)})) } else if (isIndex()) { can.onimport._tabPath(can, ice.PT, ice.CMD, can.Option(nfs.FILE), function(p, pre) { can.onimport.tabview(can, "", can.core.Keys(can.base.trimSuffix(pre, ice.PT), p), ctx.INDEX) }, can.ui.path) } else { can.onimport.__tabPath(can) } can.page.SelectChild(can, can.ui._content.parentNode, can.page.Keys(html.DIV_CONTENT, html.FIELDSET_STORY, [[[html.IFRAME, html.CONTENT]]]), function(target) { if (can.onmotion.toggle(can, target, target == msg._content)) { can.ui.content = msg._content } }), can.ui.content._plugin = msg._plugin, can.ui.profile._plugin = msg._profile can.page.SelectChild(can, can.ui._content.parentNode, can.page.Keys(html.DIV_PROFILE, [[[html.IFRAME, html.PROFILE]]]), function(target) { if (can.onmotion.toggle(can, target, target == msg._profile)) { can.ui.profile = msg._profile } }), can.onimport.layout(can), can.ui.current && can.onmotion.toggle(can, can.ui.current, !isIndex() && !isSpace()) skip || can.onaction.selectLine(can, can.Option(nfs.LINE), true), can.base.isFunc(cb) && cb(), cb = null var ls = can.db.file.split(ice.PS); if (ls.length > 4) { ls = [ls.slice(0, 2).join(ice.PS)+"/.../"+ls.slice(-2).join(ice.PS)] } can.Status(kit.Dict(nfs.FILE, ls.join(ice.PS), mdb.TYPE, can.db.parse)) }) } function load(msg) { var skip = false; can.db.tabview[key] = msg can.onimport.tabs(can, [{name: can.base.beginWith(file, "http://")? file.split(ice.QS)[0]: file.split(ice.FS)[0].split(isIndex()? ice.PT: ice.PS).pop(), text: file, _menu: shy([ nfs.SAVE, nfs.TRASH, web.REFRESH, ], function(event, button, meta) { can.onaction[button](event, can, button) })}], function(event, tabs) { can._tab = msg._tab = tabs._target, show(skip), skip = true }, function(tabs) { can.onengine.signal(can, VIEW_REMOVE, msg), can.ui.zone.source.refresh() msg._content != can.ui._content && can.page.Remove(can, msg._content), msg._profile != can.ui._profile && can.page.Remove(can, msg._profile) delete(can.ui._content._cache[key]), delete(can.ui._profile._cache[key]), delete(can.ui._display._cache[key]) delete(can.db.tabview[key]), delete(can._cache_data[key]) }, can.ui.tabs) } if (can.db.tabview[key]) { return !can._msg._tab && !can.isSimpleMode()? load(can.db.tabview[key]): show() } isIndex()||isSpace()? load(can.request({}, {index: file, line: line})): can.run({}, [path, file], load, true) }, history: function(can, record) { can.base.Eq(record, can.db.history[can.db.history.length-1], mdb.TEXT) || can.db.history.push(record) return can.Status(ice.BACK, can.db.history.length), record }, project: function(can, path) { can.onimport.zone(can, can.core.Item(can.onfigure, function(name, cb) { if (can.base.isFunc(cb)) { return {name: name, _trans: can.onfigure._trans? can.onfigure._trans[name]||"": "", _init: function(target, zone) { return cb(can, target, zone, path) }} } }), can.ui.project) }, profile: function(can, msg) { var _msg = can.db.tabview[can.onexport.keys(can)]; _msg.Option(html.WIDTH, msg.Option(html.WIDTH)||0.5) if (msg.Result().indexOf("