diff --git a/frame.js b/frame.js index 36a658d3..968b532c 100644 --- a/frame.js +++ b/frame.js @@ -163,6 +163,10 @@ Volcanos("onappend", { _init: function(can, meta, list, cb, target, field) { _follow: can._follow+"."+meta.name+"."+item.name, }, Volcanos.meta.libs.concat([item.display||"/plugin/input.js"]), function(input) { input.onimport._init(input, input.Conf(item), item.list||[], function() {}, input._target); + if (location.protocol == "chrome-extension:") { + var p = sub.user.Cookie(can, item.name) + item.type != "button" && p != undefined && (input._target.value = p) + } if (can.user.Search(can, "active") == meta.name || can.user.Search(can, "title") == meta.name) { var p = sub.user.Search(can, item.name) p != undefined && (input._target.value = p) diff --git a/lib/base.js b/lib/base.js index 24bc55e5..d3c28711 100644 --- a/lib/base.js +++ b/lib/base.js @@ -1,4 +1,4 @@ -Volcanos("base", {help: "基础模块", +var base = Volcanos("base", {help: "基础模块", isNone: function(c) {return c === undefined || c === null}, isSpace: function(c) {return c == " " || c == "Enter"}, diff --git a/lib/core.js b/lib/core.js index 4ed82cfe..62f96f92 100644 --- a/lib/core.js +++ b/lib/core.js @@ -1,4 +1,4 @@ -Volcanos("core", {help: "核心模块", +var core = Volcanos("core", {help: "核心模块", List: shy("迭代器", function(obj, cb, interval, cbs) { if (typeof obj == "number") { var begin = 0, end = obj, step = 1; diff --git a/lib/misc.js b/lib/misc.js index 9c68d9da..bcbbb0b8 100644 --- a/lib/misc.js +++ b/lib/misc.js @@ -1,4 +1,4 @@ -Volcanos("misc", {help: "工具模块", +var misc = Volcanos("misc", {help: "工具模块", POST: shy("请求后端", {order: 0}, function(can, msg, url, form, cb) { var xhr = new XMLHttpRequest(); xhr.open("POST", url), xhr.onreadystatechange = function() { @@ -103,7 +103,7 @@ Volcanos("misc", {help: "工具模块", var msg = {"result": [event.data]} } - msg = can.Event(event, msg), msg.Reply = function() { + msg = (can.request||can.Event)(event, msg), msg.Reply = function() { // 回复命令 msg.Option("_handle", true) msg.Option("_target", msg.Option("_source")) @@ -117,7 +117,8 @@ Volcanos("misc", {help: "工具模块", typeof cb == "function" && cb(event, msg, msg.detail[0], msg.detail.slice(1)) } catch (e) { // 执行失败 - msg.Reply(can.Log("err", e)) + // con + console.log(e) } } return can._socket diff --git a/lib/page.js b/lib/page.js index c39f03d9..c3b72b2e 100644 --- a/lib/page.js +++ b/lib/page.js @@ -1,4 +1,4 @@ -Volcanos("page", {help: "网页模块", +var page = Volcanos("page", {help: "网页模块", ClassList: { has: function(can, obj, key) {var list = obj.className? obj.className.split(" "): []; for (var i = 2; i < arguments.length; i++) { diff --git a/lib/user.js b/lib/user.js index 29ee6a13..7c59c1c5 100644 --- a/lib/user.js +++ b/lib/user.js @@ -1,4 +1,4 @@ -Volcanos("user", {help: "用户模块", +var user = Volcanos("user", {help: "用户模块", alert: function(text) {alert(JSON.stringify(text))}, confirm: function(text) {return confirm(JSON.stringify(text))}, prompt: function(text, cb, def, silent) {(text = silent? def: prompt(text, def||"")) != undefined && typeof cb == "function" && cb(text); return text}, diff --git a/manifest.json b/manifest.json index 6254ac19..7672dbd1 100644 --- a/manifest.json +++ b/manifest.json @@ -2,9 +2,23 @@ "manifest_version": 2, "name": "volcanos", "version": "0.0.1", - "background": {"page": "plugin/chrome/chrome.html"}, - "browser_action": {"default_popup": "plugin/chrome/popup.html"}, - "content_scripts": [], + "background": {"page": "/plugin/chrome/chrome.html"}, + "browser_action": { + "default_icon": "/favicon.ico", + "default_popup": "/plugin/chrome/popup.html" + }, + "content_scripts": [ + { + "matches": [ "" ], + "js": ["/proto.js", + "/lib/base.js", + "/lib/core.js", + "/lib/misc.js", + "/lib/page.js", + "/lib/user.js", + "/plugin/chrome/contexts.js"] + } + ], "permissions": [ "tabs", "history", diff --git a/pane/Action.js b/pane/Action.js index cf02be6d..bf2e4bf0 100644 --- a/pane/Action.js +++ b/pane/Action.js @@ -24,7 +24,7 @@ Volcanos("ondetail", {help: "交互菜单", list: ["共享", "更名", "删除"] }) Volcanos("onexport", {help: "导出数据", list: [], _init: function(can, msg, list, cb, target) { var key = "action"; can.Cache(can.Conf("river")+"."+can.Conf("storm"), can._output, can._output.scrollTop+1); - var river = can.Conf("river", msg.Option("river")), storm = can.Conf("storm", msg.Option("storm")); + var river = can.Conf("river", msg.Option("river")||"main"), storm = can.Conf("storm", msg.Option("storm")||"main") var position = can.Conf(key, msg.Option(key, can.Cache(river+"."+storm, can._output)||"")); if (position) { can._output.scrollTo(0, position-1); return } diff --git a/plugin/chrome/chrome.html b/plugin/chrome/chrome.html new file mode 100644 index 00000000..e4b1dbd9 --- /dev/null +++ b/plugin/chrome/chrome.html @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/plugin/chrome/chrome.js b/plugin/chrome/chrome.js new file mode 100644 index 00000000..c1ba12e4 --- /dev/null +++ b/plugin/chrome/chrome.js @@ -0,0 +1,155 @@ +var can = Volcanos("chrome", { + _send: function(msg, cb) {chrome.extension.sendRequest(msg, cb)}, + _open: function(url) {chrome.windows.create({url: url})}, + + open: function(msg, cmd, cb) { + chrome.windows.create({url: cmd[0]}) + typeof cb == "function" && cb(msg) + }, + wins: function(msg, cmd, cb) { + if (cmd.length == 0) { + // 窗口列表 + chrome.windows.getAll(function(wins) { + can.core.List(wins, function(win) {win.wid = win.id + msg.Push(win, ["wid", "state", "left", "top", "width", "height"]) + }) + typeof cb == "function" && cb(msg) + }) + return + } + + if (cmd.length > 1) { + // 新建标签 + chrome.tabs.create({windowId: parseInt(cmd[0]), url: cmd[1], selected: false}, function() { + can.wins(msg, [cmd[0]], cb) + }) + return + } + + // 标签列表 + chrome.tabs.getAllInWindow(parseInt(cmd[0]), function(tabs) { + can.core.List(tabs, function(tab) {tab.tid = tab.id + msg.Push(tab, ["tid", "active", "width", "height", "index", "title", "url"]) + }) + typeof cb == "function" && cb(msg) + }) + }, + tabs: function(msg, cmd, cb) { + if (cmd.length == 0) { + chrome.tabs.getAllInWindow(function(tabs) { + can.core.List(tabs, function(tab) { + msg.Push("id", tab.id) + msg.Push("active", tab.active) + msg.Push("index", tab.index) + msg.Push("title", tab.title) + msg.Push("url", tab.url) + }) + typeof cb == "function" && cb(msg) + }) + return + } + + chrome.tabs[cmd[1]](parseInt(cmd[0]), cb) + }, + cookie: function(msg, cmd, cb) { + if (cmd[0] == "modify") {var data = {}; data[cmd[1]] = cmd[2] + chrome.bookmarks.update(cmd[4], data, function() { + typeof cb == "function" && cb(msg) + }) + return + } else if (cmd[0] == "delete") { + chrome.bookmarks.remove(cmd[2], function() { + typeof cb == "function" && cb(msg) + }) + return + } else if (cmd.length > 2) { + chrome.bookmarks.create({parentId: cmd[0], url: cmd[1], title: cmd[2], index: cmd[3]||0}, cb) + } + + chrome.cookies.getAll({name: ""}, function(cs) { + typeof cb == "function" && cb(msg) + }) + }, + history: function(msg, cmd, cb) { + chrome.tabs.getAllInWindow(function(tabs) { + can.core.List(tabs, function(tab) { + msg.Push("id", tab.id) + msg.Push("active", tab.active) + msg.Push("index", tab.index) + msg.Push("title", tab.title) + msg.Push("url", tab.url) + }) + typeof cb == "function" && cb(msg) + }) + }, + bookmark: function(msg, cmd, cb) { + if (cmd[0] == "modify") {var data = {}; data[cmd[1]] = cmd[2] + chrome.bookmarks.update(cmd[4], data, function() { + typeof cb == "function" && cb(msg) + }) + return + } else if (cmd[0] == "delete") { + chrome.bookmarks.remove(cmd[2], function() { + typeof cb == "function" && cb(msg) + }) + return + } else if (cmd.length > 2) { + chrome.bookmarks.create({parentId: cmd[0], url: cmd[1], title: cmd[2], index: cmd[3]||0}, cb) + } + + chrome.bookmarks.getSubTree(cmd[0]||"0", function(labs) { + for (var i = 0; i < labs.length; i++) {labs[i].pid = labs[i].parentId + msg.Push("time", can.base.Time(labs[i].dateAdded)) + msg.Push(labs[i], ["pid", "id", "index", "title", "url"]) + labs = labs.concat(labs[i].children||[]) + } + typeof cb == "function" && cb(msg) + }) + }, +}, ["/lib/base", "/lib/core", "/lib/misc", "/lib/page", "/lib/user"], function(can) {can.Conf({iceberg: "http://localhost:9020/"}) + can.user.toast = function(message, title) {chrome.notifications.create(null, { + message: message, title: title||"volcanos", iconUrl: "/favicon.ico", type: "basic", + })}, + + can.run = function(event, cmd, cb, silent) { var msg = can.request(event) + can.misc.Run(event, can, {names: "code/chrome/crx"}, cmd, cb) + }, + + chrome.history.onVisited.addListener(function(item) { + can.run({}, ["history", item.id, item.url, item.title], function(msg) { + can.user.toast(item.url, item.title) + }) + }) + return + + can.misc.WSS(can, "ws://localhost:9020/space/", {node: "chrome", name: chrome.runtime.id}, function(event, msg) { + if (msg.Option("_handle")) {return can.user.toast(msg.result.join(""))} + + can.user.toast(msg.detail.join(" ")) + switch (msg.detail[0]) { + case "space": can._share = msg.detail[2]; break + case "pwd": msg.Echo("hello world"); break + default: (can[msg.detail[0]]||can.chrome[msg.detail[0]])(msg, msg.detail.slice(1), function(msg) { + msg.Reply(msg) + }); return + } + msg.Reply(msg) + }, function() {can.user.toast("wss connect", "iceberg")}) + + can.run(can, {cmd: ["login", can.sid||""]}, function(msg) { + can.sid = msg.Result() + }) + + chrome.bookmarks.onCreated.addListener(function(id, item) { + chrome.bookmarks.get(item.parentId, function(root) { + can.run(can, {cmd: ["bookmark", item.id, item.url, item.title, root[0].title]}, function(msg) { + can.user.toast(item.url, item.title) + }) + }) + }) + + chrome.extension.onRequest.addListener(function(msg, sender, cb) { + can.run(can, msg, cb) + }) +}) + diff --git a/plugin/chrome/contexts.js b/plugin/chrome/contexts.js new file mode 100644 index 00000000..adb3699a --- /dev/null +++ b/plugin/chrome/contexts.js @@ -0,0 +1,19 @@ +var can = Volcanos("chrome", { +}, [], function(can) { + can.user = user + can.page = page + can.misc = misc + can.core = core + can.base = base + + chrome.extension.onMessage.addListener( function (request, sender, sendResponse) { + var title = can.page.Select(can, document.body, "p.title", function(item) { + return item.innerText + }).join("-") + can.page.Select(can, document.body, "video", function(item) { + sendResponse({poster: item.poster, src: item.src, title: title}) + console.log(item) + }) + }) +}) + diff --git a/plugin/chrome/popup.html b/plugin/chrome/popup.html new file mode 100644 index 00000000..e662eed8 --- /dev/null +++ b/plugin/chrome/popup.html @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/plugin/chrome/popup.js b/plugin/chrome/popup.js new file mode 100644 index 00000000..98efb7f6 --- /dev/null +++ b/plugin/chrome/popup.js @@ -0,0 +1,8 @@ +Volcanos({name: "demo", volcano: "/frame.js", iceberg: "http://localhost:9020/chat/", intshell: "plug.sh", + libs: ["/lib/base", "/lib/core", "/lib/misc", "/lib/page", "/lib/user"], panes: [ + {type: "pane", name: "Action", help: "工作台", pos: "middle", list: ["/pane/Action.js", "/pane/Action.css"]}, + ], main: {name: "Action", engine: "remote", list: ["/publish/order.js"]}, plugin: [ + "/plugin/state.js", "/plugin/input.js", "/plugin/table.js", + ], +}) + diff --git a/plugin/inner.js b/plugin/inner.js index 379a137d..d15577bc 100644 --- a/plugin/inner.js +++ b/plugin/inner.js @@ -17,7 +17,7 @@ Volcanos("onimport", {help: "导入数据", _init: function(can, msg, list, cb, msg.Option("_action") != "查看" && msg.Option("_action") != "打开" && can.onappend.table(can, target, "table", msg) can.ui = can.page.Append(can, target, [ - {view: ["project", "div"], style: {width: "80px", "max-height": height-160+"px"}}, + {view: ["project", "div"], style: {width: "80px", "max-height": height-180+"px"}}, {view: ["profile", "div"]}, {view: "preview", style: {width: "30px"}}, @@ -50,6 +50,8 @@ Volcanos("onimport", {help: "导入数据", _init: function(can, msg, list, cb, return typeof cb == "function" && cb(msg) }, tabview: function(can, path, name) { + can.user.Cookie(can, "path", path) + can.user.Cookie(can, "name", name) can.Option("path", path) can.Option("name", name) can.Option("key", "") @@ -356,10 +358,29 @@ Volcanos("onsyntax", {help: "语法高亮", list: ["keyword", "prefix", "line"], }, }, line: function(can, line) { var auto = true, loop = true + var p = location.href.startsWith("https")? "": "http://localhost:9020" var total = 0 function cb(event) { console.log(event) } - return {className: "preview", type: "video", style: {height: can.Conf("height")-160+"px", width: can.Conf("width")-160+"px"}, - data: {src: "/share/local/"+line, controls: "controls", autoplay: auto, loop: loop}, + return {className: "preview", type: "video", style: { + height: can.Conf("height")-160+"px", width: can.Conf("width")-160+"px"}, + data: {src: p+"/share/local/"+line, controls: "controls", autoplay: auto, loop: loop}, + oncontextmenu: cb, onplay: cb, onpause: cb, onended: cb, + onloadedmetadata: function(event) { + total = event.timeStamp + event.target.currentTime = can._msg.currentTime || 0 + }, onloadeddata: cb, ontimeupdate: function(event) { + can.Status("当前行", can.onexport.position(can, (can._msg.currentTime=event.target.currentTime)-1, event.target.duration)) + }, + } + }, + }, + url: { + line: function(can, line) { var auto = true, loop = true + var total = 0 + function cb(event) { console.log(event) } + return {className: "preview", type: "video", style: { + height: can.Conf("height")-160+"px", width: can.Conf("width")-160+"px"}, + data: {src: line, controls: "controls", autoplay: auto, loop: loop}, oncontextmenu: cb, onplay: cb, onpause: cb, onended: cb, onloadedmetadata: function(event) { total = event.timeStamp @@ -569,7 +590,7 @@ Volcanos("onkeymap", {help: "键盘交互", list: ["command", "normal", "insert" }, }, }) -Volcanos("onaction", {help: "控件交互", list: ["", "项目", "", "上传", "保存", "运行", "日志", "", "提交", "历史", "记录", "复盘", ""], +Volcanos("onaction", {help: "控件交互", list: ["", "项目", "", "上传", "保存", "运行", "日志", "", "提交", "历史", "记录", "复盘", "", "列表"], modifyLine: function(can, target, value) { var p = can.onsyntax.parse(can, value) typeof p == "object"? can.page.Appends(can, target, [p]): target.innerHTML = p }, @@ -629,6 +650,18 @@ Volcanos("onaction", {help: "控件交互", list: ["", "项目", "", "上传", " "提交": function(event, can, msg) { can.onkeymap._remote(event, can, "提交") }, "历史": function(event, can, msg) { can.onkeymap._remote(event, can, "历史") }, + "收藏": function(event, can, msg) { + chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) { + chrome.tabs.sendMessage(tabs[0].id, { action: "copy" }, function (response) { + var win = chrome.extension.getBackgroundPage(); + win.can.user.toast(response.src) + can.run(event, ["action", "favor", "url.favor", "spide", response.title, response.src, "poster", response.poster], function(msg) { + alert(response.title) + }, true) + }) + }) + }, + "列表": function(event, can, msg) { can.onkeymap._remote(event, can, "收藏", ["action", "favor", "url.favor"]) }, }) Volcanos("ondetail", {help: "菜单交互", list: ["删除行", "合并行", "插入行", "添加行", "追加行"], "删除行": function(event, can, msg) { diff --git a/publish/order.js b/publish/order.js index 2b3d33d8..f16914b7 100644 --- a/publish/order.js +++ b/publish/order.js @@ -1,67 +1,39 @@ -Volcanos("onengine", { - river: { - "two": {name: "two", storm: { - "one": {name: "one", action: [ - {name: "some", help: "some", inputs: [ - {type: "text", name: "one"}, - {type: "button", name: "one"}, - ], engine: function(event, can, msg, pane, cmds, cb) { - msg.Echo("hello world") - typeof cb == "function" && cb(msg) - }}, - ]}, - "two": {name: "two", action: [ - {name: "some", help: "some", inputs: [ - {type: "text", name: "one"}, - {type: "button", name: "one"}, - ], engine: function(event, can, msg, pane, cmds, cb) { - msg.Echo("hello world") - typeof cb == "function" && cb(msg) - }}, - {name: "miss", help: "some", inputs: [ - {type: "text", name: "one"}, - {type: "button", name: "one"}, - ], engine: function(event, can, msg, pane, cmds, cb) { - msg.Echo("hello miss world") - typeof cb == "function" && cb(msg) - }}, - ]}, - }}, - }, - remote: function(event, can, msg, pane, cmds, cb) { - switch (pane._name) { - case "River": - if (cmds.length == 0) { - can.core.Item(can.onengine.river, function(key, value) { - msg.Push("key", key) - msg.Push("name", value.name) - }) - } - break - case "Storm": - var river = can.onengine.river[cmds[0]] - if (!river) { break } - can.core.Item(river.storm, function(key, value) { - msg.Push("key", key) - msg.Push("name", value.name) - }) - typeof cb == "function" && cb(msg) - return true - case "Action": - var river = can.onengine.river[cmds[0]] - var storm = river && river.storm[cmds[1]] - if (!storm) { break } if (cmds.length == 2) { - can.core.List(storm.action, function(value) { - msg.Push("name", value.name||"") - msg.Push("help", value.help||"") - msg.Push("inputs", JSON.stringify(value.inputs||[])) - }) - typeof cb == "function" && cb(msg) - } else { - storm.action[cmds[2]].engine(event, can, msg, pane, cmds, cb) - } - return true - } - return false; - }, -}, [], function(can) {}) +Volcanos("onengine", { river: { + "main": {name: "main", storm: { + "main": {name: "main", action: [ + {name: "IDE", help: "集成开发环境", inputs: [ + {type: "text", name: "path", value: "tmp", action: "auto"}, + {type: "text", name: "name", value: "hi.qrc", action: "auto"}, + {type: "text", name: "key", value: "", action: "auto"}, + {type: "button", name: "打开", action: "auto"}, + {type: "button", name: "返回"}, + {type: "button", name: "提交"}, + {type: "button", name: "历史"}, + ], index: "web.wiki.inner", feature: {display: "/plugin/inner.js", style: "editor"}}, + ]}, + "word": {name: "word", action: [ + {name: "trans", help: "词汇", inputs: [ + {type: "text", name: "word", value: "miss"}, + {type: "text", name: "method", value: ""}, + {type: "button", name: "翻译"}, + ], group: "web.wiki.alpha", index: "trans"}, + ]}, + "hello": {name: "应用1", action: [ + {name: "some", help: "some", inputs: [ + {type: "text", name: "one"}, + {type: "button", name: "one"}, + ], engine: function(event, can, msg, pane, cmds, cb) { + can.onappend.toast(can, "hello", "world"); + msg.Echo("hello world"); + typeof cb == "function" && cb(msg); + }}, + ]}, + "world": {name: "应用2", action: [ + {name: "hello", help: "world", inputs: [ + {type: "text", name: "one", value: "pwd"}, + {type: "button", name: "one"}, + ], group: "cli", index: "system"}, + ]}, + }}, +}, }) +