summaryrefslogtreecommitdiff
path: root/src/web/app/common
diff options
context:
space:
mode:
authorsyuilo <syuilotan@yahoo.co.jp>2017-02-15 15:45:01 +0900
committersyuilo <syuilotan@yahoo.co.jp>2017-02-15 15:45:01 +0900
commit3d38356a91dfbbb57b7feb4a0c069accb98dbb19 (patch)
tree0b957876e63222a006f2b5e8a0061596400bbbd6 /src/web/app/common
parent[Client] 文言を修正 (diff)
downloadmisskey-3d38356a91dfbbb57b7feb4a0c069accb98dbb19.tar.gz
misskey-3d38356a91dfbbb57b7feb4a0c069accb98dbb19.tar.bz2
misskey-3d38356a91dfbbb57b7feb4a0c069accb98dbb19.zip
[Client] Messagingをいろいろ
Diffstat (limited to 'src/web/app/common')
-rw-r--r--src/web/app/common/tags/index.js4
-rw-r--r--src/web/app/common/tags/messaging/form.tag159
-rw-r--r--src/web/app/common/tags/messaging/index.tag328
-rw-r--r--src/web/app/common/tags/messaging/message.tag230
-rw-r--r--src/web/app/common/tags/messaging/room.tag224
5 files changed, 945 insertions, 0 deletions
diff --git a/src/web/app/common/tags/index.js b/src/web/app/common/tags/index.js
index 692a7070a4..21d817dbd2 100644
--- a/src/web/app/common/tags/index.js
+++ b/src/web/app/common/tags/index.js
@@ -20,3 +20,7 @@ require('./twitter-setting.tag');
require('./authorized-apps.tag');
require('./poll.tag');
require('./poll-editor.tag');
+require('./messaging/room.tag');
+require('./messaging/message.tag');
+require('./messaging/index.tag');
+require('./messaging/form.tag');
diff --git a/src/web/app/common/tags/messaging/form.tag b/src/web/app/common/tags/messaging/form.tag
new file mode 100644
index 0000000000..8979edf288
--- /dev/null
+++ b/src/web/app/common/tags/messaging/form.tag
@@ -0,0 +1,159 @@
+<mk-messaging-form>
+ <textarea ref="text" onkeypress={ onkeypress } onpaste={ onpaste } placeholder="ここにメッセージを入力"></textarea>
+ <div class="files"></div>
+ <mk-uploader ref="uploader"></mk-uploader>
+ <button class="send" onclick={ send } disabled={ sending } title="メッセージを送信"><i class="fa fa-paper-plane" if={ !sending }></i><i class="fa fa-spinner fa-spin" if={ sending }></i></button>
+ <button class="attach-from-local" type="button" title="PCから画像を添付する"><i class="fa fa-upload"></i></button>
+ <button class="attach-from-drive" type="button" title="アルバムから画像を添付する"><i class="fa fa-folder-open"></i></button>
+ <input name="file" type="file" accept="image/*"/>
+ <style type="stylus">
+ :scope
+ display block
+
+ > textarea
+ cursor auto
+ display block
+ width 100%
+ min-width 100%
+ max-width 100%
+ height 64px
+ margin 0
+ padding 8px
+ font-size 1em
+ color #000
+ outline none
+ border none
+ border-top solid 1px #eee
+ border-radius 0
+ box-shadow none
+ background transparent
+
+ > .send
+ position absolute
+ bottom 0
+ right 0
+ margin 0
+ padding 10px 14px
+ line-height 1em
+ font-size 1em
+ color #aaa
+ transition color 0.1s ease
+
+ &:hover
+ color $theme-color
+
+ &:active
+ color darken($theme-color, 10%)
+ transition color 0s ease
+
+ .files
+ display block
+ margin 0
+ padding 0 8px
+ list-style none
+
+ &:after
+ content ''
+ display block
+ clear both
+
+ > li
+ display block
+ float left
+ margin 4px
+ padding 0
+ width 64px
+ height 64px
+ background-color #eee
+ background-repeat no-repeat
+ background-position center center
+ background-size cover
+ cursor move
+
+ &:hover
+ > .remove
+ display block
+
+ > .remove
+ display none
+ position absolute
+ right -6px
+ top -6px
+ margin 0
+ padding 0
+ background transparent
+ outline none
+ border none
+ border-radius 0
+ box-shadow none
+ cursor pointer
+
+ .attach-from-local
+ .attach-from-drive
+ margin 0
+ padding 10px 14px
+ line-height 1em
+ font-size 1em
+ font-weight normal
+ text-decoration none
+ color #aaa
+ transition color 0.1s ease
+
+ &:hover
+ color $theme-color
+
+ &:active
+ color darken($theme-color, 10%)
+ transition color 0s ease
+
+ input[type=file]
+ display none
+
+ </style>
+ <script>
+ @mixin \api
+
+ @onpaste = (e) ~>
+ data = e.clipboard-data
+ items = data.items
+ for i from 0 to items.length - 1
+ item = items[i]
+ switch (item.kind)
+ | \file =>
+ @upload item.get-as-file!
+
+ @onkeypress = (e) ~>
+ if (e.which == 10 || e.which == 13) && e.ctrl-key
+ @send!
+
+ @select-file = ~>
+ @refs.file.click!
+
+ @select-file-from-drive = ~>
+ browser = document.body.append-child document.create-element \mk-select-file-from-drive-window
+ event = riot.observable!
+ riot.mount browser, do
+ multiple: true
+ event: event
+ event.one \selected (files) ~>
+ files.for-each @add-file
+
+ @send = ~>
+ @sending = true
+ @api \messaging/messages/create do
+ user_id: @opts.user.id
+ text: @refs.text.value
+ .then (message) ~>
+ @clear!
+ .catch (err) ~>
+ console.error err
+ .then ~>
+ @sending = false
+ @update!
+
+ @clear = ~>
+ @refs.text.value = ''
+ @files = []
+ @update!
+ </script>
+</mk-messaging-form>
diff --git a/src/web/app/common/tags/messaging/index.tag b/src/web/app/common/tags/messaging/index.tag
new file mode 100644
index 0000000000..2950f2a88f
--- /dev/null
+++ b/src/web/app/common/tags/messaging/index.tag
@@ -0,0 +1,328 @@
+<mk-messaging>
+ <div class="search">
+ <div class="form">
+ <label for="search-input"><i class="fa fa-search"></i></label>
+ <input ref="searchInput" type="search" oninput={ search } placeholder="ユーザーを探す"/>
+ </div>
+ <div class="result">
+ <ol class="users" if={ searchResult.length > 0 }>
+ <li each={ user in searchResult }>
+ <a onclick={ user._click }>
+ <img class="avatar" src={ user.avatar_url + '?thumbnail&size=32' } alt=""/>
+ <span class="name">{ user.name }</span>
+ <span class="username">@{ user.username }</span>
+ </a>
+ </li>
+ </ol>
+ </div>
+ </div>
+ <div class="history" if={ history.length > 0 }>
+ <virtual each={ history }>
+ <a class="user" data-is-me={ is_me } data-is-read={ is_read } onclick={ _click }>
+ <div>
+ <img class="avatar" src={ (is_me ? recipient.avatar_url : user.avatar_url) + '?thumbnail&size=64' } alt=""/>
+ <header>
+ <span class="name">{ is_me ? recipient.name : user.name }</span>
+ <span class="username">{ '@' + (is_me ? recipient.username : user.username ) }</span>
+ <mk-time time={ created_at }></mk-time>
+ </header>
+ <div class="body">
+ <p class="text"><span class="me" if={ is_me }>あなた:</span>{ text }</p>
+ </div>
+ </div>
+ </a>
+ </virtual>
+ </div>
+ <p class="no-history" if={ history.length == 0 }>履歴はありません。<br/>ユーザーを検索して、いつでもメッセージを送受信できます。</p>
+ <style type="stylus">
+ :scope
+ display block
+
+ > .search
+ display block
+ position -webkit-sticky
+ position sticky
+ top 0
+ left 0
+ z-index 1
+ width 100%
+ background #fff
+ box-shadow 0 0px 2px rgba(0, 0, 0, 0.2)
+
+ > .form
+ padding 8px
+ background #f7f7f7
+
+ > label
+ display block
+ position absolute
+ top 0
+ left 8px
+ z-index 1
+ height 100%
+ width 38px
+ pointer-events none
+
+ > i
+ display block
+ position absolute
+ top 0
+ right 0
+ bottom 0
+ left 0
+ width 1em
+ height 1em
+ margin auto
+ color #555
+
+ > input
+ margin 0
+ padding 0 12px 0 38px
+ width 100%
+ font-size 1em
+ line-height 38px
+ color #000
+ outline none
+ border solid 1px #eee
+ border-radius 5px
+ box-shadow none
+ transition color 0.5s ease, border 0.5s ease
+
+ &:hover
+ border solid 1px #ddd
+ transition border 0.2s ease
+
+ &:focus
+ color darken($theme-color, 20%)
+ border solid 1px $theme-color
+ transition color 0, border 0
+
+ > .result
+ display block
+ top 0
+ left 0
+ z-index 2
+ width 100%
+ margin 0
+ padding 0
+ background #fff
+
+ > .users
+ margin 0
+ padding 0
+ list-style none
+
+ > li
+ > a
+ display inline-block
+ z-index 1
+ width 100%
+ padding 8px 32px
+ vertical-align top
+ white-space nowrap
+ overflow hidden
+ color rgba(0, 0, 0, 0.8)
+ text-decoration none
+ transition none
+
+ &:hover
+ color #fff
+ background $theme-color
+
+ .name
+ color #fff
+
+ .username
+ color #fff
+
+ &:active
+ color #fff
+ background darken($theme-color, 10%)
+
+ .name
+ color #fff
+
+ .username
+ color #fff
+
+ .avatar
+ vertical-align middle
+ min-width 32px
+ min-height 32px
+ max-width 32px
+ max-height 32px
+ margin 0 8px 0 0
+ border-radius 6px
+
+ .name
+ margin 0 8px 0 0
+ /*font-weight bold*/
+ font-weight normal
+ color rgba(0, 0, 0, 0.8)
+
+ .username
+ font-weight normal
+ color rgba(0, 0, 0, 0.3)
+
+
+ > .history
+
+ > a
+ display block
+ padding 20px 30px
+ text-decoration none
+ background #fff
+ border-bottom solid 1px #eee
+
+ *
+ pointer-events none
+ user-select none
+
+ &:hover
+ background #fafafa
+
+ > .avatar
+ filter saturate(200%)
+
+ &:active
+ background #eee
+
+ &[data-is-read]
+ &[data-is-me]
+ opacity 0.8
+
+ &:not([data-is-me]):not([data-is-read])
+ background-image url("/_/resources/desktop/unread.svg")
+ background-repeat no-repeat
+ background-position 0 center
+
+ &:after
+ content ""
+ display block
+ clear both
+
+ > div
+ max-width 500px
+ margin 0 auto
+
+ > header
+ margin-bottom 2px
+ white-space nowrap
+ overflow hidden
+
+ > .name
+ text-align left
+ display inline
+ margin 0
+ padding 0
+ font-size 1em
+ color rgba(0, 0, 0, 0.9)
+ font-weight bold
+ transition all 0.1s ease
+
+ > .username
+ text-align left
+ margin 0 0 0 8px
+ color rgba(0, 0, 0, 0.5)
+
+ > mk-time
+ position absolute
+ top 0
+ right 0
+ display inline
+ color rgba(0, 0, 0, 0.5)
+ font-size 80%
+
+ > .avatar
+ float left
+ width 54px
+ height 54px
+ margin 0 16px 0 0
+ border-radius 8px
+ transition all 0.1s ease
+
+ > .body
+
+ > .text
+ display block
+ margin 0 0 0 0
+ padding 0
+ overflow hidden
+ overflow-wrap break-word
+ font-size 1.1em
+ color rgba(0, 0, 0, 0.8)
+
+ .me
+ color rgba(0, 0, 0, 0.4)
+
+ > .image
+ display block
+ max-width 100%
+ max-height 512px
+
+ > .no-history
+ margin 0
+ padding 2em 1em
+ text-align center
+ color #999
+ font-weight 500
+
+ // TODO: element base media query
+ @media (max-width 400px)
+ > .search
+ > .result
+ > .users
+ > li
+ > a
+ padding 8px 16px
+
+ > .history
+ > a
+ padding 16px
+ font-size 14px
+
+ > div
+ > .avatar
+ margin 0 12px 0 0
+
+ </style>
+ <script>
+ @mixin \i
+ @mixin \api
+
+ @search-result = []
+
+ @on \mount ~>
+ @api \messaging/history
+ .then (history) ~>
+ @is-loading = false
+ history.for-each (message) ~>
+ message.is_me = message.user_id == @I.id
+ message._click = ~>
+ if message.is_me
+ @trigger \navigate-user message.recipient
+ else
+ @trigger \navigate-user message.user
+ @history = history
+ @update!
+ .catch (err) ~>
+ console.error err
+
+ @search = ~>
+ q = @refs.search-input.value
+ if q == ''
+ @search-result = []
+ else
+ @api \users/search do
+ query: q
+ .then (users) ~>
+ users.for-each (user) ~>
+ user._click = ~>
+ @trigger \navigate-user user
+ @search-result = []
+ @search-result = users
+ @update!
+ .catch (err) ~>
+ console.error err
+ </script>
+</mk-messaging>
diff --git a/src/web/app/common/tags/messaging/message.tag b/src/web/app/common/tags/messaging/message.tag
new file mode 100644
index 0000000000..375a2fefcc
--- /dev/null
+++ b/src/web/app/common/tags/messaging/message.tag
@@ -0,0 +1,230 @@
+<mk-messaging-message data-is-me={ message.is_me }><a class="avatar-anchor" href={ CONFIG.url + '/' + message.user.username } title={ message.user.username } target="_blank"><img class="avatar" src={ message.user.avatar_url + '?thumbnail&size=64' } alt=""/></a>
+ <div class="content-container">
+ <div class="balloon">
+ <p class="read" if={ message.is_me && message.is_read }>既読</p>
+ <button class="delete-button" if={ message.is_me } title="メッセージを削除"><img src="/_/resources/desktop/messaging/delete.png" alt="Delete"/></button>
+ <div class="content" if={ !message.is_deleted }>
+ <div ref="text"></div>
+ <div class="image" if={ message.file }><img src={ message.file.url } alt="image" title={ message.file.name }/></div>
+ </div>
+ <div class="content" if={ message.is_deleted }>
+ <p class="is-deleted">このメッセージは削除されました</p>
+ </div>
+ </div>
+ <footer>
+ <mk-time time={ message.created_at }></mk-time><i class="fa fa-pencil is-edited" if={ message.is_edited }></i>
+ </footer>
+ </div>
+ <style type="stylus">
+ :scope
+ $me-balloon-color = #23A7B6
+
+ display block
+ padding 10px 12px 10px 12px
+ background-color transparent
+
+ &:after
+ content ""
+ display block
+ clear both
+
+ > .avatar-anchor
+ display block
+
+ > .avatar
+ display block
+ min-width 54px
+ min-height 54px
+ max-width 54px
+ max-height 54px
+ margin 0
+ border-radius 8px
+ transition all 0.1s ease
+
+ > .content-container
+ display block
+ margin 0 12px
+ padding 0
+ max-width calc(100% - 78px)
+
+ > .balloon
+ display block
+ float inherit
+ margin 0
+ padding 0
+ max-width 100%
+ min-height 38px
+ border-radius 16px
+
+ &:before
+ content ""
+ pointer-events none
+ display block
+ position absolute
+ top 12px
+
+ &:hover
+ > .delete-button
+ display block
+
+ > .delete-button
+ display none
+ position absolute
+ z-index 1
+ top -4px
+ right -4px
+ margin 0
+ padding 0
+ cursor pointer
+ outline none
+ border none
+ border-radius 0
+ box-shadow none
+ background transparent
+
+ > img
+ vertical-align bottom
+ width 16px
+ height 16px
+ cursor pointer
+
+ > .read
+ user-select none
+ display block
+ position absolute
+ z-index 1
+ bottom -4px
+ left -12px
+ margin 0
+ color rgba(0, 0, 0, 0.5)
+ font-size 11px
+
+ > .content
+
+ > .is-deleted
+ display block
+ margin 0
+ padding 0
+ overflow hidden
+ overflow-wrap break-word
+ font-size 1em
+ color rgba(0, 0, 0, 0.5)
+
+ > [ref='text']
+ display block
+ margin 0
+ padding 8px 16px
+ overflow hidden
+ overflow-wrap break-word
+ font-size 1em
+ color rgba(0, 0, 0, 0.8)
+
+ &, *
+ user-select text
+ cursor auto
+
+ & + .file
+ &.image
+ > img
+ border-radius 0 0 16px 16px
+
+ > .file
+ &.image
+ > img
+ display block
+ max-width 100%
+ max-height 512px
+ border-radius 16px
+
+ > footer
+ display block
+ clear both
+ margin 0
+ padding 2px
+ font-size 10px
+ color rgba(0, 0, 0, 0.4)
+
+ > .is-edited
+ margin-left 4px
+
+ &:not([data-is-me='true'])
+ > .avatar-anchor
+ float left
+
+ > .content-container
+ float left
+
+ > .balloon
+ background #eee
+
+ &:before
+ left -14px
+ border-top solid 8px transparent
+ border-right solid 8px #eee
+ border-bottom solid 8px transparent
+ border-left solid 8px transparent
+
+ > footer
+ text-align left
+
+ &[data-is-me='true']
+ > .avatar-anchor
+ float right
+
+ > .content-container
+ float right
+
+ > .balloon
+ background $me-balloon-color
+
+ &:before
+ right -14px
+ left auto
+ border-top solid 8px transparent
+ border-right solid 8px transparent
+ border-bottom solid 8px transparent
+ border-left solid 8px $me-balloon-color
+
+ > .content
+
+ > p.is-deleted
+ color rgba(255, 255, 255, 0.5)
+
+ > [ref='text']
+ &, *
+ color #fff !important
+
+ > footer
+ text-align right
+
+ &[data-is-deleted='true']
+ > .content-container
+ opacity 0.5
+
+ </style>
+ <script>
+ @mixin \i
+ @mixin \text
+
+ @message = @opts.message
+ @message.is_me = @message.user.id == @I.id
+
+ @on \mount ~>
+ if @message.text?
+ tokens = @analyze @message.text
+
+ @refs.text.innerHTML = @compile tokens
+
+ @refs.text.children.for-each (e) ~>
+ if e.tag-name == \MK-URL
+ riot.mount e
+
+ # URLをプレビュー
+ tokens
+ .filter (t) -> t.type == \link
+ .map (t) ~>
+ @preview = @refs.text.append-child document.create-element \mk-url-preview
+ riot.mount @preview, do
+ url: t.content
+ </script>
+</mk-messaging-message>
diff --git a/src/web/app/common/tags/messaging/room.tag b/src/web/app/common/tags/messaging/room.tag
new file mode 100644
index 0000000000..3acfc14b0e
--- /dev/null
+++ b/src/web/app/common/tags/messaging/room.tag
@@ -0,0 +1,224 @@
+<mk-messaging-room>
+ <div class="stream" ref="stream">
+ <p class="initializing" if={ init }><i class="fa fa-spinner fa-spin"></i>読み込み中</p>
+ <p class="empty" if={ !init && messages.length == 0 }><i class="fa fa-info-circle"></i>このユーザーとまだ会話したことがありません</p>
+ <virtual each={ message, i in messages }>
+ <mk-messaging-message message={ message }></mk-messaging-message>
+ <p class="date" if={ i != messages.length - 1 && message._date != messages[i + 1]._date }><span>{ messages[i + 1]._datetext }</span></p>
+ </virtual>
+ </div>
+ <div class="typings"></div>
+ <footer>
+ <div ref="notifications"></div>
+ <div class="grippie" title="ドラッグしてフォームの広さを調整"></div>
+ <mk-messaging-form user={ user }></mk-messaging-form>
+ </footer>
+ <style type="stylus">
+ :scope
+ display block
+
+ > .stream
+ max-width 600px
+ margin 0 auto
+
+ > .empty
+ width 100%
+ margin 0
+ padding 16px 8px 8px 8px
+ text-align center
+ font-size 0.8em
+ color rgba(0, 0, 0, 0.4)
+
+ i
+ margin-right 4px
+
+ > .no-history
+ display block
+ margin 0
+ padding 16px
+ text-align center
+ font-size 0.8em
+ color rgba(0, 0, 0, 0.4)
+
+ i
+ margin-right 4px
+
+ > .message
+ // something
+
+ > .date
+ display block
+ margin 8px 0
+ text-align center
+
+ &:before
+ content ''
+ display block
+ position absolute
+ height 1px
+ width 90%
+ top 16px
+ left 0
+ right 0
+ margin 0 auto
+ background rgba(0, 0, 0, 0.1)
+
+ > span
+ display inline-block
+ margin 0
+ padding 0 16px
+ //font-weight bold
+ line-height 32px
+ color rgba(0, 0, 0, 0.3)
+ background #fff
+
+ > footer
+ position -webkit-sticky
+ position sticky
+ z-index 2
+ bottom 0
+ width 100%
+ max-width 600px
+ margin 0 auto
+ padding 0
+ background rgba(255, 255, 255, 0.95)
+ background-clip content-box
+
+ > [ref='notifications']
+ position absolute
+ top -48px
+ width 100%
+ padding 8px 0
+ text-align center
+
+ > p
+ display inline-block
+ margin 0
+ padding 0 12px 0 28px
+ cursor pointer
+ line-height 32px
+ font-size 12px
+ color $theme-color-foreground
+ background $theme-color
+ border-radius 16px
+ transition opacity 1s ease
+
+ > i
+ position absolute
+ top 0
+ left 10px
+ line-height 32px
+ font-size 16px
+
+ > .grippie
+ height 10px
+ margin-top -10px
+ background transparent
+ cursor ns-resize
+
+ &:hover
+ //background rgba(0, 0, 0, 0.1)
+
+ &:active
+ //background rgba(0, 0, 0, 0.2)
+
+ </style>
+ <script>
+ @mixin \i
+ @mixin \api
+ @mixin \messaging-stream
+
+ @user = @opts.user
+ @init = true
+ @sending = false
+ @messages = []
+
+ @connection = new @MessagingStreamConnection @I, @user.id
+
+ @on \mount ~>
+ @connection.event.on \message @on-message
+ @connection.event.on \read @on-read
+
+ document.add-event-listener \visibilitychange @on-visibilitychange
+
+ @api \messaging/messages do
+ user_id: @user.id
+ .then (messages) ~>
+ @init = false
+ @messages = messages.reverse!
+ @update!
+ @scroll-to-bottom!
+ .catch (err) ~>
+ console.error err
+
+ @on \unmount ~>
+ @connection.event.off \message @on-message
+ @connection.event.off \read @on-read
+ @connection.close!
+
+ document.remove-event-listener \visibilitychange @on-visibilitychange
+
+ @on \update ~>
+ @messages.for-each (message) ~>
+ date = (new Date message.created_at).get-date!
+ month = (new Date message.created_at).get-month! + 1
+ message._date = date
+ message._datetext = month + '月 ' + date + '日'
+
+ @on-message = (message) ~>
+ is-bottom = @is-bottom!
+
+ @messages.push message
+ if message.user_id != @I.id and not document.hidden
+ @connection.socket.send JSON.stringify do
+ type: \read
+ id: message.id
+ @update!
+
+ if is-bottom
+ # Scroll to bottom
+ @scroll-to-bottom!
+ else if message.user_id != @I.id
+ # Notify
+ @notify '新しいメッセージがあります'
+
+ @on-read = (ids) ~>
+ if not Array.isArray ids then ids = [ids]
+ ids.for-each (id) ~>
+ if (@messages.some (x) ~> x.id == id)
+ exist = (@messages.map (x) -> x.id).index-of id
+ @messages[exist].is_read = true
+ @update!
+
+ @is-bottom = ~>
+ current = @refs.stream.scroll-top + @refs.stream.offset-height
+ max = @refs.stream.scroll-height
+ current > (max - 32)
+
+ @scroll-to-bottom = ~>
+ @refs.stream.scroll-top = @refs.stream.scroll-height
+
+ @notify = (message) ~>
+ n = document.create-element \p
+ n.inner-HTML = '<i class="fa fa-arrow-circle-down"></i>' + message
+ n.onclick = ~>
+ @scroll-to-bottom!
+ n.parent-node.remove-child n
+ @refs.notifications.append-child n
+
+ set-timeout ~>
+ n.style.opacity = 0
+ set-timeout ~>
+ n.parent-node.remove-child n
+ , 1000ms
+ , 4000ms
+
+ @on-visibilitychange = ~>
+ if document.hidden then return
+ @messages.for-each (message) ~>
+ if message.user_id != @I.id and not message.is_read
+ @connection.socket.send JSON.stringify do
+ type: \read
+ id: message.id
+ </script>
+</mk-messaging-room>