<!DOCTYPE html> <html lang="en" > <head> <meta charset="utf-8" /> <meta http-equiv="x-ua-compatible" content="ie=edge" /> <meta name="description" content="Matrix Construct" /> <link rel="icon" type="image/png" href="favicon.ico" /> <link rel="stylesheet" href="font-awesome.min.css" /> <link rel="stylesheet" href="flat-ui.min.css" /> <link rel="stylesheet" href="construct.css" /> <!-- for erry --> <title> Matrix Construct </title> </head> <body ng-app="ircd" ng-class="{ loaded: true }" > <!-- -------------------------------------------------------------------------- Matrix Construct Client The document is specified as a set of Angular templates in <script> tags. These templates are composed into the document by including other templates in a tree. The root of the tree is the #charybdis <div> at the end of the <body>. The first template specified ('ircd') is the child content of that root <div>. 'ircd' and 'charybdis' and 'client' are various namespace prefixes we reserve for now. Our HTML is styled specifically for working with Angular. The style is simple, easy to type and mostly consistent without many special cases. Tags without attributes are just like classic HTML: <tag> content </tag> Tags with attributes use newlines to give them more space, clarity and for easy addition and modification of attributes; also helps the revision trackers (i.e git-blame): <tag ng-foo="foo" > --------------------------------------------------------------------------- --> <script id="ircd" type="text/ng-template" > <div id="charybdis_rooms" class="rooms pane" ng-show="mc.show['#charybdis_rooms']" ng-include="'ircd_rooms'" > </div> <div id="charybdis_menu" class="menu row wrap" ng-controller="menu as menu" ng-show="mc.show['#charybdis_menu']" ng-include="'ircd_main_menu'" > </div> <div id="charybdis_login" class="login_ pane" ng-show="mc.show['#charybdis_login']" ng-include="'charybdis_login'" ircd-catch > </div> </script> <!-- -------------------------------------------------------------------------- Main Menu --------------------------------------------------------------------------- --> <script id="ircd_main_menu" type="text/ng-template" > <button class="item column wrap" ng-repeat="(name, item) in mc.main.menu" ng-hide="item.hide == true" ang-click="menu.toggle(mc.main.menu, name, $event);" ng-class=" { order: item.order, sticky: item.sticky, selected: menu.selected(mc.main.menu, name, item) }" > <i class="fa icon {{ item.icon }}" aria-hidden="true" > </i> <h2 class="name" ng-bind="name" > </h2> </button> </script> <script id="ircd_menu_item" type="text/ng-template" > <button class="item" ng-repeat="item in items" ng-class="item.classes" > <i class="fa icon" ng-class="item.icon" aria-hidden="true" > </i> <h1 class="name" > {{ item.name }} </h1> </button> </script> <script id="ircd_menu" type="text/ng-template" > <form class="menu" ng-include="'ircd_menu_item'" > </form> </script> <!-- -------------------------------------------------------------------------- Main Login --------------------------------------------------------------------------- --> <script id="charybdis_login" type="text/ng-template" > <form id="charybdis_login_form" > <h3> <!-- <span class="matrix"><b>Z</b>emos <b>I</b>nter<b>A</b>ctive</span> --> <span class="matrix"><b>M</b>atrix</span> <span class="construct"><b>C</b>onstruct</span> </h3> <input name="username" type="text" ng-model="mc.local.user_id" /> <input name="password" type="password" ng-model="mc.local.wasspord" /> <div class="submit" > <button name="login_" type="submit" class="submit button" ng-click="mc.run()" > LOGIN </button> <button name="register" type="submit" class="submit button" ng-class=" { disabled: mc.auth['m.register.user'].disabled, }" ng-click="mc.auth['m.register.user']() && mc.run()" > REGISTER </button> </div> </form> </script> <!-- -------------------------------------------------------------------------- Rooms --------------------------------------------------------------------------- --> <script id="ircd_rooms" type="text/ng-template" > <div class="room no-animate" ng-repeat="room in mc.rooms.current.list" ng-controller="room as this" ng-include="'ircd_room'" > </div> </script> <!-- -------------------------------------------------------------------------- Room --------------------------------------------------------------------------- --> <script id="ircd_room" type="text/ng-template" > <label for="{{room.id}}" > </label> <div class="event control bar" ng-show="room.control.show_event_control" ng-include="'ircd_room_control_events'" ircd-catch > </div> <div class="detail control bar" ng-show="room.control.show_detail" ng-include="'ircd_room_control_detail'" ircd-catch > </div> <div class="status frieze bar" ng-if="room.content['mc.room.config']['show'].frieze !== false" ng-include="'ircd_room_control_frieze'" > </div> <div class="main" ng-include="'ircd_room_main'" > </div> </script> <script id="ircd_room_main" type="text/ng-template" > <div class="content" ng-include="'ircd_room_content'" ircd-catch > </div> <div class="members" ng-if="room.content['mc.room.config']['show'].members" ng-controller="mc.room.membership.controller as members" ng-include="'ircd_room_members'" > </div> <form class="event player menu column nowrap" ng-show="room.control.show_event_control" ng-include="'ircd_room_events_player'" > </form> <div class="explore" ng-show="room.control.show_explore" ng-include="'ircd_room_explore'" > </div> </script> <script id="ircd_room_content" type="text/ng-template" > <form class="search" ng-if="room.control.show_search" ng-include="'ircd_room_search'" > </form> <div class="filler grow" > </div> <div class="events" ng-controller="room.events as events" ang-scroll="room.scroll.on($event)" ng-include="'ircd_room_events'" > </div> <form class="input" ng-if="room.content['mc.room.config']['show'].input !== false" ng-show="room.control.show_main_input && room.control.mode == 'LIVE'" ng-include="'ircd_room_input'" > </form> </script> <!-- Room Members --> <script id="ircd_room_members" type="text/ng-template" > <div class="menu" ng-include="'ircd_room_members_menu'" > </div> <div class="list" ang-scroll="members.scroll($event)" ng-include="'ircd_room_members_list'" ircd-catch > </div> <form class="search" ng-include="'ircd_room_members_search'" > </form> </script> <script id="ircd_room_members_menu" type="text/ng-template" > <button class="item" ng-repeat="(name, item) in mc.room.membership.menu" ng-show="item.show === true" ng-click= " room.content['mc.room.config']['show']._members = members.filter != name; members.filter = name; members.info = undefined; members.list = room.membership.sorted(name); item.click(room, $event, members); " ng-class=" { selected: members.filter == name }"> <i class="fa icon" ng-class="item.icon" aria-hidden="true" > </i> <h5 class="name" > {{ item.name !== undefined? item.name : name.toUpperCase() }} </h5> </button> </script> <script id="ircd_room_members_search" type="text/ng-template" > <label class="h6" ng-hide="members.filter == 'invite'" > SEARCH MEMBERS </label> <label class="h6" ng-show="members.filter == 'invite'" > INVITE MEMBER </label> <input name="pattern" type="text" autocomplete="off" /> </script> <script id="ircd_room_members_list" type="text/ng-template" > <div class="loading" ng-show="members.loading === true" > <i class="fa icon fa-spinner" aria-hidden="true" > </i> </div> <div class="member" ng-repeat="member in members.list | limitTo:members.limit():members.begin" ng-init="mxid = member.state_key" ng-show="!members.info || members.info == mxid" ng-include="'ircd_room_members_member'" ng-class=" { me: mxid == mc.my.mxid, grow: members.info == mxid, active: mc.users[mxid].currently_active === true, inactive: mc.users[mxid].currently_active === false, }"> </div> </script> <script id="ircd_room_members_invite" type="text/ng-template" > <i class="icon fa fa-user-o" aria-hidden="true" > </i> <form ng-submit="room.invite($event)" > <input name="invite" type="text" autocomplete="ja" onfocus="this.value=''" onfocusout="this.value=''" /> <h6> INVITE </h6> </form> </script> <script id="ircd_room_members_member" type="text/ng-template" > <div class="head" ng-click="togswap(members, 'info', mxid); $event.stopPropagation();" ng-include="'ircd_room_members_member_head'" ng-class=" { selected: members.info == mxid, }"> </div> <div class="info" ng-if="members.info == mxid" ng-include="'ircd_room_members_member_info'" > </div> </script> <script id="ircd_room_members_member_head" type="text/ng-template" > <i class="icon fa" aria-hidden="true" ng-class=" { 'fa-user-o': room.typing.active[mxid] !== true, 'fa-keyboard-o': room.typing.active[mxid] === true, }"> </i> <h3 class="name" > {{ mc.m.sid(mxid) }} </h3> <h5 class="idle" ng-if="mc.users[mxid].last_active_ago" > {{ mc.date.describe.elapsed(mc.users[mxid].last_active_ago, true); }} </h5> <div class="grow" > </div> <h6 class="domain" > {{ mc.m.domid(mxid) }} </h6> </script> <script id="ircd_room_members_member_info" type="text/ng-template" > <div class="mxid" > <p> {{ mxid }} </p> </div> <div class="data" ng-include="'ircd_room_members_member_info_data'" > </div> <form class="menu" ng-include="'ircd_room_members_member_info_menu'" > </form> <div class="event" ng-click="room.seek(member.event_id); $event.stopPropagation();" > <p> {{ member.event_id }} </p> </div> </script> <script id="ircd_room_members_member_info_data" type="text/ng-template" > <div class="attrs" > <div class="attr" ng-repeat="(name, attr) in mc.room.membership.controller.attributes" ng-if="!attr.show || attr.show(room, member) !== false" > <h3> {{ attr.name? attr.name(room, member) : name; }} </h3> <p>{{attr.value(room, member)}}</p> </div> </div> <div class="avatar" > <img ng-if="member.content.avatar_url" ng-src="{{mc.m.xc(member.content.avatar_url)}}" onerror="this.style.display='none'" target="_blank" /> </div> </script> <script id="ircd_room_members_member_info_menu" type="text/ng-template" > <button class="item" ng-repeat="(name, item) in mc.room.membership.member_info_menu" ang-click="item.click($event, room, mxid)" > <i class="fa icon {{ item.icon }}" aria-hidden="true" > </i> <h4 class="name" > {{ name }} </h4> </button> </script> <script id="ircd_room_explore" type="text/ng-template" > <div class="control bar" > <i class="refresh icon fa fa-refresh" ng-click="$event.stopPropagation(); room.refresh_explore($event);" aria-hidden="true" > </i> </div> <div class="content" > </div> </script> <script id="ircd_room_input_files" type="text/ng-template" > <div class="file" ng-repeat="(name, file) in room.control.files" ng-class=" { start: file.ajax === undefined && file.reader.readyState == file.reader.EMPTY, loading: file.ajax === undefined && file.reader.readyState == file.reader.LOADING, loaded: file.ajax === undefined && file.reader.readyState == file.reader.DONE, uploading: file.ajax !== undefined && file.progress.loaded != file.progress.total, uploaded: file.ajax !== undefined && file.progress.loaded == file.progress.total, failed: file.progress.type == 'error', }"> <div class="progress" ng-if="file.progress.loaded != file.progress.total" style="width: {{(file.progress.loaded / file.progress.total) * 100}}%;" > </div> <div class="error" ng-if="file.progress.type == 'error'" ng-init="error = new mc.error(file.error)" ng-include="'ircd_error'" > </div> <button class="remove" ng-click="mc.room.attach.cancel.call(room, $event, file); $event.stopPropagation();" > <i class="fa icon fa-close" aria-hidden="true" > </i> </button> <img ng-if="file.opts.content.url !== undefined" ng-src="{{mc.m.xc(file.opts.content.url)}}" > </img> <h5 class="name" ng-if="file.opts.content.url === undefined" > {{ file.name }} </h5> <h5 class="url" ng-if="file.opts.content.url !== undefined" > {{ file.opts.content.url }} </h5> <div class="status" > <p class="bytes loaded" ng-if="file.progress.loaded != file.progress.total" > {{ mc.space.describe.bytes(file.progress.loaded) }} of </p> <p class="bytes total" > {{ mc.space.describe.bytes(file.progress.total) }} </p> <p class="state" ng-if="file.reader.readyState == file.reader.LOADING" > READING </p> <p class="state" ng-if="file.ajax === undefined && file.reader.readyState == file.reader.DONE" > READY </p> <p class="state" ng-if="file.ajax !== undefined && file.progress.type == 'loadend'" > UPLOADED </p> </div> <div class="text" ng-if="file.opts.content.url !== undefined" > <h6 class="label" > TEXT </h6> <input name="caption" class="caption" ng-model="file.opts.content.body" /> </div> <button class="post" ng-if="file.opts.content.url !== undefined" ang-click="mc.room.send.message.image.call(room, file.opts.content.url, file.opts.content.body); $event.stopPropagation()" > <i class="fa icon fa-reply" aria-hidden="true" > </i> </button> </div> <div class="summary" ng-if="length(room.control.files) > 1" ng-if="false" > </div> </script> <script id="ircd_room_input_message" type="text/ng-template" > <div class="attach" > <i class="reply icon fa fa-paperclip" aria-hidden="true" > </i> <input name="file" type="file" class="file" multiple onchange= " let scope = angular.element(this).scope(); scope.room.attach(event); scope.$apply(); " /> </div> <textarea name="message" class="message" autocomplete="off" rows="1" style="white-space: normal;" ng-model="room.control.input" ng-change="room.input.change($event)" ng-keydown="room.input.keydown($event)" ng-blur="room.input.blur($event)" > </textarea> <button name="submit" type="submit" class="submit" ng-hide="empty(room.control.input)" ng-click="room.input.submit($event)" ng-class=" { eval: room.control.evalmode || room.opts.local, empty: empty(room.control.input), }"> <i class="reply icon fa fa-reply" aria-hidden="true" > </i> <span ng-if="false" ng-show="!room.control.evalmode && !room.opts.local" > SEND </span> <span ng-show="room.control.evalmode || room.opts.local" > EVAL </span> </button> </script> <script id="ircd_room_input" type="text/ng-template" > <div class="files" ng-include="'ircd_room_input_files'" > </div> <div class="message" ng-include="'ircd_room_input_message'" > </div> </script> <!-- Room Search --> <script id="ircd_room_search" type="text/ng-template" > <div class="row nowrap" > <div class="column nowrap grow" > <input name="query" class="query" autocomplete="off" style="white-space: normal;" ng-model="room.control.search_query" ng-change="room.search($event);" ng-model-options="{debounce: 250}" /> <h6 class="label" > SEARCH {{ room.content['m.room.name'][''].name }} </h6> </div> <div class="menu row nowrap" ng-controller="menu as menu" > <button class="item" ng-repeat="(name, item) in room.search_menu" ng-click="menu.toggle(room.search_menu, name, item, event);" ng-class=" { selected: menu.selected(room.search_menu, name, item), }"> <i class="fa icon {{item.icon}}" aria-hidden="true" > </i> <p class="name" > {{ name }} </p> </button> </div> </div> </script> <script id="ircd_room_events_player" type="text/ng-template" > <button ng-repeat="(name, item) in room.timeline_player" ng-class="{ selected: room.control.mode == name }" ng-click="item.click($event, room);" class="item" > <i class="fa icon" ng-class="item.icon" aria-hidden="true" > </i> <h3 class="name" > {{ name }} </h3> </button> </script> <!-- Room Control --> <script id="ircd_room_control_events_state" type="text/ng-template" > <h3> STATE SLOT </h3> <div class="slots column nowrap" > <div class="slot row nowrap" ng-repeat="(name, event) in room.state" ng-class=" { active: event.event_id !== undefined, empty: event.event_id === undefined, disabled: event.type === undefined && event.content === undefined, }"> <h4> {{ name.replace('m.room.','').replace('_', ' ').toUpperCase(); }} </h4> <input class="id" type="text" ng-value="event.event_id" /> <p class="sender" > {{event.sender}} </p> </div> </div> </script> <script id="ircd_room_control_events" type="text/ng-template" > <div class="row nowrap" > <div class="state column nowrap" ng-include="'ircd_room_control_events_state'" > </div> <div class="capstan column nowrap" > <div class="head row nowrap" > <div class="column nowrap" > <h3> EVENT HORIZON </h3> <form> <div ng-repeat="(key, val) in room.timeline.horizon_event();" ng-if="_typeof(val) != 'object'" > <h5> {{ key }} </h5> <input type="text" ng-value="val" /> </div> </form> </div> <div class="column nowrap" > <h3> TIMELINE </h3> <form> <div ng-repeat="(key, val) in room.timeline_stats()" > <h5> {{ key }} </h5> <input type="text" ng-value="val" /> </div> </form> </div> <div class="column nowrap" > <h3> CURRENT EVENT </h3> <form> <div ng-repeat="(key, val) in room.current_event()" ng-if="_typeof(val) != 'object'" > <h5> {{ key }} </h5> <input type="text" ng-value="val" /> </div> </form> </div> </div> <div class="viewport column nowrap" > <h3> VIEWPORT </h3> <form> <h4> DIVISION </h4> <div ng-repeat="(key, val) in room.scroll.pct()" > <h5> {{ key }} </h5> <input type="text" value="{{parseInt(val * 100)}}%" /> </div> </form> <form> <h4> LAST EVENT </h4> <div ng-repeat="(key, val) in mc.get_rect(room.items().children().last())" > <h5> {{ key }} </h5> <input type="text" ng-value="val" /> </div> </form> <form> <h4> SCROLL AREA </h4> <div ng-repeat="(key, val) in mc.get_rect(room.items())" > <h5> {{ key }} </h5> <input type="text" ng-value="val" /> </div> </form> </div> </div> </div> <div class="row" > <div class="unknown" ng-if="false" > <div class="unknown" > </div> </div> </div> </script> <script id="ircd_room_control_state_history_visibility" type="text/ng-template" > <h3> HISTORY VISIBILITY </h3> <form class="menu" > <button class="item" ng-repeat="(name, item) in room.detail_scrollback" ng-click="room.timeline.issue( { type: 'm.room.history_visibility', content: { history_visibility: name, }, }, { element: $event.delegateTarget, });" ng-class=" { selected: room.content['m.room.history_visibility'][''].history_visibility == name, pending: room.pending['m.room.history_visibility'][''].history_visibility == name, }"> <i class="fa icon {{item.icon}}" aria-hidden="true" > </i> <h4 class="name" > {{ item.name? item.name : name.replace('_', ' ').toUpperCase() }} </h4> </button> </form> </script> <script id="ircd_room_control_state_join_rules" type="text/ng-template" > <h3> JOIN RULES </h3> <div class="menu" > <button class="item" ng-repeat="(name, item) in room.detail_join_rules" ng-click="room.timeline.issue( { type: 'm.room.join_rules', content: { join_rule: name, }, }, { element: $event.delegateTarget, });" ng-class=" { selected: room.content['m.room.join_rules'][''].join_rule == name, pending: room.pending['m.room.join_rules'][''].join_rule == name, }"> <i class="fa icon {{item.icon}}" aria-hidden="true" > </i> <h4 class="name" > {{ name.replace('_', ' ').toUpperCase() }} </h4> </button> </div> </script> <script id="ircd_room_control_state_guest_access" type="text/ng-template" > <h3> GUEST ACCESS </h3> <div class="menu row nowrap" > <button class="item" ng-repeat="(name, item) in room.detail_guest_access" ng-click="room.timeline.issue( { type: 'm.room.guest_access', content: { guest_access: name, }, }, { element: $event.delegateTarget, });" ng-class=" { selected: room.content['m.room.guest_access'][''].guest_access == name, pending: room.pending['m.room.guest_access'][''].guest_access == name, }"> <i class="fa icon" ng-class="item.icon" aria-hidden="true" > </i> <h4 class="name" > {{ name.replace('_', ' ').toUpperCase() }} </h4> </button> </div> </script> <script id="ircd_room_control_power_levels" type="text/ng-template" > <h3> PRIVILEGE LEVELS </h3> <div class="levels column nowrap" > <div class="level" ng-repeat="(name, level) in room.content['m.room.power_levels']['']" ng-if="_typeof(level) === 'number'" > <h5 class="name" > {{ name.replace('_', ' ') }} </h5> <input type="text" class="number" ng-value="level" /> </div> </div> </script> <script id="ircd_room_control_state_aliases_server_alias" type="text/ng-template" > <h3 class="hashtag" > # </h3> <input class="name" type="text" ng-value="alias" ng-model="room.pending['m.room.aliases'][server].content.aliases[$index]" ng-change="room.realias($event, server, $index);" ng-model-options="{ updateOn: 'blur', getterSetter: false }" /> <h3 class="colon" > : </h3> <input type="text" class="server" ng-value="server" > <div class="progress" > </div> </script> <script id="ircd_room_control_state_aliases" type="text/ng-template" > <div class="server" ng-repeat="(server, event) in room.state['m.room.aliases']" > <div class="alias" ng-repeat="alias in event.content.aliases track by $index" ng-include="'ircd_room_control_state_aliases_server_alias'" ng-class=" { pending: room.pending['m.room.aliases'][server] !== undefined, }"> </div> <div class="alias" ng-if="server == mc.my.server" ng-include="'ircd_room_control_state_aliases_server_alias'" ng-init= " server = mc.my.server; $index = 'next'; "> </div> </div> <div class="server" ng-show="room.state['m.room.aliases'][mc.my.server] === undefined" > <div class="alias" ng-include="'ircd_room_control_state_aliases_server_alias'" ng-init= " server = mc.my.server; $index = 'next'; "> </div> </div> </script> <script id="ircd_room_control_state_name" type="text/ng-template" > <input name="name" type="text" autocomplete="off" ng-value="room.content['m.room.name'][''].name" ng-model="room.pending['m.room.name'].content.name" ng-model-options="{ updateOn: 'blur', getterSetter: false }" ng-change="room.restate($event, 'm.room.name');" /> <h6 class="label" > ROOM NAME </h6> <div class="progress" > </div> </script> <script id="ircd_room_control_ident" type="text/ng-template" > <form class="name" ng-include="'ircd_room_control_state_name'" ng-class=" { pending: room.pending['m.room.name'] !== undefined, }"> </form> <form class="aliases" ng-include="'ircd_room_control_state_aliases'" > </form> </script> <script id="ircd_room_control_rules" type="text/ng-template" > <div class="history" ng-include="'ircd_room_control_state_history_visibility'" > </div> <div class="join_rules" ng-include="'ircd_room_control_state_join_rules'" > </div> <div class="guest_access" ng-include="'ircd_room_control_state_guest_access'" > </div> </script> <script id="ircd_room_control_topic" type="text/ng-template" > <textarea name="topic" style="white-space: normal" > {{ room.content['m.room.topic'][''].topic || 'topic' }} </textarea> </script> <script id="ircd_room_control_detail" type="text/ng-template" > <div class="power_levels" ng-include="'ircd_room_control_power_levels'" > </div> <div class="rules" ng-include="'ircd_room_control_rules'" > </div> <div class="forms" > <div class="ident" ng-include="'ircd_room_control_ident'" > </div> </div> <div class="topic" ng-include="'ircd_room_control_topic'" > </div> </script> <script id="ircd_room_control_frieze" type="text/ng-template" > <div class="name" ng-click= " room.control.show_search = !room.control.show_search; room.search($event); $event.stopPropagation(); "> <h3 class="name" > {{ room.content['m.room.name'][''].name }} </h3> <button ng-class=" { selected: room.control.show_search, }"> <i class="search icon fa fa-search" aria-hidden="true" > </i> </button> <h3 class="alias" > {{room.content['m.room.canonical_alias'][''].alias}} </h3> </div> <div class="id" ng-if="room.content['mc.room.config']['show'].control !== false" ng-dblclick="room.control.show_detail = !room.control.show_detail; $event.preventDefault();" > <button ng-click="room.control.show_detail = !room.control.show_detail" ng-class=" { selected: room.control.show_detail, }"> <i class="detail icon fa fa-wrench pointer" aria-hidden="true" > </i> </button> <h5 class="id" > {{ room.id }} </h5> </div> <div class="events" ng-if="room.content['mc.room.config']['show'].player !== false" ng-click= " room.control.show_event_control = !room.control.show_event_control; room.control.show_event_timeline = room.control.show_event_control; "> <button ng-class=" { selected: room.control.show_event_control, }"> <i class="members icon fa fa-gear pointer" aria-hidden="true" > </i> </button> <div class="timeline" > <p class="count" > {{ room.timeline.length }} </p> <h5> TL </h5> </div> <div class="state" > <p class="count" > {{ room.timeline.stats().state }} </p> <h5> ST </h5> </div> <div class="servers" > <p class="count" > {{ room.timeline.servers().length }} </p> <h5> HS </h5> </div> <div class="activity" > <i class="mode icon fa" aria-hidden="true" ng-class="room.timeline_player[room.control.mode].icon" > </i> <p class="bytes down" ng-if="mc.io.stats.recv.bytes" > {{mc.space.describe.bytes(mc.io.stats.recv.bytes)}}↓ </p> <i class="activity icon fa fa-exchange" aria-hidden="true" ng-class=" { activated: room.control.activity === true, }"> </i> <p class="bytes up" ng-if="mc.io.stats.send.bytes" > {{mc.space.describe.bytes(mc.io.stats.sent.bytes)}}↑ </p> <h5 ng-if="false" class="timestamp" > {{ room.timeline[room.timeline.length - 1].origin_server_ts }} </h5> </div> </div> <div class="members" ng-if="!room.opts.local" ng-click="toggle(room.content['mc.room.config']['show'], 'members')" > <button ng-class=" { selected: room.content['mc.room.config']['show'].members, }"> <i class="members icon fa fa-users" aria-hidden="true" > </i> </button> <div ng-repeat="(name, item) in mc.room.membership.frieze" ng-if="item.show !== false && item.count(room)" ng-click="item.click(room, $event); $event.stopPropagation();" > <p class="count" > {{ item.count(room); }} </p> <h5> {{ name }} </h5> </div> </div> <div class="explore" ng-click="room.toggle_explore($event);" > <i class="explore fa icon arrow" aria-hidden="true" ng-class=" { selected: room.control.show_explore, 'fa-angle-double-up': room.control.show_explore, 'fa-angle-double-right': !room.control.show_explore, }"> </i> <h4> EXPLORE </h4> </div> <div class="menu_toggle" ng-hide="mc.show['#charybdis_menu']" ng-include="'ircd_room_control_frieze_charybdis_menu'" > </div> </script> <script id="ircd_room_control_frieze_charybdis_menu" type="text/ng-template" > <button ng-click="mc.show['#charybdis_menu'] = !mc.show['#charybdis_menu'];" ng-class=" { selected: mc.show['#charybdis_menu'] } "> <i class="icon fa fa-bars" aria-hidden="true" > </i> </button> </script> <!-- Room Timeline --> <script id="ircd_room_events" type="text/ng-template" > <div ng-repeat="event in room.timeline" ng-if="events.can_render(event, $index)" ng-show="events.can_show(event, $index)" class="event" ng-class=" { state: mc.event.is_state(event), zoom: room.control.content.zoom == event.event_id, grouping_start: events.is_grouping_start(event, $index), grouping_end: events.is_grouping_end(event, $index), show_info: room.control.show_event_info[event.event_id] !== undefined, highlight: room.control.show_event_timeline && room.control.show_event_info[event.event_id] !== undefined, }"> <label for="{{event.event_id}}" > </label> <div class="timeline" ng-if="room.control.show_event_timeline" ng-click="togdel(room.control.show_event_info, event.event_id);" ng-include="'ircd_room_event_timeline'" > </div> <h4 class="sender" ng-if="event.sender" ng-include="'ircd_room_event_sender'" ng-dblclick= " room.control.show_event_timeline = !room.control.show_event_timeline; togdel(room.control.show_event_info, event.event_id); $event.stopPropagation(); $event.preventDefault(); "> </h4> <div class="handler" ng-if="handler_exists(event.type)" ng-include="handler_path(event.type)" ng-class=" { selected: event.$mc$selected === true, [this.dots_to_underscores(event.type)]: true, }" > </div> <div class="handler unhandled" ng-if="!handler_exists(event.type)" ng-include="'ircd_room_event_unhandled'" > </div> <h3 class="target" ng-if="this.should_show_target(event)" ng-include="'ircd_room_event_target'" > </h3> <div class="right" > <div class="timestamp" > <p> +{{ mc.date.describe.elapsed(mc.date.ago(event.origin_server_ts)); }} </p> </div> </div> </div> <div class="present event" ng-include="'ircd_room_event_present'" > </div> </script> <script id="ircd_room_event_timeline" type="text/ng-template" > <h4 class="index" ng-class=" { 'selected': room.control.show_event_info[event.event_id] === true }"> {{ $index }} </h4> <div class="info column nowrap" ng-if="room.control.show_event_info[event.event_id] === true" ng-click="$event.stopPropagation()" > <p class="id" > {{ event.event_id }} </p> <form class="explore2 event object" ng-include="'ircd_object'" ng-init="object = event;" ng-controller="explore" > </form> <form class="menu row nowrap" > <button class="item" ng-repeat="(name, item) in room.event_menu" ng-click="item.click($event, room)" ng-class=" { }"> <i class="fa icon {{item.icon}}" aria-hidden="true" > </i> <h2 class="name" > {{ name }} </h2> </button> </form> </div> </script> <script id="ircd_room_event_sender" type="text/ng-template" > <span class="open bracket" >{{ this.open_bracket(event); }}</span> <a class="avatar" ng-if="false" ng-if="room.content['m.room.member'][event.sender].avatar_url" ng-href="room.content['m.room.member'][event.sender].avatar_url" > <img ng-src="room.content['m.room.member'][event.sender].avatar_url" alt="{{ room.content['m.room.member'][event.sender].avatar_url }}" target="_blank" /> </a> <span class="name" ng-if="!this.sender_is_server(event)" ng-class=" { me: event.sender == mc.session.user_id, }" > <span ng-if="mc.users[event.sender].displayname" > {{ mc.users[event.sender].displayname }} </span> <span ng-if="!mc.users[event.sender].displayname" > {{this.sender_sid(event.sender)}} </span> </span> <span class="domain" >{{this.sender_domid(event.sender)}}</span> <span class="close bracket" >{{this.close_bracket(event)}}</span> </script> <script id="ircd_room_event_target" type="text/ng-template" > <span class="open bracket" ><</span> <span class="name" >{{ mc.m.sid(event.target) }}</span> <span class="domain" >{{ event.domid(event.target) }}</span> <span class="close bracket" >></span> </script> <script id="ircd_room_event_present" type="text/ng-template" > <div class="typing" > <i class="fa icon fa-keyboard-o" ng-hide="empty(room.typing.active)" > </i> <div class="typer" ng-repeat="(mxid, state) in room.typing.active" ng-if="state === true" > <h1> <{{mc.m.sid(mxid)}}> </h1> </div> </div> <div class="receipts" ng-if="!empty(room.current_event()['m.read'])" > <div class="receipt" ng-repeat="mxid in Object.keys(room.current_event()['m.read']) | reverse" > <h1> {{ mc.m.sid(mxid) }} </h1> <p> {{ mc.date.describe.since(room.current_event()['m.read'][mxid].ts, true) }} </p> </div> <i class="fa icon fa-eye" > </i> </div> </script> <script id="ircd_room_event_unhandled" type="text/ng-template" > <div class="changed" > <h1> {{event.type}} </h1> <h4> </h4> </div> <p class="guru" style="white-space: pre-wrap;" > {{ debug.stringify(event, 2) }} </p> </script> <!-- -------------------------------------------------------------------------- Room Timeline Event Handlers --------------------------------------------------------------------------- --> <script id="ircd_room_event__m_room_message" type="text/ng-template" > <div class="message" ng-if="handler_exists(['m.room.message', event.content.msgtype])" ng-include="handler_path(['m.room.message', event.content.msgtype])" > </div> <div class="message" ng-if="!handler_exists(['m.room.message', event.content.msgtype])" ng-include="handler_path(['m.room.message', '_unhandled'])" > </div> </script> <script id="ircd_room_event__m_room_message__m_text" type="text/ng-template" > <p class="text" >{{event.content.body}}</p> </script> <script id="ircd_room_event__m_room_message__m_notice" type="text/ng-template" > <div class="notice" >{{event.content.body}}</div> </script> <script id="ircd_room_event__m_room_message__m_emote" type="text/ng-template" > <p class="emote" >{{event.content.body}}</p> </script> <script id="ircd_room_event__m_room_message__m_image" type="text/ng-template" > <div class="image" ng-class=" { zoom: room.control.content.zoom == event.event_id, }"> <h6 class="label" > {{ event.content.body }} </h6> <img ng-click="room.dom.zoom($event, event);" ng-src="{{mc.m.xc(event.content.url)}}" alt="{{event.content.body}}" /> </div> </script> <script id="ircd_room_event__m_room_message__m_video" type="text/ng-template" > <a class="video" ng-switch-when="m.video" > <img ng-src="{{event.content.info.thumbnail_url}}" ng-if="event.content.info.thumbnail_url !== undefined" ng-show="event.content.info" alt="{{event.content.body}}" /> <iframe ng-if="false" class="ytplayer" type="text/html" width="480" height="260" ng-src="{{mc.embed(event.content.url)}}" frameborder="0" > </iframe> </a> </script> <script id="ircd_room_event__m_room_message___unhandled" type="text/ng-template" > <p class="default" > <span ng-if="empty(event.content)" > Message content is empty. </span> <span ng-if="!empty(event.content)" > <span ng-if="!empty(event.content.msgtype)" > No msgtype in content. </span> <span ng-if="!empty(event.content.msgtype)" class="unhandled" > Unhandled msgtype: {{event.content.msgtype}} </span> </span> </p> </script> <script id="ircd_room_event__m_room_member" type="text/ng-template" > <div class="changed" ng-class="event.content.membership" > <h1> MEMBER </h1> <h2> {{event.content.membership.toUpperCase()}} </h2> <h3 ng-switch on="event.content.membership" > <span class="state_key" ng-if="empty(event.content.displayname)" > {{mc.m.sid(event.state_key)}} </span> <span class="displayname state_key" ng-if="!empty(event.content.displayname)" > {{event.content.displayname}} </span> <span ng-if="!empty(event.content.displayname)" > a.k.a. </span> <span class="displayname state_key" ng-if="!empty(event.content.displayname)" > {{mc.m.sid(event.state_key)}} </span> of <span class="domain" > {{mc.m.domid(event.state_key)}} </span> <!-- <span ng-switch-when="join">joined</span> <span ng-switch-when="leave">left</span> <span ng-switch-when="invite">invited</span> <span class="default unhandled" ng-switch-default > {{event.content.membership}} </span> --> </h3> </div> </script> <script id="ircd_room_event__m_room_create" type="text/ng-template" > <div class="changed" > <h1> CREATE </h1> <h4> {{ room.id }} </h4> </div> </script> <script id="ircd_room_event__m_room_power_levels" type="text/ng-template" > <div class="changed" > <h1> POWER LEVELS </h1> <h4> </h4> </div> <div class="new levels" style="display: none" > <div class="level" ng-repeat="(name, level) in event.content" ng-if="_typeof(level) === 'number'" > <h5 class="name" > {{ name }} </h5> <p> {{ level }} </p> </div> </div> <div class="old levels" ng-if="false" > <div class="level" ng-repeat="(name, level) in event.content" ng-if="_typeof(level) === 'number'" > <h4 class="name" > {{ name }} </h4> <p> {{ level }} </p> </div> </div> </script> <script id="ircd_room_event__m_room_canonical_alias" type="text/ng-template" > <div class="changed" > <h1> CANONICAL ALIAS </h1> <h4> {{ event.content.alias }} </h4> </div> </script> <script id="ircd_room_event__m_room_join_rules" type="text/ng-template" > <div class="changed" > <h1> JOIN RULES </h1> <h4> {{ event.content.join_rule }} </h4> </div> <div class="join_rules menu" style="display: none" > <button class="item" ng-repeat="(name, item) in room.detail_join_rules" ng-class=" { selected: event.content.join_rule.toLowerCase() == name.toLowerCase(), }"> <i class="fa icon {{item.icon}}" aria-hidden="true" > </i> <h2 class="name" > {{ name }} </h2> </button> </div> </script> <script id="ircd_room_event__m_room_history_visibility" type="text/ng-template" > <div class="changed" > <h1> HISTORY VISIBILITY </h1> <h4> {{ event.content.history_visibility }} </h4> </div> </script> <script id="ircd_room_event__m_room_guest_access" type="text/ng-template" > <div class="changed" > <h1> GUEST ACCESS </h1> <h4> {{ event.content.guest_access }} </h4> </div> </script> <script id="ircd_room_event__m_room_aliases" type="text/ng-template" > <div class="changed" > <h1> ALIASES </h1> <h4> </h4> </div> <div class="aliases" > <h3 class="alias" ng-repeat="alias in event.content.aliases" > {{ alias }} </h3> </div> </script> <script id="ircd_room_event__m_room_name" type="text/ng-template" > <div class="changed" > <h1> NAME </h1> <h4 class="name center" ng-if="!room.name" > {{ event.content.name }} </h4> <h4 class="name center" ng-if="room.name" > from <b>{{ room.name }}</b> to <b>{{ event.content.name }}</b> </h4> </div> </script> <script id="ircd_room_event__m_room_topic" type="text/ng-template" > <div class="changed" > <h1 ng-click="event.$mc$selected =! event.$mc$selected" > TOPIC </h1> <h4 class="center" > {{ event.content.topic.split('\n')[0] }} </h4> </div> <div class="topic" ng-if="event.$mc$selected === true" > <p> {{ event.content.topic }} </p> </div> </script> <script id="ircd_room_event__ircd_key" type="text/ng-template" > <div class="changed" > <h1 ng-click="event.$mc$selected =! event.$mc$selected" > SERVER KEY </h1> <h4> {{event.content.server_name}} </h4> </div> <form class="explore2" ng-if="event.$mc$selected === true" ng-include="'ircd_object'" ng-init="object = event.content;" ng-controller="explore" > </form> </script> <script id="ircd_room_event__mc_room" type="text/ng-template" > <div class="changed" > <h1 ng-click="event.$mc$selected =! event.$mc$selected" > ROOM </h1> <h2> {{event.membership}} </h2> <h3> {{event.state_key}} </h3> </div> <div class="item" ng-init="room = mc.rooms[event.membership][event.state_key]" ng-include="'ircd_rooms_list_item'" > </div> </script> <script id="ircd_room_event__mc_menu" type="text/ng-template" > <div class="changed" > <h1 ng-click="event.$mc$selected =! event.$mc$selected" > MENU </h1> <h2 ng-click="event.$mc$selected =! event.$mc$selected" > {{ event.state_key }} </h2> </div> <div class="menu" ng-if="handler_exists(['mc.menu', event.state_key])" ng-include="handler_path(['mc.menu', event.state_key])" > </div> <div class="unhandled" ng-if="!handler_exists(['mc.menu', event.state_key])" ng-include="'ircd_room_event___unhandled'" > </div> </script> <script id="ircd_room_event__mc_room_config" type="text/ng-template" > <div class="changed" > <h1 ng-click="event.$mc$selected =! event.$mc$selected" > CONFIG </h1> <h2 ng-click="event.$mc$selected =! event.$mc$selected" > {{ event.state_key }} </h2> </div> <div class="config" > <button class="item" ng-repeat="(key, value) in event.content" ng-click="event.content[key] =! event.content[key]" > <i class="fa icon {{ item.icon }}" aria-hidden="true" > </i> <h2 class="name" ng-bind="key" > </h2> </div> </div> </script> <script id="ircd_room_event__mc_menu__rooms" type="text/ng-template" > <button class="item" ng-repeat="(name, item) in mc.rooms.menu" ng-hide="item.hide == true" ang-click="menu.toggle(mc.rooms.menu, name, $event);" ng-class=" { order: item.order, sticky: item.sticky, selected: menu.selected(mc.rooms.menu, name, item) }" > <i class="fa icon {{ item.icon }}" aria-hidden="true" > </i> <h2 class="name" ng-bind="name" > </h2> </button> </script> <script id="ircd_rooms_list_item" type="text/ng-template" > <div class="head" ng-click="mc.rooms.info(room.id); mc.rooms.current.add(room.id); $event.stopPropagation();" ng-include="'ircd_rooms_list_item_head'" ng-class=" { joined: mc.rooms.join[room.id] !== undefined, invited: mc.rooms.invite[room.id] !== undefined, }"> </div> <div class="info" ng-if="mc.rooms.info.model == room.id;" ng-include="'ircd_rooms_list_item_info'" > </div> </script> <script id="ircd_rooms_list_item_head" type="text/ng-template" > <div class="left focus" ng-click="mc.rooms.current.add(room.id); mc.rooms.info(room.id); $event.stopPropagation();" ng-class=" { 'grow': mc.rooms.info.model == room.id, joined: mc.rooms.join[room.id] !== undefined, invited: mc.rooms.invite[room.id] !== undefined, selected: mc.rooms.current(room.id) !== undefined, }"> <i class="left fa icon" ng-class=" { 'fa-minus': mc.rooms.info.model == room.id, 'fa-plus-square': mc.rooms.info.model != room.id, }"> </i> </div> <h3 class="right id grow" ng-if="empty(room.content['m.room.name'][''].name) && empty(room.content['m.room.canonical_alias'][''].alias)" > {{ room.id }} </h3> <h3 class="right name grow" ng-if="!empty(room.content['m.room.name'][''].name) && empty(room.content['m.room.canonical_alias'][''].alias)" > {{ room.content['m.room.name'][''].name }} </h3> <h3 class="right alias grow" ng-if="!empty(room.content['m.room.canonical_alias'][''].alias)" > {{ room.content['m.room.canonical_alias'][''].alias }} </h3> <h4 class="right highlight_count" ng-show="room.notifications.highlight_count" > {{ room.notifications.highlight_count }} </h4> <h4 class="right notification_count" ng-show="room.notifications.notification_count" > {{ room.notifications.notification_count }} </h4> <h4 class="right member_count" > {{ room.membership.count('join') }} </h4> </script> <script id="ircd_rooms_list_item_info" type="text/ng-template" > <div class="name" > <h3> {{ room.content['m.room.name'][''].name }} </h3> </div> <div class="id" > <h4> {{ room.id }} </h4> </div> <div class="stats" > <div class="joined" ng-if="mc.rooms.join[room.id] !== undefined" > <h5 class="label" > JOINED </h5> <p> {{mc.date.describe.since(mc.rooms.join[room.id].membership.me().origin_server_ts)}} ago ({{mc.date.local.pretty(mc.rooms.join[room.id].membership.me().origin_server_ts)}}) </p> </div> </div> <form class="menu" ng-controller="menu as menu" ng-include="'ircd_rooms_list_item_info_menu'" > </form> </script> <script id="ircd_rooms_list_item_info_menu" type="text/ng-template" > <button type="submit" class="item" ng-repeat="(name, item) in mc.rooms.info.menu" ng-hide="item.hide(room.id)" ang-mousedown="menu.hold(mc.rooms.info.menu, name, $event, room.id);" ang-mouseup="menu.hold(mc.rooms.info.menu, name, $event, room.id);" ang-click="menu.toggle(mc.rooms.info.menu, name, $event, room.id);" ng-class="item.classes" > <i class="fa icon" ng-class="item.icon" aria-hidden="true" > </i> <h3 class="name" > {{ name }} </h3> </button> </script> <!-- -------------------------------------------------------------------------- Util --------------------------------------------------------------------------- --> <script id="ircd_error" type="text/ng-template" > <div class="error" tabindex="0" ng-controller="errors as this" ng-dblclick="this.close($event);" ng-blur="this.close($event);" > <div class="header row nowrap" > <h4 ng-show="this.error.m.errcode && this.error.m.errcode != 'M_UNKNOWN'" > {{ mc.m.pretty_errcode(this.error.m.errcode); }} </h4> <h5 style="justify-content: flex-end; flex-grow: 1" > {{ this.error.status }} {{ this.error.name }} </h5> </div> <div class="message grow column nowrap" > <p ng-show="this.error.m.error" > {{ this.error.m.error }} </p> <p ng-show="this.error.message" > {{ this.error.message }} </p> </div> <div class="footer row nowrap" > <i class="fa fa-code guru icon" aria-hidden="true" ng-show="this.error.stack || this.error.request_stack || this.error.response_stack" ng-click="this.guru = !this.guru; $event.stopPropagation();" > </i> <div class="grow" > </div> <i class="fa fa-remove icon" aria-hidden="true" ng-hide="this.error.fatal" ng-click="this.close($event);" > </i> </div> <div class="guru column nowrap" ng-show="this.guru === true" ng-dblclick="this.guru = !this.guru; $event.stopPropagation();" > <i class="fa fa-remove icon" aria-hidden="true" ng-click="this.guru = !this.guru; $event.stopPropagation();" > </i> <div class="stack row nowrap" > <div class="stack column nowrap" ng-if="this.error.request_stack" > <h3> REQUEST STACK </h3> <p class="request stack" >{{this.error.request_stack}}</p> </div> <div class="stack column nowrap" ng-if="this.error.response_stack" > <h3> RESPONSE STACK </h3> <p class="response stack" >{{this.error.response_stack}}</p> </div> <div class="stack column nowrap" ng-if="!this.error.response_stack && !error_request_stack && this.error.stack" > <h3> EXCEPTION STACK </h3> <p class="stack" >{{this.error.stack}}</p> </div> </div> <div class="json column nowrap" ng-if="this.error.m" > <p class="json" >{{debug.stringify(this.error.m, 3)}}</p> </div> </div> </div> </script> <!-- Old jquery explorer --> <script id="json_member" type="text/ng-template" > <div class="member" > <div class="key" > <i class="icon fa" > </i> <p class="name" > </p> </div> <div class="value" style="display: none" > </div> </div> </script> <script id="json_object" type="text/ng-template" > <div class="object" > </div> </script> <!-- New explorer --> <script id="ircd_object" type="text/ng-template" > <div class="member" ng-repeat="(key, val) in object" > <h5 class="key" ng-if="_typeof(val) !== 'undefined'" > {{ key }} </h5> <input type="text" ng-value="val" ng-if="_typeof(val) != 'object' && _typeof(val) != 'undefined'" class="value" /> <div class="object" ng-include="'ircd_object'" ng-if="_typeof(val) == 'object'" ng-init="object = val;" > </div> </div> </script> <!-- -------------------------------------------------------------------------- #charybdis --------------------------------------------------------------------------- --> <div id="charybdis" class="ircd" ng-controller="mc" ng-include="'ircd'" ircd-catch > </div> <script src="jquery.min.js"></script> <script src="angular.min.js"></script> <script src="angular-animate.min.js"></script> <script src="js/util.js"></script> <script src="js/debug.js"></script> <script src="js/ircd.js"></script> <script src="js/mc.js"></script> <script src="js/ng.js"></script> <script src="js/error.js"></script> <script src="js/watch.js"></script> <script src="js/task.js"></script> <script src="js/storage.js"></script> <script src="js/datetime.js"></script> <script src="js/random.js"></script> <script src="js/ui.js"></script> <script src="js/explore.js"></script> <script src="js/scroll.js"></script> <script src="js/menu.js"></script> <script src="js/io.js"></script> <script src="js/io.request.js"></script> <script src="js/m.js"></script> <script src="js/my.js"></script> <script src="js/event.js"></script> <script src="js/user.js"></script> <script src="js/users.js"></script> <script src="js/room.js"></script> <script src="js/room/timeline.js"></script> <script src="js/room/state.js"></script> <script src="js/room/power.js"></script> <script src="js/room/members.js"></script> <script src="js/room/send.js"></script> <script src="js/room/typing.js"></script> <script src="js/room/receipt.js"></script> <script src="js/room/input.js"></script> <script src="js/room/input.history.js"></script> <script src="js/room/attach.js"></script> <script src="js/room/scroll.js"></script> <script src="js/room/account.js"></script> <script src="js/room/notifications.js"></script> <script src="js/room/dom.js"></script> <script src="js/room/sync.js"></script> <script src="js/room/focus.js"></script> <script src="js/room/events.js"></script> <script src="js/room/controller.js"></script> <script src="js/room/misc.js"></script> <script src="js/rooms.js"></script> <script src="js/console.js"></script> <script src="js/settings.js"></script> <script src="js/filter.js"></script> <script src="js/sync.js"></script> <script src="js/auth.js"></script> <script src="js/main.js"></script> <script src="construct.js"></script> </body> </html>