diff --git a/base/mdb/render.go b/base/mdb/render.go index bff3c67a..52f6f339 100644 --- a/base/mdb/render.go +++ b/base/mdb/render.go @@ -26,6 +26,7 @@ func RenderAction(arg ...ice.Any) ice.Actions { m.Cmdy(kit.Keys(value[TEXT], value[NAME]), m.CommandKey(), k, arg[1], kit.Select("", arg, 2), kit.Slice(arg, 3)) }) }) + m.Sort(m.OptionFields()) }}, }, ClearOnExitHashAction()) } diff --git a/base/web/spide.go b/base/web/spide.go index 3bbbd494..df247c81 100644 --- a/base/web/spide.go +++ b/base/web/spide.go @@ -257,7 +257,8 @@ func init() { }}, mdb.SEARCH: {Hand: func(m *ice.Message, arg ...string) { if arg[0] == mdb.FOREACH && arg[1] == "" { - m.PushSearch(mdb.TYPE, LINK, mdb.NAME, ice.DEV, mdb.TEXT, mdb.HashSelectField(m, ice.COM, CLIENT_ORIGIN)) + m.PushSearch(mdb.TYPE, LINK, mdb.NAME, ice.DEV, mdb.TEXT, mdb.HashSelectField(m, ice.DEV, CLIENT_ORIGIN)) + m.PushSearch(mdb.TYPE, LINK, mdb.NAME, ice.COM, mdb.TEXT, mdb.HashSelectField(m, ice.COM, CLIENT_ORIGIN)) m.PushSearch(mdb.TYPE, LINK, mdb.NAME, ice.SHY, mdb.TEXT, mdb.HashSelectField(m, ice.SHY, CLIENT_ORIGIN)) } }}, diff --git a/core/chat/macos/applications.go b/core/chat/macos/applications.go new file mode 100644 index 00000000..ba031c6f --- /dev/null +++ b/core/chat/macos/applications.go @@ -0,0 +1,42 @@ +package macos + +import ( + ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/ctx" + "shylinux.com/x/icebergs/base/mdb" + "shylinux.com/x/icebergs/base/nfs" + "shylinux.com/x/icebergs/base/web" + "shylinux.com/x/icebergs/core/code" + "shylinux.com/x/icebergs/core/team" + kit "shylinux.com/x/toolkits" +) + +const APPLICATIONS = "applications" + +func init() { + Index.MergeCommands(ice.Commands{ + APPLICATIONS: {Actions: ice.MergeActions(ice.Actions{ + ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { + Notify(m, "runtime", "系统启动成功", ctx.INDEX, "cli.runtime") + FinderAppend(m, "Applications", m.PrefixKey()) + FinderAppend(m, "Pictures", web.WIKI_FEEL) + AppInstall(m, "Finder", "nfs.dir") + AppInstall(m, "Safari", web.CHAT_IFRAME) + AppInstall(m, "Calendar", web.TEAM_PLAN, ctx.ARGS, team.MONTH) + AppInstall(m, "Terminal", web.CODE_XTERM) + AppInstall(m, "Grapher", web.WIKI_DRAW) + AppInstall(m, "Photos", web.WIKI_FEEL) + AppInstall(m, "Books", web.WIKI_WORD) + }}, + code.INSTALL: {Hand: func(m *ice.Message, arg ...string) { AppInstall(m, arg[0], arg[1], arg[2:]...) }}, + }, CmdHashAction("index,args"))}, + }) +} +func install(m *ice.Message, cmd, name, index string, arg ...string) { + name, icon := kit.Select(kit.Select("", kit.Split(index, ice.PT), -1), name), "" + kit.If(nfs.Exists(m, kit.PathJoin(USR_ICONS, name, nfs.PNG)), func() { icon = kit.PathJoin(USR_ICONS, name, nfs.PNG) }) + m.Cmd(Prefix(cmd), mdb.CREATE, mdb.NAME, name, mdb.ICON, icon, ctx.INDEX, index, arg) +} +func AppInstall(m *ice.Message, name, index string, arg ...string) { + install(m, APPLICATIONS, name, index, arg...) +} diff --git a/core/chat/macos/desktop.css b/core/chat/macos/desktop.css new file mode 100644 index 00000000..a99ae860 --- /dev/null +++ b/core/chat/macos/desktop.css @@ -0,0 +1,89 @@ +fieldset.macos.desktop { background-size:cover; background-position:center; } +fieldset.macos.desktop>div.output>fieldset.macos { background-color:transparent; } +fieldset.macos.desktop>div.output>fieldset.macos>div.output { background-color:transparent; } +fieldset.macos.desktop>div.output>fieldset.macos.menu { font-family:monospace; line-height:25px; border-radius:0; height:25px; width:100%; position:absolute; top:0; } +fieldset.macos.desktop>div.output>fieldset.macos.searchs { position:absolute; } +fieldset.macos.desktop>div.output>fieldset.macos.searchs>form.option>div.item.icon.delete { display:none; } +fieldset.macos.desktop>div.output>fieldset.macos.searchs>form.option>div.item.keyword input { width:320px; background-color:transparent; border:#404141 solid 1px; } +fieldset.macos.desktop>div.output>fieldset.macos.searchs>form.option>div.item.keyword:hover { background-color:transparent; } +fieldset.macos.desktop>div.output>fieldset.macos.notifications { height:calc(100% - 25px); width:250px; overflow:auto; position:absolute; top:25px; right:0; } +fieldset.macos.desktop>div.output>fieldset.macos.notifications>div.output>div.item { margin-top:10px; margin-right:10px; min-height:60px; clear:both; } +fieldset.macos.desktop>div.output>fieldset.macos.notifications div.item div.title { padding-top:10px; height:24px; width:132px; overflow:hidden; } +fieldset.macos.desktop>div.output>fieldset.macos.notifications div.item div.time { color:gray; font-size:12px; padding:5px; padding-top:10px; height:24px; width:48px; } +fieldset.macos.desktop>div.output>fieldset.macos.notifications div.item div.content { width:180px; } +fieldset.macos.desktop>div.output>fieldset.macos.dock { border:#ffffff3d solid 1px; border-radius:20px; position:absolute; bottom:10px; z-index:11; transition:margin-left 0.3s; } +fieldset.macos.desktop>div.output>fieldset.macos.dock:hover { margin-left:-40px; transition:margin-left 0.3s; } +fieldset.macos.desktop>div.output>div.desktop { padding-top:25px; } +fieldset.macos.desktop>div.output>div.desktop:not(.select) { display:none; } +fieldset.macos.desktop>div.output>div.desktop>div.item { position:absolute; text-align:center; } +fieldset.macos.desktop>div.output>div.desktop>div.item:hover { background-color:unset; } +fieldset.macos.desktop>div.output>div.desktop>div.item img { width:80px; border-radius:80px; } +fieldset.macos.desktop>div.output>div.desktop>div.item>div.name { font-size:12px; width:80px; overflow:hidden; } +fieldset.macos.desktop>div.output>div.desktop>fieldset { border-radius:10px; position:absolute; } +fieldset.macos.desktop>div.output>div.desktop>fieldset>div.item.button { border-radius:20px; height:20px; width:20px; scale:0.7; position:absolute; top:15px; right:10px; } +fieldset.macos.desktop>div.output>div.desktop>fieldset>legend { background-color:unset; padding-right:10px; margin:10px 0; } +fieldset.macos.desktop>div.output>div.desktop>fieldset>form.option>* { margin:10px 0px 10px 10px; } +fieldset.macos.desktop>div.output>div.desktop>fieldset>form.option>div.icon { margin-left:0; margin-top:12px; margin-bottom:8px; } +fieldset.macos.desktop>div.output>div.desktop>fieldset>form.option>div.item.icons { margin-left:0; } +fieldset.macos.desktop>div.output>div.desktop>fieldset>form.option>div.item:last-child { margin-right:20px; } +fieldset.macos.desktop>div.output>div.desktop>fieldset>div.action>* { margin:10px 0px 10px 10px; } +fieldset.macos.desktop>div.output>div.desktop>fieldset>div.action>div.item.icons>span.icon { margin-top:12px; } +fieldset.macos.desktop>div.output>div.desktop>fieldset>div.action>div.item:last-child { margin-right:80px; } +fieldset.macos.menu>div.output>div.item { padding:0 5px; float:right; cursor:pointer; } +fieldset.macos.menu>div.output>div.menu { float:left; padding:0 20px; cursor:pointer; } +fieldset.macos.menu>div.output>div.tabs { float:left; } +fieldset.macos.menu>div.output>div.tabs.select { background-color:transparent; color:white; } +fieldset.macos.dock>div.output { height:80px; overflow:visible; display:flex; } +fieldset.macos.dock>div.output>div.space { background-color:#ececec36; margin:10px; height:calc(100% - 20px); width:2px; } +fieldset.macos.dock>div.output>div.item { text-align:center; align-self:baseline; transition:margin-top 0.3s; } +fieldset.macos.dock>div.output>div.item:hover { background-color:unset; margin-top:-80px; transition:margin-top 0.3s; } +fieldset.macos.dock>div.output>div.item img { border-radius:80px; width:80px; transition:width 0.3s; } +fieldset.macos.dock>div.output>div.item img:hover { width:160px; transition:width 0.3s; } +fieldset.macos.finder>div.output>div.project>div.item input { width:100%; } +fieldset.macos.finder>div.output div.content>div.item { float:left; text-align:center; } +fieldset.macos.finder>div.output div.content>div.item img { width:80px; border-radius:80px; } +fieldset.macos.finder>div.output div.content>div.item div.name { font-size:12px; text-align:center; } +div.carte.macos.float { font-size:14px; padding:10px; border:#ffffff5e solid 1px; border-radius:8px; } +div.carte.macos.float div.item { background:transparent; } +div.carte.macos.float hr { border-bottom:gray solid 1px; } +div.carte.macos.float { background-color:#e1e5ea; } +fieldset.macos.desktop>div.output { color:black; } +fieldset.macos.desktop>div.output>fieldset.macos.menu { background-color:#daefff99; color:black; } +fieldset.macos.desktop>div.output>fieldset.macos.dock { background-color:#e9f1f594; } +fieldset.macos.desktop>div.output>fieldset.macos.searchs { background-color:#daefff99; } +fieldset.macos.desktop>div.output>fieldset.macos.notifications div.item { background-color:#daefff99; color:black; } +fieldset.macos.desktop>div.output>div.desktop>fieldset { background-color:#dee1e6; } +fieldset.macos.desktop>div.output>div.desktop>fieldset>div.output { background-color:white; } +fieldset.macos.desktop>div.output>div.desktop>fieldset>div.status { border-top:#dddede solid 1px; } +fieldset.macos.desktop>div.output>div.desktop fieldset table.content tbody tr:nth-child(odd) { background-color:#f4f5f5; color:black; } +fieldset.macos.desktop>div.output>div.desktop fieldset table.content tbody tr:nth-child(even) { background-color:white; color:black; } +fieldset.macos.desktop>div.output>div.desktop fieldset input { background-color:white; border:#e4e5e5 solid 1px; color:black; caret-color:black; } +fieldset.macos.desktop>div.output>div.desktop fieldset>div.output.card>div.item { border:#d3d4d4 solid 1px; } +fieldset.macos.desktop>div.output>div.desktop fieldset>div.output.card>div.item>div.title { border-bottom:#d3d4d4 solid 1px; } +body.dark fieldset.macos.desktop input { color:#e8eaed; } +body.dark fieldset.macos.desktop input[type=button] { background-color:#5e5f5f; } +body.dark fieldset.macos.desktop>div.output { background-color:unset; color:white; } +body.dark fieldset.macos.desktop>div.output>fieldset.macos.menu { background-color:#08234ad1; color:#e8eaed; } +body.dark fieldset.macos.desktop>div.output>fieldset.macos.dock { background-color:#0e202e70; } +body.dark fieldset.macos.desktop>div.output>fieldset.macos.searchs { background-color:#0e202e70; } +body.dark fieldset.macos.desktop>div.output>fieldset.macos.searchs a { color:white; } +body.dark fieldset.macos.desktop>div.output>fieldset.macos.notifications div.item { background-color:#08234ad1; color:white; } +body.dark fieldset.macos.desktop>div.output>div.desktop>fieldset { background-color:#333434; } +body.dark fieldset.macos.desktop>div.output>div.desktop>fieldset>div.output { background-color:#1a1d1d; } +body.dark fieldset.macos.desktop>div.output>div.desktop>fieldset>div.status { border-top:#3e4040 solid 1px; } +body.dark fieldset.macos.desktop>div.output>div.desktop fieldset table.content tbody tr:nth-child(odd) { background-color:#1a1d1e; color:white; } +body.dark fieldset.macos.desktop>div.output>div.desktop fieldset table.content tbody tr:nth-child(even) { background-color:#282B2F; color:white; } +body.dark fieldset.macos.desktop>div.output>div.desktop fieldset input { background-color:#333434; border:#404141 solid 1px; color:white; caret-color:white; } +body.dark fieldset.macos.desktop>div.output>div.desktop fieldset>div.output.card>div.item { border:#3e4040 solid 1px; } +body.dark fieldset.macos.desktop>div.output>div.desktop fieldset>div.output.card>div.item>div.title { border-bottom:#3e4040 solid 1px; } +body.dark div.carte.macos.float { background-color:#29323beb; color:#e8eaed; } +body.light fieldset.macos.desktop>div.output { background-color:unset; } +body.black fieldset.macos.desktop>div.output>div.desktop>fieldset { background-color:#3433337a; } +body.black fieldset.macos.desktop>div.output>div.desktop>fieldset>div.output { background-color:#1a1d1d9c; } +body.black fieldset.macos.desktop>div.output>div.desktop fieldset table.content tbody tr:nth-child(odd) { background-color:#1a1d1ee0; color:white; } +body.black fieldset.macos.desktop>div.output>div.desktop fieldset table.content tbody tr:nth-child(even) { background-color:#282b2fc7; color:white; } +body.white fieldset.macos.desktop>div.output>div.desktop>fieldset { background-color:#f5f5f594; } +body.white fieldset.macos.desktop>div.output>div.desktop>fieldset>legend { color:black; } +body.white fieldset.macos.desktop>div.output>div.desktop>fieldset>div.output { background-color:#ffffff94; } +body.white fieldset.macos.desktop>div.output>div.desktop fieldset table.content tbody tr:nth-child(odd) { background-color:#a5afbdb5; color:black; } +body.white fieldset.macos.desktop>div.output>div.desktop fieldset table.content tbody tr:nth-child(even) { background-color:#d4dddfd4; color:black; } diff --git a/core/chat/macos/desktop.go b/core/chat/macos/desktop.go new file mode 100644 index 00000000..86f7ab20 --- /dev/null +++ b/core/chat/macos/desktop.go @@ -0,0 +1,7 @@ +package macos + +import ice "shylinux.com/x/icebergs" + +const DESKTOP = "desktop" + +func init() { Index.MergeCommands(ice.Commands{DESKTOP: {Actions: CmdHashAction()}}) } diff --git a/core/chat/macos/desktop.js b/core/chat/macos/desktop.js new file mode 100644 index 00000000..098abe42 --- /dev/null +++ b/core/chat/macos/desktop.js @@ -0,0 +1,146 @@ +Volcanos(chat.ONIMPORT, { + _init: function(can, msg, cb) { if (can.isCmdMode()) { can.onappend.style(can, html.OUTPUT), can.ConfHeight(can.page.height()) } can.onimport.layout(can) + can.ui = {}, can.base.isFunc(cb) && cb(msg), can.onmotion.clear(can), can.onlayout.background(can, can.user.info.background, can._fields) + can.onimport._menu(can), can.onimport._dock(can), can.onimport._searchs(can), can.onimport._notifications(can) + }, + _menu: function(can) { can.onappend.plugin(can, {index: "web.chat.macos.menu", style: html.OUTPUT}, function(sub) { can.ui.menu = sub + sub.onexport.record = function(_, value, key, item) { delete(can.onfigure._path) + switch (value) { + case "create": + can.onaction.create(event, can) + break + case "desktop": var carte = can.user.carte(event, can, {}, can.core.Item(can.onfigure), function(event, button, meta, carte) { can.onfigure[button](event, can, carte) }); break + case "searchs": can.onmotion.toggle(can, can.ui.searchs._target); break + case "notifications": can.onmotion.toggle(can, can.ui.notifications._target); break + } + } + sub.onexport.output = function() { can.onimport._desktop(can, can._msg) } + }) }, + _searchs: function(can) { can.onappend.plugin(can, {index: "web.chat.macos.searchs"}, function(sub) { can.ui.searchs = sub + can.page.style(can, sub._target, html.LEFT, can.ConfWidth()/4, html.TOP, can.ConfHeight()/4), sub.onimport.size(sub, can.ConfHeight()/2, can.ConfWidth()/2, true) + sub.onexport.record = function(sub, value, key, item) { + if (item.cmd == ctx.COMMAND) { can.onimport._window(can, {index: can.core.Keys(item.type, item.name.split(lex.SP)[0])}) } + } + }) }, + _notifications: function(can) { can.onappend.plugin(can, {index: "web.chat.macos.notifications", style: html.OUTPUT}, function(sub) { can.ui.notifications = sub + sub.onexport.record = function(sub, value, key, item) { can.onimport._window(can, item) } + }) }, + _dock: function(can) { can.onappend.plugin(can, {index: "web.chat.macos.dock", style: html.OUTPUT}, function(sub) { can.ui.dock = sub + sub.onexport.output = function(sub, msg) { can.page.style(can, sub._target, html.LEFT, (can.ConfWidth()-msg.Length()*80)/2) } + sub.onexport.record = function(sub, value, key, item) { can.onimport._window(can, item) } + }) }, + _item: function(can, item) { can.runAction(can.request(event, item), mdb.CREATE, [], function() { can.run(event, [], function(msg) { + can.page.SelectChild(can, can.ui.desktop, html.DIV_ITEM, function(target) { can.page.Remove(can, target) }), can.onimport.__item(can, msg, can.ui.desktop) + }) }) }, + __item: function(can, msg, target) { msg = msg||can._msg, msg.Table(function(item, index) { + can.page.Append(can, target, [{view: html.ITEM, list: [{view: html.ICON, list: [{img: can.misc.PathJoin(item.icon)}]}, {view: [mdb.NAME, "", item.name]}], + onclick: function(event) { can.onimport._window(can, item) }, style: can.onexport.position(can, index), + oncontextmenu: function(event) { var carte = can.user.carteRight(event, can, { + remove: function() { can.runAction(event, mdb.REMOVE, [item.hash]) }, + }); can.page.style(can, carte._target, html.TOP, event.y) }, + }]) + }) }, + _desktop: function(can, msg) { var target = can.page.Append(can, can._output, [{view: html.DESKTOP}])._target; can.onimport.__item(can, msg, target), can.ui.desktop = target + target._tabs = can.onimport.tabs(can, [{name: "Desktop"+(can.page.Select(can, can._output, html.DIV_DESKTOP).length-1)}], function() { can.onmotion.select(can, can._output, "div.desktop", target), can.ui.desktop = target }, function() { can.page.Remove(can, target) }, can.ui.menu._output), target._tabs._desktop = target + target.ondragend = function() { can.onimport._item(can, window._drag_item) } + }, + _window: function(can, item) { item.height = can.base.Min(can.ConfHeight()-400, 320, 800), item.width = can.base.Min(can.ConfWidth()-400, 480, 1000) + can.onappend.plugin(can, item, function(sub) { can.ondetail.select(can, sub._target) + var index = 0; can.core.Item({ + "#f95f57": function(event) { sub.onaction.close(event, sub) }, + "#fcbc2f": function(event) { + var dock = can.page.Append(can, can.ui.dock._output, [{view: html.ITEM, list: [{view: html.ICON, list: [{img: can.misc.PathJoin(item.icon)}]}], onclick: function() { + can.onmotion.toggle(can, sub._target, true), can.page.Remove(can, dock) + }}])._target; sub.onmotion.hidden(sub, sub._target) + }, + "#32c840": function(event) { sub.onaction.full(event, sub) }, + }, function(color, cb) { can.page.insertBefore(can, [{view: [[html.ITEM, html.BUTTON]], style: {"background-color": color, right: 10+20*index++}, onclick: cb}], sub._output) }) + sub.onimport.size(sub, item.height, item.width, true), can.onmotion.move(can, sub._target, {"z-index": 10, top: 125, left: 100}) + sub.onmotion.resize(can, sub._target, function(height, width) { sub.onimport.size(sub, height, width) }, 25) + sub.onexport.record = function(sub, value, key, item) { can.onimport._window(can, item) } + sub.onexport.actionHeight = function(sub) { return can.page.ClassList.has(can, sub._target, html.OUTPUT)? 0: html.ACTION_HEIGHT+20 }, + sub.onexport.marginTop = function() { return 25 } + sub.onappend.desktop = function(item) { can.onimport._item(can, item) } + sub.onappend.dock = function(item) { can.ui.dock.runAction(can.request(event, item), mdb.CREATE, [], function() { can.ui.dock.Update() }) } + }, can.ui.desktop) + }, + session: function(can, list) { can.page.Select(can, can._output, html.DIV_DESKTOP, function(target) { can.page.Remove(can, target) }), can.onmotion.clear(can, can._action) + can.core.List(list, function(item) { can.onimport._desktop(can), can.core.List(item.list, function(item) { can.onimport._window(can, item) }) }) + }, + layout: function(can) { can.page.styleHeight(can, can._output, can.ConfHeight()) }, +}, [""]) +Volcanos(chat.ONACTION, {list: ["full"], + create: function(event, can, button) { can.onimport._desktop(can) }, + full: function(event, can) { document.body.requestFullscreen() }, +}) +Volcanos(chat.ONDETAIL, { + select: function(can, target) { can.page.SelectChild(can, can.ui.desktop, html.FIELDSET, function(fieldset) { + can.page.style(can, fieldset, "z-index", fieldset == target? "10": "9"), fieldset == target && can.onmotion.toggle(can, fieldset, true) + }) }, +}) +Volcanos(chat.ONFIGURE, { + "session\t>": function(event, can, carte) { can.runActionCommand(event, "session", [], function(msg) { + var _carte = can.user.carteRight(event, can, {}, [{view: [html.ITEM, "", mdb.CREATE], onclick: function(event) { + can.user.input(event, can, [mdb.NAME], function(list) { + var args = can.page.SelectChild(can, can._output, html.DIV_DESKTOP, function(target) { + return {name: can.page.Select(can, target._tabs, html.SPAN_NAME).innerText, list: can.page.SelectChild(can, target, html.FIELDSET, function(target) { + return {index: target._can._index, args: target._can.onexport.args(target._can), style: {left: target.offsetLeft, top: target.offsetTop}} + })} + }) + can.runActionCommand(event, "session", [ctx.ACTION, mdb.CREATE, mdb.NAME, list[0], ctx.ARGS, JSON.stringify(args)], function(msg) { + can.user.toastSuccess(can, "session created") + }) + }) + }}].concat("", msg.Table(function(value) { + return {view: [html.ITEM, "", value.name], + onclick: function() { can.onimport.session(can, can.base.Obj(value.args, [])) }, + oncontextmenu: function(event) { can.user.carteRight(event, can, { + remove: function() { can.runActionCommand(event, "session", [mdb.REMOVE, value.name], function() { can.user.toastSuccess(can, "session removed") }) }, + }, [], function() {}, _carte) }, + } + })), function(event) {}, carte) + }) }, + "desktop\t>": function(event, can, carte) { + var _carte = can.user.carteRight(event, can, {}, [{view: [html.ITEM, "", mdb.CREATE], onclick: function(event) { + can.onaction.create(event, can), can.user.toastSuccess(can, "desktop created") + }}].concat("", can.page.Select(can, can.ui.menu._output, "div.tabs>span.name", function(target) { + return {view: [html.ITEM, "", target.innerText+(can.page.ClassList.has(can, target.parentNode, html.SELECT)? " *": "")], + onclick: function(event) { target.click() }, + oncontextmenu: function(event) { can.user.carteRight(event, can, { + remove: function() { target.parentNode._close(), can.user.toastSuccess(can, "desktop removed") }, + }, [], function() {}, _carte) }, + } + })), function(event) {}, carte) + }, + "window\t>": function(event, can, carte) { + can.user.carteRight(event, can, {}, [{view: [html.ITEM, "", mdb.CREATE], onclick: function(event) { + can.user.input(event, can, [ctx.INDEX, ctx.ARGS], function(data) { + can.onimport._window(can, data) + }) + }}, ""].concat(can.page.Select(can, can.ui.desktop, "fieldset>legend", function(legend) { + return {view: [html.ITEM, "", legend.innerText+(legend.parentNode.style["z-index"] == "10"? " *": "")], onclick: function(event) { + can.ondetail.select(can, legend.parentNode) + }} + })), function(event) {}, carte) + }, + "layout\t>": function(event, can, carte) { var list = can.page.SelectChild(can, can.ui.desktop, html.FIELDSET) + can.user.carteRight(event, can, { + grid: function(event) { for (var i = 0; i*i < list.length; i++) {} for (var j = 0; j*i < list.length; j++) {} + var height = (can.ConfHeight()-25)/j, width = can.ConfWidth()/i; can.core.List(list, function(target, index) { + can.page.style(can, target, html.TOP, parseInt(index/i)*height+25, html.LEFT, index%i*width) + target._can.onimport.size(target._can, height, width) + }) + }, + free: function(event) { can.core.List(list, function(target, index) { + can.page.style(can, target, html.TOP, can.ConfHeight()/2/list.length*index+25, html.LEFT, can.ConfWidth()/2/list.length*index) + }) }, + full: function(event) { can.onaction.full(event, can) }, + }, [], function(event) {}, carte) + }, +}) +Volcanos(chat.ONEXPORT, { + position: function(can, index) { var top = 25, margin = 20, height = 100, width = 80 + var n = parseInt((can.ConfHeight()-top)/(height+margin)) + return {top: index%n*height+top+margin/2, left: parseInt(index/n)*(width+margin)+margin/2} + } +}) diff --git a/core/chat/macos/dock.go b/core/chat/macos/dock.go new file mode 100644 index 00000000..18c19e16 --- /dev/null +++ b/core/chat/macos/dock.go @@ -0,0 +1,13 @@ +package macos + +import ( + ice "shylinux.com/x/icebergs" +) + +const DOCK = "dock" + +func init() { Index.MergeCommands(ice.Commands{DOCK: {Actions: CmdHashAction()}}) } + +func DockAppend(m *ice.Message, name, index string, arg ...string) { + install(m, DOCK, name, index, arg...) +} diff --git a/core/chat/macos/dock.js b/core/chat/macos/dock.js new file mode 100644 index 00000000..f797c513 --- /dev/null +++ b/core/chat/macos/dock.js @@ -0,0 +1,21 @@ +Volcanos(chat.ONIMPORT, {_init: function(can, msg) { + function show(msg) { can.onmotion.clear(can) + msg.Table(function(item) { can.page.Append(can, can._output, [{view: html.ITEM, list: [{view: html.ICON, list: [{img: can.misc.PathJoin(item.icon)}] }], + onclick: function(event) { can.sup.onexport.record(can, item.name, mdb.NAME, item) }, + oncontextmenu: function(event) { var carte = can.user.carte(event, can, { + remove: function() { item.name != "Finder" && can.runAction(event, mdb.REMOVE, [item.hash]) }, + }); can.page.style(can, carte._target, html.LEFT, event.x) }, + }]) }), can.page.Append(can, can._output, [{view: "space"}]) + } show(msg) + return + var current = null, before, begin + can.page.SelectChild(can, can._output, mdb.FOREACH, function(target) { target.draggable = true + target.ondragstart = function() { current = target, can.page.style(can, target, "visibility", html.HIDDEN) } + target.ondragenter = function(event) { before = target, begin = {x: event.x, y: event.y} } + target.ondragover = function(event) { var offset = event.x - begin.x; can.page.style(can, target, {position: "relative", left: -offset}) } + target.ondragleave = function(event) { } + target.ondragend = function(event) { before && can.page.insertBefore(can, current, before) + can.page.SelectChild(can, can._output, mdb.FOREACH, function(target) { can.page.style(can, target, {position: "", left: "", visibility: html.VISIBLE}) }) + } + }) +}}) diff --git a/core/chat/macos/finder.go b/core/chat/macos/finder.go new file mode 100644 index 00000000..18923d8a --- /dev/null +++ b/core/chat/macos/finder.go @@ -0,0 +1,32 @@ +package macos + +import ( + ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/log" + "shylinux.com/x/icebergs/base/mdb" + "shylinux.com/x/icebergs/base/web" +) + +const FINDER = "finder" + +func init() { + Index.MergeCommands(ice.Commands{ + FINDER: {Name: "finder list", Actions: ice.MergeActions(ice.Actions{ + ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { + if m.Cmd(DOCK).Length() == 0 { + DockAppend(m, "Finder", m.PrefixKey()) + DockAppend(m, "Safari", web.CHAT_IFRAME) + DockAppend(m, "Terminal", web.CODE_XTERM) + DockAppend(m, "", web.CODE_VIMER) + } + }}, + mdb.SEARCH: {Hand: func(m *ice.Message, arg ...string) { + mdb.IsSearchForEach(m, arg, func() []string { return []string{web.LINK, DESKTOP, m.MergePodCmd("", DESKTOP, log.DEBUG, ice.TRUE)} }) + }}, + }, CmdHashAction(mdb.NAME))}, + }) +} + +func FinderAppend(m *ice.Message, name, index string, arg ...string) { + install(m, FINDER, name, index, arg...) +} diff --git a/core/chat/macos/finder.js b/core/chat/macos/finder.js new file mode 100644 index 00000000..5273c1e5 --- /dev/null +++ b/core/chat/macos/finder.js @@ -0,0 +1,20 @@ +Volcanos(chat.ONIMPORT, { _init: function(can, msg) { can.onmotion.clear(can), can.ui = can.onappend.layout(can), msg.Table(function(value, index) { + var item = can.onimport.item(can, value, function(event) { if (can.onmotion.cache(can, function() { return value.name }, can.ui.content)) { return } + can.runActionCommand(event, value.index, [], function(msg) { + switch (value.name) { + case "Applications": can.onimport.icons(can, msg, can.ui.content); break + default: can.onappend.table(can, msg, null, can.ui.content) + } can.onimport.layout(can) + }) + }); index == 0 && item.click() + }), can.onmotion.hidden(can, can.ui.profile), can.onmotion.hidden(can, can.ui.display) }, + icons: function(can, msg, target) { msg.Table(function(value) { value.icon = can.misc.PathJoin(value.icon||can.page.drawText(can, value.name, 80)) + var item = can.page.Append(can, target, [{view: html.ITEM, list: [{view: html.ICON, list: [{img: value.icon}]}, {view: [mdb.NAME, "", value.name]}], onclick: function(event) { + can.sup.onexport.record(can.sup, value.name, mdb.NAME, value) + }, oncontextmenu: function(event) { can.user.carteRight(event, can, { + "add to desktop": function() { can.sup.onappend.desktop(value) }, + "add to dock": function() { can.sup.onappend.dock(value) }, + }, []) }}])._target; item.draggable = true, item.ondragstart = function(event) { window._drag_item = value } + }) }, + layout: function(can) { can.ui.layout(can.ConfHeight(), can.ConfWidth()) }, +}) diff --git a/core/chat/macos/macos.go b/core/chat/macos/macos.go new file mode 100644 index 00000000..8bf0cb4c --- /dev/null +++ b/core/chat/macos/macos.go @@ -0,0 +1,36 @@ +package macos + +import ( + ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/ctx" + "shylinux.com/x/icebergs/base/mdb" + "shylinux.com/x/icebergs/base/nfs" + "shylinux.com/x/icebergs/core/chat" + kit "shylinux.com/x/toolkits" +) + +const ( + USR_ICONS = "usr/icons/" +) +const MACOS = "macos" + +var Index = &ice.Context{Name: MACOS, Commands: ice.Commands{ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { ice.Info.Load(m).Cmd(FINDER, ice.CTX_INIT) }}}} + +func init() { chat.Index.Register(Index, nil, DESKTOP) } + +func Prefix(arg ...string) string { return chat.Prefix(MACOS, kit.Keys(arg)) } + +func CmdHashAction(arg ...string) ice.Actions { + file := kit.PathJoin("/require/", kit.FileLines(2)) + return ice.MergeActions(ice.Actions{ + mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { + switch mdb.HashInputs(m, arg); arg[0] { + case mdb.NAME: + m.Cmd(nfs.DIR, USR_ICONS, func(value ice.Maps) { m.Push(arg[0], kit.TrimExt(value[nfs.PATH], nfs.PNG)) }) + case mdb.ICON: + m.Cmd(nfs.DIR, USR_ICONS, func(value ice.Maps) { m.Push(arg[0], value[nfs.PATH]) }) + } + }}, + mdb.SELECT: {Name: "list hash auto create", Hand: func(m *ice.Message, arg ...string) { mdb.HashSelect(m, arg...).Sort(mdb.NAME).Display(file) }}, + }, ctx.CmdAction(), mdb.HashAction(mdb.SHORT, kit.Select("", arg, 0), mdb.FIELD, kit.Select("time,hash,name,icon,text,index,args", arg, 1), kit.Slice(arg, 2))) +} diff --git a/core/chat/macos/macos.shy b/core/chat/macos/macos.shy new file mode 100644 index 00000000..52ae4615 --- /dev/null +++ b/core/chat/macos/macos.shy @@ -0,0 +1,17 @@ +title "MacOS" +chain ` +desktop + menu + notifications + searchs + session + desktop + window + layout + dock + Finder + Applications + Pictures + Safari + Terminal +` \ No newline at end of file diff --git a/core/chat/macos/menu.go b/core/chat/macos/menu.go new file mode 100644 index 00000000..ae0d587e --- /dev/null +++ b/core/chat/macos/menu.go @@ -0,0 +1,7 @@ +package macos + +import ice "shylinux.com/x/icebergs" + +const MENU = "menu" + +func init() { Index.MergeCommands(ice.Commands{MENU: {Actions: CmdHashAction()}}) } diff --git a/core/chat/macos/menu.js b/core/chat/macos/menu.js new file mode 100644 index 00000000..89930200 --- /dev/null +++ b/core/chat/macos/menu.js @@ -0,0 +1,6 @@ +Volcanos(chat.ONIMPORT, {_init: function(can, msg) { can.page.Append(can, can._output, can.user.header(can)), can.page.Append(can, can._output, [ + {view: [html.ITEM, "", "notifications"], onclick: function(event) { can.sup.onexport.record(can, "notifications") }}, + {view: [html.ITEM, "", "searchs"], onclick: function(event) { can.sup.onexport.record(can, "searchs") }}, + {view: [html.MENU, "", location.hostname], onclick: function(event) { can.sup.onexport.record(can, html.DESKTOP) }}, + {view: [html.MENU, "", "+"], onclick: function(event) { can.sup.onexport.record(can, mdb.CREATE) }}, +]) }}) diff --git a/core/chat/macos/notifications.go b/core/chat/macos/notifications.go new file mode 100644 index 00000000..3b767f31 --- /dev/null +++ b/core/chat/macos/notifications.go @@ -0,0 +1,22 @@ +package macos + +import ( + ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/mdb" + kit "shylinux.com/x/toolkits" +) + +const NOTIFICATIONS = "notifications" + +func init() { + Index.MergeCommands(ice.Commands{NOTIFICATIONS: {Name: "notifications list", Actions: ice.MergeActions(ice.Actions{ + mdb.PRUNES: {Name: "prunes", Hand: func(m *ice.Message, arg ...string) { + m.Conf("", kit.Keys(mdb.HASH), "") + }}, + }, CmdHashAction()), Hand: func(m *ice.Message, arg ...string) { + mdb.HashSelect(m, arg...).SortStrR(mdb.TIME).Display("") + }}}) +} +func Notify(m *ice.Message, name, text string, arg ...string) { + m.Cmd(NOTIFICATIONS, mdb.CREATE, mdb.NAME, name, mdb.TEXT, text, arg) +} diff --git a/core/chat/macos/notifications.js b/core/chat/macos/notifications.js new file mode 100644 index 00000000..4b414884 --- /dev/null +++ b/core/chat/macos/notifications.js @@ -0,0 +1,11 @@ +Volcanos(chat.ONIMPORT, {_init: function(can, msg) { + can.onappend._action(can), can.page.style(can, can._action, html.DISPLAY, html.BLOCK) + can.page.Appends(can, can._output, msg.Table(function(item) { return {view: html.ITEM, _init: function(target) { + target.onclick = function(event) { can.sup.onexport.record(can.sup, item.index, ctx.INDEX, item), can.runAction(event, mdb.REMOVE, [item.hash], function() { can.page.Remove(can, target) }) } + var ui = can.onappend.layout(can, [html.ICON, [[wiki.TITLE, mdb.TIME], wiki.CONTENT]], "", target) + can.page.Append(can, ui.icon, [{img: can.misc.PathJoin(item.icon||can.page.drawText(can, item.index, 60))}]) + ui.title.innerHTML = item.name||"", ui.content.innerHTML = item.text||"", ui.time.innerHTML = item.time.split(lex.SP).pop().split(nfs.DF).slice(0, 2).join(nfs.DF) + }} })) +}}) +Volcanos(chat.ONACTION, {list: [mdb.PRUNES], +}) \ No newline at end of file diff --git a/core/chat/macos/opens.go b/core/chat/macos/opens.go new file mode 100644 index 00000000..8aedbb28 --- /dev/null +++ b/core/chat/macos/opens.go @@ -0,0 +1,20 @@ +package macos + +import ( + "strings" + + ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/cli" +) + +const OPENS = "opens" + +func init() { + Index.MergeCommands(ice.Commands{ + OPENS: {Name: "open app auto", Hand: func(m *ice.Message, arg ...string) { + if strings.HasPrefix(m.Option(ice.MSG_USERWEB), "http://localhost:") { + m.Cmd(cli.SYSTEM, "open", "-a", arg) + } + }}, + }) +} diff --git a/core/chat/macos/searchs.go b/core/chat/macos/searchs.go new file mode 100644 index 00000000..ee19c119 --- /dev/null +++ b/core/chat/macos/searchs.go @@ -0,0 +1,15 @@ +package macos + +import ( + ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/mdb" + kit "shylinux.com/x/toolkits" +) + +const SEARCHS = "searchs" + +func init() { + Index.MergeCommands(ice.Commands{SEARCHS: {Name: "search keyword list", Hand: func(m *ice.Message, arg ...string) { + m.Cmdy(mdb.SEARCH, mdb.FOREACH, kit.Select("", arg, 0), "ctx,cmd,type,name,text") + }}}) +} diff --git a/core/chat/macos/session.go b/core/chat/macos/session.go new file mode 100644 index 00000000..fea047a2 --- /dev/null +++ b/core/chat/macos/session.go @@ -0,0 +1,10 @@ +package macos + +import ( + ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/mdb" +) + +const SESSION = "session" + +func init() { Index.MergeCommands(ice.Commands{SESSION: {Actions: CmdHashAction(mdb.NAME)}}) } diff --git a/core/code/vimer.go b/core/code/vimer.go index 52750ffd..6668ad97 100644 --- a/core/code/vimer.go +++ b/core/code/vimer.go @@ -175,7 +175,7 @@ func init() { }, aaa.RoleAction(ctx.COMMAND), web.DreamAction(), mdb.HashAction(mdb.SHORT, nfs.PATH, mdb.FIELD, "time,path")), Hand: func(m *ice.Message, arg ...string) { if m.Cmdy(INNER, arg); arg[0] != ctx.ACTION { kit.If(len(arg) > 1, func() { mdb.HashCreate(m.Spawn(), nfs.PATH, path.Join(kit.Slice(arg, 0, 2)...)) }) - m.Action(nfs.MODULE, nfs.SCRIPT, nfs.SAVE, COMPILE, "show", "exec") + m.Action(nfs.SAVE, COMPILE, "show", "exec") ctx.DisplayLocal(m, "") } }}, diff --git a/core/core.go b/core/core.go index 1e02af17..5893216f 100644 --- a/core/core.go +++ b/core/core.go @@ -2,6 +2,7 @@ package shy import ( _ "shylinux.com/x/icebergs/core/chat" + _ "shylinux.com/x/icebergs/core/chat/macos" _ "shylinux.com/x/icebergs/core/chat/oauth" _ "shylinux.com/x/icebergs/core/code" _ "shylinux.com/x/icebergs/core/mall" diff --git a/render.go b/render.go index db7ea6de..e3a1fc22 100644 --- a/render.go +++ b/render.go @@ -201,7 +201,7 @@ func (m *Message) EchoDownload(arg ...string) *Message { } func (m *Message) Display(file string, arg ...Any) { if file == "" { - file = kit.FileLine(2, 100) + file = kit.PathJoin("/require/", kit.FileLines(2)) } m.Option(MSG_DISPLAY, kit.MergeURL(kit.Select(kit.ExtChange(file, JS), file, strings.Contains(file, QS)), arg...)) }