From e668707738f940b8601a1655beaf4da66f1ae3f3 Mon Sep 17 00:00:00 2001 From: shy Date: Wed, 24 Jan 2024 19:15:31 +0800 Subject: [PATCH] add chat.message --- base/web/dream.go | 4 +- base/web/spide.go | 8 +-- base/web/store.go | 36 ++++++----- base/web/store.js | 24 +++++--- core/chat/location/location.js | 2 + core/chat/message.css | 45 ++++++++++++++ core/chat/message.go | 56 +++++++++++++++++ core/chat/message.js | 109 +++++++++++++++++++++++++++++++++ 8 files changed, 252 insertions(+), 32 deletions(-) create mode 100644 core/chat/message.css create mode 100644 core/chat/message.go create mode 100644 core/chat/message.js diff --git a/base/web/dream.go b/base/web/dream.go index e010676d..6eb9e9bd 100644 --- a/base/web/dream.go +++ b/base/web/dream.go @@ -424,9 +424,7 @@ func init() { func DreamAction() ice.Actions { return ice.MergeActions(ice.Actions{ - DREAM_ACTION: {Hand: func(m *ice.Message, arg ...string) { - DreamProcess(m, nil, arg...) - }}, + DREAM_ACTION: {Hand: func(m *ice.Message, arg ...string) { DreamProcess(m, nil, arg...) }}, }, gdb.EventsAction(DREAM_OPEN, DREAM_CLOSE, DREAM_INPUTS, DREAM_CREATE, DREAM_TRASH, DREAM_TABLES, DREAM_ACTION, SERVE_START)) } func DreamProcess(m *ice.Message, args ice.Any, arg ...string) { diff --git a/base/web/spide.go b/base/web/spide.go index 01f43dea..031cc31c 100644 --- a/base/web/spide.go +++ b/base/web/spide.go @@ -295,16 +295,16 @@ func init() { Index.MergeCommands(ice.Commands{ // SPIDE: {Name: "spide client.name action=raw,msg,save,cache method=GET,PUT,POST,DELETE url format=form,part,json,data,file arg run create", Help: "蜘蛛侠", Actions: ice.MergeActions(ice.Actions{ SPIDE: {Help: "蜘蛛侠", Meta: kit.Dict(ice.CTX_TRANS, kit.Dict(html.INPUT, kit.Dict( - CLIENT_TYPE, "类型", - CLIENT_NAME, "名称", CLIENT_URL, "地址", + CLIENT_TYPE, "类型", CLIENT_NAME, "名称", CLIENT_URL, "地址", CLIENT_METHOD, "方法", CLIENT_ORIGIN, "服务", CLIENT_TIMEOUT, "超时", CLIENT_PROTOCOL, "协议", CLIENT_HOST, "主机", CLIENT_HOSTNAME, "机器", ))), Actions: ice.MergeActions(ice.Actions{ ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { conf := mdb.Confm(m, cli.RUNTIME, cli.CONF) + dev := kit.Select("https://2021.shylinux.com", ice.Info.Make.Domain, conf[cli.CTX_DEV]) m.Cmd("", mdb.CREATE, ice.SHY, kit.Select("https://shylinux.com", conf[cli.CTX_SHY]), nfs.REPOS) - m.Cmd("", mdb.CREATE, ice.DEV, kit.Select("https://2021.shylinux.com", ice.Info.Make.Domain, conf[cli.CTX_DEV]), nfs.REPOS) - m.Cmd("", mdb.CREATE, "dev_ip", kit.Select("https://2021.shylinux.com", os.Getenv("ctx_dev_ip")), nfs.REPOS) + m.Cmd("", mdb.CREATE, ice.DEV, dev, nfs.REPOS) + m.Cmd("", mdb.CREATE, ice.DEV_IP, kit.Select(dev, os.Getenv("ctx_dev_ip")), nfs.REPOS) m.Cmd("", mdb.CREATE, ice.OPS, kit.Select("http://localhost:9020", conf[cli.CTX_OPS]), nfs.REPOS) m.Cmd("", mdb.CREATE, ice.DEMO, kit.Select("http://localhost:20000", conf[cli.CTX_DEMO])) m.Cmd("", mdb.CREATE, ice.MAIL, kit.Select("https://mail.shylinux.com", conf[cli.CTX_MAIL])) diff --git a/base/web/store.go b/base/web/store.go index 8b218383..dbd54e0f 100644 --- a/base/web/store.go +++ b/base/web/store.go @@ -5,10 +5,12 @@ import ( "strings" ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/aaa" "shylinux.com/x/icebergs/base/cli" "shylinux.com/x/icebergs/base/ctx" "shylinux.com/x/icebergs/base/mdb" "shylinux.com/x/icebergs/base/nfs" + "shylinux.com/x/icebergs/base/web/html" kit "shylinux.com/x/toolkits" ) @@ -16,15 +18,14 @@ const STORE = "store" func init() { Index.MergeCommands(ice.Commands{ - STORE: {Name: "store", Help: "系统商店", Actions: ice.MergeActions(ice.Actions{ + STORE: {Name: "store", Help: "系统商店", Role: aaa.VOID, Actions: ice.MergeActions(ice.Actions{ mdb.INPUTS: {Hand: func(m *ice.Message, arg ...string) { m.Cmds(SPIDE).Table(func(value ice.Maps) { kit.If(value[CLIENT_TYPE] == nfs.REPOS, func() { m.Push("", value, arg[0]) }) }) }}, mdb.CREATE: {Name: "create name* origin*", Hand: func(m *ice.Message, arg ...string) { - m.Option(mdb.TYPE, nfs.REPOS) - m.Cmd(SPIDE, mdb.CREATE, m.OptionSimple("name,origin,type")) + m.Cmd(SPIDE, mdb.CREATE, m.OptionSimple("name,origin"), mdb.TYPE, nfs.REPOS) }}, - "install": {Help: "安装", Hand: func(m *ice.Message, arg ...string) { + "install": {Hand: func(m *ice.Message, arg ...string) { if !kit.HasPrefixList(arg, ctx.RUN) { if !nfs.Exists(m, path.Join(ice.USR_LOCAL_WORK, m.Option(mdb.NAME))) { if strings.HasPrefix(m.Option(mdb.ICON), nfs.REQUIRE) { @@ -39,31 +40,36 @@ func init() { ctx.ProcessField(m, CHAT_IFRAME, S(m.Option(mdb.NAME)), arg...) }}, OPEN: {Hand: func(m *ice.Message, arg ...string) { - if !kit.HasPrefixList(arg, ctx.RUN) { - defer m.Push("title", m.Option(mdb.NAME)) - } ctx.ProcessField(m, CHAT_IFRAME, S(m.Option(mdb.NAME)), arg...) + kit.If(!kit.HasPrefixList(arg, ctx.RUN), func() { m.Push("title", m.Option(mdb.NAME)) }) }}, - PORTAL: {Help: "官网", Hand: func(m *ice.Message, arg ...string) { - if !kit.HasPrefixList(arg, ctx.RUN) { - defer m.Push("title", m.Option(mdb.NAME)) - } + PORTAL: {Hand: func(m *ice.Message, arg ...string) { ctx.ProcessField(m, CHAT_IFRAME, m.Option(ORIGIN)+S(m.Option(mdb.NAME))+C(PORTAL), arg...) + kit.If(!kit.HasPrefixList(arg, ctx.RUN), func() { m.Push("title", m.Option(mdb.NAME)) }) }}, }, ctx.ConfAction(ctx.TOOLS, DREAM)), Hand: func(m *ice.Message, arg ...string) { if len(arg) == 0 { - m.Cmdy(SPIDE, arg, kit.Dict(ice.MSG_FIELDS, "time,client.type,client.name,client.origin")).Action(mdb.CREATE).Display("") + m.Cmd(SPIDE, arg, kit.Dict(ice.MSG_FIELDS, "time,client.type,client.name,client.origin")).Table(func(value ice.Maps) { + if value[CLIENT_TYPE] == nfs.REPOS && value[CLIENT_NAME] != ice.OPS { + m.Push(mdb.NAME, value[CLIENT_NAME]) + } + }) + m.Action(html.FILTER, mdb.CREATE).Display("") ctx.Toolkit(m) } else { origin := SpideOrigin(m, arg[0]) - m.SetAppend().SplitIndex(m.Cmdx(SPIDE, arg[0], C(DREAM))).Table(func(value ice.Maps) { - if !nfs.Exists(m, path.Join(ice.USR_LOCAL_WORK, value[mdb.NAME])) { + m.SetAppend().Spawn().SplitIndex(m.Cmdx(SPIDE, arg[0], C(DREAM))).Table(func(value ice.Maps) { + if value[mdb.TYPE] != WORKER { + return + } + m.Push("", value, kit.Split("time,name,icon,repos,binary,module,version")) + if m.Push(ORIGIN, origin); !nfs.Exists(m, path.Join(ice.USR_LOCAL_WORK, value[mdb.NAME])) { m.PushButton("install", PORTAL) } else { m.PushButton(OPEN, PORTAL) } - m.Push(ORIGIN, origin) }) + m.StatusTimeCount(ORIGIN, origin) } }}, }) diff --git a/base/web/store.js b/base/web/store.js index 19a25b7e..702c5ef4 100644 --- a/base/web/store.js +++ b/base/web/store.js @@ -1,21 +1,24 @@ Volcanos(chat.ONIMPORT, { _init: function(can, msg) { - can.ui = can.onappend.layout(can), can.onappend.style(can, "output card", can.ui.content), can.onimport._project(can, msg) + can.ui = can.onappend.layout(can), can.onimport._project(can, msg), can.onappend.style(can, "output card", can.ui.content) can.onmotion.delay(can, function() { can.onimport.layout(can) }) can.sup.onimport._field = function(sup, msg) { msg.Table(function(item) { can.onappend._plugin(can, item, {style: html.FLOAT}, function(sub) {}) }) } }, - _project: function(can, msg) { var select - msg.Table(function(value) { if (value["client.type"] != nfs.REPOS) { return } value.name = `${value["client.name"]}` - var _target = can.onimport.item(can, value, function(event) { - if (can.onmotion.cache(can, function() { return value.name }, can.ui.content)) { return can.onimport.layout(can) } - can.run(event, [value.name], function(msg) { can.onimport._content(can, msg), can.onimport.layout(can) }) - }, function() {}, can.ui.project); select = (value.name == ice.DEV? _target: select)||_target + _project: function(can, msg) { var select, current = can.db.hash[0]||ice.DEV + msg.Table(function(value) { + var _target = can.onimport.item(can, value, function(event) { can.isCmdMode() && can.misc.SearchHash(can, value.name) + if (can.onmotion.cache(can, function() { return value.name }, can.ui.content, can._status)) { return can.onimport.layout(can) } + can.run(event, [value.name], function(msg) { + can.onappend._status(can, msg.Option(ice.MSG_STATUS)) + can.onimport._content(can, msg), can.onimport.layout(can) + }) + }, function() {}, can.ui.project); select = (value.name == current? _target: select)||_target }), select && select.click() }, - _content: function(can, msg) { var year = new Date().getFullYear()+"-" - can.page.Appends(can, can.ui.content, msg.Table(function(value) { if (value.type != web.WORKER) { return } + _content: function(can, msg) { + can.page.Appends(can, can.ui.content, msg.Table(function(value) { var icon = value.icon; if (can.base.beginWith(value.icon, nfs.PS)) { icon = value.origin+value.icon } return {view: [[html.ITEM, value.status]], list: [ {view: [wiki.TITLE, html.DIV], list: [{img: icon}, {view: mdb.NAME, list: [ @@ -25,7 +28,7 @@ Volcanos(chat.ONIMPORT, { // {icon: "bi bi-share"}, {text: value.forks_count||"0"}, // {icon: "bi bi-star"}, {text: value.stars_count||"0"}, {icon: "bi bi-folder2"}, {text: value.version.split("-").slice(0, 2).join("-")}, - {icon: "bi bi-clock"}, {text: can.base.trimPrefix(value.time.split(":").slice(0, 2).join(":"), year)}, + {icon: "bi bi-clock"}, {text: can.base.TimeTrim(value.time)}, ]} ]}]}, {view: [wiki.CONTENT, html.DIV, value.description]}, {view: html.ACTION, inner: value.action, _init: function(target) { can.onappend.mores(can, target, value, 5) }}, @@ -33,6 +36,7 @@ Volcanos(chat.ONIMPORT, { })) }, layout: function(can) { + can.Action(html.FILTER) && can.onmotion.filter(can, can.Action(html.FILTER)) can.user.isMobile && can.onmotion.toggle(can, can.ui.project, can.user.isLandscape()) can.ui.layout(can.ConfHeight(), can.ConfWidth()), can.onlayout.expand(can, can.ui.content, 320) }, diff --git a/core/chat/location/location.js b/core/chat/location/location.js index 42d49ea1..640ee3b4 100644 --- a/core/chat/location/location.js +++ b/core/chat/location/location.js @@ -1,6 +1,8 @@ Volcanos(chat.ONIMPORT, {_init: function(can, msg) {}, _layout_init: function(can, msg, cb) { can.db.list = {}, can.ui = can.onappend.layout(can), can.onimport._project(can) + can.onmotion.hidden(can, can.ui.project) + can.onmotion.hidden(can, can._action) // can.core.Item(can.ui.zone, function(key, item) { key == "favor" || item._legend.click() }) if (can.user.isMobile) { can.page.style(can, can.ui.project, "z-index", 10, "position", "absolute", html.MAX_HEIGHT, can.ConfHeight()-120) diff --git a/core/chat/message.css b/core/chat/message.css new file mode 100644 index 00000000..2570435d --- /dev/null +++ b/core/chat/message.css @@ -0,0 +1,45 @@ +body.light fieldset.web.chat.message>div.output { background-color:white; } +body.light fieldset.web.chat.message>div.output>div.layout>div.layout>div.content>div.list { background-color:#e3e3e2; } +body.light fieldset.web.chat.message>div.output>div.layout>div.layout>div.content>div.list>div.item:not(.plug).myself div.content { background-color:#94ec69; } + +fieldset.web.chat.message>div.output>div.project>div.item { height:58px; padding:var(--input-padding); } +fieldset.web.chat.message>div.output>div.project>div.item img { height:var(--header-height); width:var(--header-height); display:block; float:left; } +fieldset.web.chat.message>div.output>div.project>div.item span.time { color:var(--disable-fg-color); font-size:var(--status-font-size); } +fieldset.web.chat.message>div.output>div.project>div.item div.container { width:calc(100% - var(--header-height)); float:left; } +fieldset.web.chat.message>div.output>div.project>div.item div.title { display:flex; justify-content:space-between; } +fieldset.web.chat.message>div.output>div.project>div.item div.content { color:var(--disable-fg-color); font-size:var(--status-font-size); } +fieldset.web.chat.message>div.output>div.layout>div.layout>div.content { overflow:hidden; } +fieldset.web.chat.message>div.output>div.layout>div.layout>div.content>div.title { + font-size:24px; padding:var(--button-padding); display:flex; justify-content:space-between; position:sticky; top:0; z-index:10; +} +fieldset.web.chat.message>div.output>div.layout>div.layout>div.content>div.title i:hover { + background-color:var(--hover-bg-color); cursor:pointer; +} +fieldset.web.chat.message>div.output>div.project>div.title { + padding:var(--button-padding); + display:flex; justify-content:space-between; + position:sticky; top:0; z-index:10; +} +fieldset.web.chat.message>div.output>div.project>div.title i:hover { + background-color:var(--hover-bg-color); cursor:pointer; +} +fieldset.web.chat.message>div.output>div.layout>div.layout>div.content>div.list>div.item { padding:var(--input-padding); min-height:fit-content; display:flex; align-items:center; } +fieldset.web.chat.message>div.output>div.layout>div.layout>div.content>div.list>div.item:hover { background-color:unset; } +fieldset.web.chat.message>div.output>div.layout>div.layout>div.content>div.list>div.item.time { color:var(--disable-fg-color); font-size:var(--status-font-size); padding:0; height:fit-content; justify-content:center; } +fieldset.web.chat.message>div.output>div.layout>div.layout>div.content>div.list>div.item>img { height:var(--header-height); width:var(--header-height); } +fieldset.web.chat.message>div.output>div.layout>div.layout>div.content>div.list>div.item div.content img { max-width:256px; } +fieldset.web.chat.message>div.output>div.layout>div.layout>div.content>div.list>div.item div.container { width:fit-content; max-width:calc(100% - var(--header-height)); margin:0 var(--button-margin); } +fieldset.web.chat.message>div.output>div.layout>div.layout>div.content>div.list>div.item div.container>span.from { color:var(--disable-fg-color); font-size:var(--status-font-size); padding:0 var(--input-padding); } +fieldset.web.chat.message>div.output>div.layout>div.layout>div.content>div.list>div.item.myself div.container>span.from { float:right; } +fieldset.web.chat.message>div.output>div.layout>div.layout>div.content>div.list>div.item.myself div.container { display:flex; flex-direction:column; align-items:flex-end; } +fieldset.web.chat.message>div.output>div.layout>div.layout>div.content>div.list>div.item div.content { + display:flex; align-items:center; padding:var(--input-padding) var(--button-padding); border-radius:5px; min-height:var(--header-height); width:fit-content; +} +fieldset.web.chat.message>div.output>div.layout>div.layout>div.content>div.list>div.item.plug { height:fit-content; } +fieldset.web.chat.message>div.output>div.layout>div.layout>div.content>div.list>div.item.plug div.content { padding:0; } +fieldset.web.chat.message>div.output>div.layout>div.layout>div.content>div.list>div.item.myself { flex-direction:row-reverse; } +fieldset.web.chat.message>div.output>div.layout>div.display { height:120px; overflow:hidden; } +fieldset.web.chat.message>div.output>div.layout>div.display div.toolkit { height:var(--action-height); display:flex; } +fieldset.web.chat.message>div.output>div.layout>div.display div.toolkit i { padding:var(--input-padding); } +fieldset.web.chat.message>div.output>div.layout>div.display div.toolkit i:hover { background-color:var(--hover-bg-color); } +fieldset.web.chat.message>div.output>div.layout>div.display textarea { height:calc(100% - var(--action-height)); } diff --git a/core/chat/message.go b/core/chat/message.go new file mode 100644 index 00000000..0992a4b8 --- /dev/null +++ b/core/chat/message.go @@ -0,0 +1,56 @@ +package chat + +import ( + ice "shylinux.com/x/icebergs" + "shylinux.com/x/icebergs/base/aaa" + "shylinux.com/x/icebergs/base/cli" + "shylinux.com/x/icebergs/base/ctx" + "shylinux.com/x/icebergs/base/mdb" + "shylinux.com/x/icebergs/base/web" + kit "shylinux.com/x/toolkits" +) + +const MESSAGE = "message" + +func init() { + Index.MergeCommands(ice.Commands{ + MESSAGE: {Name: "message", Help: "消息", Icon: "Messages.png", Actions: ice.MergeActions(ice.Actions{ + ice.CTX_INIT: {Hand: func(m *ice.Message, arg ...string) { + messageCreate(m, web.DREAM, "usr/icons/Launchpad.png") + messageCreate(m, cli.SYSTEM, "usr/icons/System Settings.png") + messageInsert(m, cli.SYSTEM, mdb.TYPE, "plug", ctx.INDEX, cli.RUNTIME) + }}, + mdb.CREATE: {Name: "create type*=tech,void name* icons*"}, + mdb.INSERT: {Hand: func(m *ice.Message, arg ...string) { + mdb.ZoneInsert(m, append(arg, aaa.AVATAR, aaa.UserInfo(m, "", aaa.AVATAR, aaa.AVATAR), + aaa.USERNICK, m.Option(ice.MSG_USERNICK), aaa.USERNAME, m.Option(ice.MSG_USERNAME), + )) + }}, + web.DREAM_CREATE: {Hand: func(m *ice.Message, arg ...string) { + messageInsert(m, web.DREAM, mdb.TYPE, "plug", ctx.INDEX, IFRAME, ctx.ARGS, web.S(m.Option(mdb.NAME))) + }}, + }, web.DreamAction(), mdb.ZoneAction( + mdb.SHORT, mdb.UNIQ, mdb.FIELD, "time,hash,type,name,icons", mdb.FIELDS, "time,avatar,usernick,username,type,name,text,space,index,args", + )), Hand: func(m *ice.Message, arg ...string) { + if len(arg) == 0 { + mdb.ZoneSelect(m.Spawn(), arg...).Table(func(value ice.Maps) { + if kit.IsIn(m.Option(ice.MSG_USERROLE), value[mdb.TYPE], aaa.TECH, aaa.ROOT) { + m.PushRecord(value, mdb.Config(m, mdb.FIELD)) + } + }) + } else { + mdb.ZoneSelect(m, arg...) + } + m.Display("") + }}, + }) +} +func messageCreate(m *ice.Message, name, icon string) { + kit.Value(m.Target().Configs[m.CommandKey()].Value, kit.Keys(mdb.HASH, name, "meta.time"), m.Time()) + kit.Value(m.Target().Configs[m.CommandKey()].Value, kit.Keys(mdb.HASH, name, "meta.type"), aaa.TECH) + kit.Value(m.Target().Configs[m.CommandKey()].Value, kit.Keys(mdb.HASH, name, "meta.name"), name) + kit.Value(m.Target().Configs[m.CommandKey()].Value, kit.Keys(mdb.HASH, name, "meta.icons"), icon) +} +func messageInsert(m *ice.Message, zone string, arg ...string) { + m.Cmd("", mdb.INSERT, zone, arg, ice.Maps{ice.MSG_USERNAME: zone}) +} diff --git a/core/chat/message.js b/core/chat/message.js new file mode 100644 index 00000000..b5f1c522 --- /dev/null +++ b/core/chat/message.js @@ -0,0 +1,109 @@ +Volcanos(chat.ONIMPORT, { + _init: function(can, msg) { if (can.isCmdMode()) { can.onappend.style(can, html.OUTPUT) } + can.ui = can.onappend.layout(can), can.onimport._project(can, msg) + }, + _project: function(can, msg) { var select, current = can.db.hash[0]||ice.DEV + can.isCmdMode() && can.page.insertBefore(can, [{view: "title", list: [ + {icon: "bi bi-three-dots", onclick: function() { can.onmotion.toggle(can, can.ui.profile), can.onimport.layout(can) }}, + {text: "message"||can.ConfIndex(), onclick: function(event) { + can._legend.onclick(event) + }}, + {icon: "bi bi-plus-lg", onclick: function(event) { + can.Update(event, [ctx.ACTION, mdb.CREATE]) + }}, + ]}], can.ui.project.firstChild, can.ui.project) + msg.Table(function(value) { + var _target = can.page.Append(can, can.ui.project, [{view: html.ITEM, list: [ + {img: can.misc.Resource(can, value.icons||"usr/icons/Messages.png")}, {view: "container", list: [ + {view: "title", list: [{text: value.name||"some"}, {text: [can.base.TimeTrim(value.time), "", mdb.TIME]}]}, + {view: "content", list: [{text: value.text||"[未知消息]"}]}, + ]}, + ], onclick: function(event) { can.isCmdMode() && can.misc.SearchHash(can, value.name), can.onimport._switch(can, false) + can.db.zone = value, can.db.hash = value.hash, can.onmotion.select(can, can.ui.project, html.DIV_ITEM, _target) + if (can.onmotion.cache(can, function() { return value.name }, can._status, can.ui.content, can.ui.profile, can.ui.display)) { return can.onimport.layout(can) } + can.run(event, [value.hash], function(msg) { can.onappend._status(can, msg.Option(ice.MSG_STATUS)) + can.onimport._display(can), can.onimport._content(can, msg), can.onimport.layout(can) + }) + }}])._target; select = (value.name == current? _target: select)||_target + }), can.user.isMobile? can.onimport._switch(can, true): select && select.click() + }, + _content: function(can, msg) { + can.ui.title = can.page.Appends(can, can.ui.content, [{view: "title", list: [ + {icon: "bi bi-chevron-left", onclick: function() { can.onimport._switch(can, true) }}, + {text: can.db.zone.name}, + {icon: "bi bi-three-dots", onclick: function() { can.onmotion.toggle(can, can.ui.profile), can.onimport.layout(can) }}, + ]}])._target + can.ui.message = can.page.Append(can, can.ui.content, [{view: "list"}])._target + msg.Table(function(value) { var myself = value.username == can.user.info.username + can.page.Append(can, can.ui.message, [{view: [[html.ITEM, mdb.TIME], "", can.base.TimeTrim(value.time)]}]) + can.page.Append(can, can.ui.message, [{view: [[html.ITEM, value.type, myself? "myself": ""]], list: [ + {img: can.misc.Resource(can, (value.avatar == can.db.zone.name? "": value.avatar)||can.db.zone.icons||"usr/icons/Messages.png")}, + {view: "container", list: [{text: [value.usernick, "", "from"]}, can.onfigure[value.type](can, value)]}, + ]}]) + }) + }, + _display: function(can, msg) { + can.page.Appends(can, can.ui.display, [ + {view: "toolkit", list: can.core.Item(can.ondetail, function(icon, cb) { return {icon: icon, onclick: function(event) { cb(event, can) }} }) }, + {type: html.TEXTAREA, onkeyup: function(event) { if (event.key == "Enter" && event.ctrlKey) { + can.onimport._insert(can, [mdb.TYPE, "text", mdb.TEXT, event.target.value]) + } }}, + ]), can.onmotion.toggle(can, can.ui.display, true) + }, + _insert: function(can, args) { + can.runAction(event, mdb.INSERT, [can.db.hash].concat(args), function() { + can.run(event, [can.db.hash], function(msg) { can.onappend._status(can, msg.Option(ice.MSG_STATUS)) + can.onimport._content(can, msg), can.onimport.layout(can) + }) + }) + }, + _switch: function(can, project) { if (!can.user.isMobile) { return } + can.page.style(can, can.ui.project, html.WIDTH, can.ConfWidth()) + can.page.style(can, can.ui.project, "flex", "0 0 "+can.ConfWidth()+"px") + can.onmotion.toggle(can, can.ui.project, project) + can.onmotion.toggle(can, can.ui.content, !project) + can.onmotion.toggle(can, can.ui.display, !project) + can.onimport.layout(can) + }, + layout: function(can) { can.ui.layout(can.ConfHeight(), can.ConfWidth()) + can.ui.title && can.page.style(can, can.ui.message, html.HEIGHT, can.ui.content.offsetHeight-can.ui.title.offsetHeight) + can.ui.message && (can.ui.message.scrollTop += 10000) + }, +}, [""]) +Volcanos(chat.ONDETAIL, { + "bi bi-mic": function(event, can) {}, + "bi bi-card-image": function(event, can) { + can.user.input(event, can, [mdb.ICONS], function(args) { + can.onimport._insert(can, [mdb.TYPE, "image"].concat([mdb.TEXT, args[1]])) + }) + }, + "bi bi-camera": function(event, can) {}, + "bi bi-camera-video": function(event, can) {}, + "bi bi-file-earmark": function(event, can) {}, + "bi bi-geo-alt": function(event, can) {}, + "bi bi-window": function(event, can) { + can.user.input(event, can, [web.SPACE, ctx.INDEX, ctx.ARGS], function(args) { + can.onimport._insert(can, [mdb.TYPE, "plug"].concat(args)) + }) + }, +}) +Volcanos(chat.ONFIGURE, { + text: function(can, value) { + return {view: "content", list: [{text: value.text||"[未知消息]"}]} + }, + image: function(can, value) { + return {view: "content", list: [{img: can.misc.Resource(can, value.text)}]} + }, + plug: function(can, value) { value.type = "story" + var height = can.base.Min(can.ui.content.offsetHeight-210, 240) + var height = can.base.Max(320, height, height/(can.base.isIn(value.index, "iframe")? 1: 2)), + width = can.ui.content.offsetWidth-(can.user.isMobile? 60: 180) + return {view: "content", style: {height: height, width: width}, _init: function(target) { + can.onappend._plugin(can, value, {height: height, width: width}, function(sub) { + sub.onexport.output = function() { sub.onimport.size(sub, height, width) + can.page.style(can, target, html.HEIGHT, sub._target.offsetHeight, html.WIDTH, sub._target.offsetWidth) + } + }, target) + }} + }, +})