mirror of
https://github.com/matrix-construct/construct
synced 2024-12-29 08:54:02 +01:00
2958 lines
51 KiB
HTML
2958 lines
51 KiB
HTML
<!DOCTYPE html>
|
|
|
|
<html
|
|
lang="en"
|
|
>
|
|
|
|
<head>
|
|
<meta
|
|
charset="utf-8"
|
|
/>
|
|
<meta
|
|
http-equiv="x-ua-compatible"
|
|
content="ie=edge"
|
|
/>
|
|
<meta
|
|
name="description"
|
|
content="Charybdis Five Internet Relay Chat Matrix"
|
|
/>
|
|
|
|
<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="charybdis.css"
|
|
/>
|
|
|
|
<!--
|
|
for erry
|
|
-->
|
|
|
|
<title>
|
|
Charybdis 5 - Internet Relay Chat Matrix
|
|
</title>
|
|
</head>
|
|
|
|
|
|
<body
|
|
ng-app="ircd"
|
|
ng-class="{ loaded: true }"
|
|
>
|
|
|
|
<!----------------------------------------------------------------------------
|
|
|
|
Charybdis 5 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_motd"
|
|
class="motd pane"
|
|
ng-show="mc.show['#charybdis_motd']"
|
|
ng-dblclick="mc.show['#charybdis_motd'] = false"
|
|
ng-include="'ircd_motd'"
|
|
>
|
|
</div>
|
|
<div
|
|
id="charybdis_login"
|
|
class="login_ pane"
|
|
ng-show="mc.show['#charybdis_login']"
|
|
ng-include="'charybdis_login'"
|
|
>
|
|
</div>
|
|
</script>
|
|
|
|
|
|
<!----------------------------------------------------------------------------
|
|
|
|
Rooms
|
|
|
|
----------------------------------------------------------------------------->
|
|
|
|
|
|
<script
|
|
id="ircd_rooms"
|
|
type="text/ng-template"
|
|
>
|
|
<div
|
|
id="charybdis_room"
|
|
class="current no-animate"
|
|
ng-hide="!mc.rooms.current.list.length"
|
|
ng-include="'ircd_rooms_current'"
|
|
>
|
|
</div>
|
|
<div
|
|
id="charybdis_rooms_main"
|
|
class="main"
|
|
ng-if="mc.show['#charybdis_rooms_main']"
|
|
ircd-catch='{"delegate": "#charybdis_rooms_list"}'
|
|
>
|
|
<div
|
|
id="charybdis_rooms_head"
|
|
class="head"
|
|
ng-show="mc.show['#charybdis_menu']"
|
|
ng-include="'ircd_rooms_head'"
|
|
>
|
|
</div>
|
|
<div
|
|
id="charybdis_rooms_list"
|
|
class="list"
|
|
ng-if="!empty(mc.rooms.list)"
|
|
ng-controller="rooms.list as list"
|
|
ang-scroll="list.scroll($event)"
|
|
ng-include="'ircd_rooms_list'"
|
|
>
|
|
</div>
|
|
</div>
|
|
</script>
|
|
|
|
|
|
<script
|
|
id="ircd_rooms_head"
|
|
type="text/ng-template"
|
|
>
|
|
<h1
|
|
ng-hide="mc.show['#charybdis_menu']"
|
|
>
|
|
ROOMS
|
|
</h1>
|
|
<form
|
|
id="charybdis_rooms_menu"
|
|
class="menu"
|
|
ng-controller="menu as menu"
|
|
ng-include="'ircd_rooms_menu'"
|
|
>
|
|
</form>
|
|
<form
|
|
id="charybdis_rooms_search"
|
|
class="search"
|
|
ng-include="'ircd_rooms_search'"
|
|
ng-class="
|
|
{
|
|
selected: mc.rooms.mode == 'SEARCH',
|
|
}">
|
|
</form>
|
|
</script>
|
|
|
|
|
|
<script
|
|
id="ircd_rooms_menu"
|
|
type="text/ng-template"
|
|
>
|
|
<button
|
|
class="item"
|
|
ng-repeat="(name, item) in mc.rooms.menu"
|
|
ang-click="menu.toggle(mc.rooms.menu, name, $event)"
|
|
style="order: {{item.order !== undefined? item.order : 'initial'}}"
|
|
title="{{item.tooltip}}"
|
|
ng-hide="item.hide()"
|
|
ng-class="
|
|
{
|
|
selected: menu.selected(mc.rooms.menu, name, item),
|
|
error: item.error !== undefined,
|
|
disabled: item.disabled === true,
|
|
choice: item.choice(),
|
|
}">
|
|
<i
|
|
class="fa icon"
|
|
ng-class="item.icon"
|
|
aria-hidden="true"
|
|
>
|
|
</i>
|
|
<h3
|
|
class="name"
|
|
>
|
|
{{ name }}
|
|
</h3>
|
|
</button>
|
|
</script>
|
|
|
|
|
|
<script
|
|
id="ircd_rooms_search"
|
|
type="text/ng-template"
|
|
>
|
|
<input
|
|
name="name"
|
|
type="text"
|
|
autocomplete="off"
|
|
ng-model="mc.rooms.search.value"
|
|
ng-model-options="{debounce: 100}"
|
|
ng-change="mc.rooms.search.on.change($event);"
|
|
ng-keypress="mc.rooms.search.on.keypress($event);"
|
|
ng-focus="mc.rooms.search.on.focus($event);"
|
|
ng-blur="mc.rooms.search.on.blur($event);"
|
|
/>
|
|
<label
|
|
class="h6"
|
|
>
|
|
SEARCH ROOMS
|
|
<span
|
|
ng-hide="empty(mc.rooms.search.value)"
|
|
class="feedback"
|
|
>
|
|
{{ mc.rooms.search.feedback }}
|
|
</span>
|
|
</label>
|
|
</script>
|
|
|
|
|
|
<script
|
|
id="ircd_rooms_list"
|
|
type="text/ng-template"
|
|
>
|
|
<div
|
|
class="item"
|
|
ng-repeat="room in mc.rooms.list"
|
|
ng-show="!mc.rooms.info.model || mc.rooms.info.model == room.id"
|
|
ng-include="'ircd_rooms_list_item'"
|
|
>
|
|
</div>
|
|
</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.joined[room.id] !== undefined,
|
|
invited: mc.rooms.invited[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.joined[room.id] !== undefined,
|
|
invited: mc.rooms.invited[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.state['m.room.name'].content.name) &&
|
|
empty(room.state['m.room.canonical_alias'].content.alias)"
|
|
>
|
|
{{ room.id }}
|
|
</h3>
|
|
<h3
|
|
class="right name grow"
|
|
ng-if="!empty(room.state['m.room.name'].content.name) &&
|
|
empty(room.state['m.room.canonical_alias'].content.alias)"
|
|
>
|
|
{{ room.state['m.room.name'].content.name }}
|
|
</h3>
|
|
<h3
|
|
class="right alias grow"
|
|
ng-if="!empty(room.state['m.room.canonical_alias'].content.alias)"
|
|
>
|
|
{{ room.state['m.room.canonical_alias'].content.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.state['m.room.name'].content.name }}
|
|
</h3>
|
|
</div>
|
|
<div
|
|
class="id"
|
|
>
|
|
<h4>
|
|
{{ room.id }}
|
|
</h4>
|
|
</div>
|
|
<div
|
|
class="stats"
|
|
>
|
|
<div
|
|
class="joined"
|
|
ng-if="mc.rooms.joined[room.id] !== undefined"
|
|
>
|
|
<h5
|
|
class="label"
|
|
>
|
|
JOINED
|
|
</h5>
|
|
<p>
|
|
{{mc.date.describe.since(mc.rooms.joined[room.id].membership.me().origin_server_ts)}} ago
|
|
({{mc.date.local.pretty(mc.rooms.joined[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>
|
|
|
|
|
|
<script
|
|
id="ircd_rooms_current"
|
|
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 indicator bar"
|
|
ng-show="room.control.show_status_indicator"
|
|
ng-include="'ircd_room_control_indicator'"
|
|
>
|
|
</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'"
|
|
>
|
|
</div>
|
|
<div
|
|
class="members"
|
|
ng-if="room.control.show_members"
|
|
ng-controller="room.membership 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="events"
|
|
ng-controller="room.events as events"
|
|
ang-scroll="room.scroll.on($event)"
|
|
ng-include="'ircd_room_events'"
|
|
>
|
|
</div>
|
|
<form
|
|
class="input"
|
|
ng-show="room.control.show_main_input && room.control.mode == 'LIVE'"
|
|
ng-include="'ircd_room_input'"
|
|
>
|
|
</form>
|
|
</script>
|
|
|
|
|
|
<script
|
|
id="ircd_room_members"
|
|
type="text/ng-template"
|
|
>
|
|
<div
|
|
class="menu"
|
|
ng-include="'ircd_room_members_menu'"
|
|
>
|
|
</div>
|
|
<form
|
|
class="search"
|
|
ng-include="'ircd_room_members_search'"
|
|
>
|
|
</form>
|
|
<div
|
|
class="list"
|
|
ang-scroll="members.scroll($event)"
|
|
ng-include="'ircd_room_members_list'"
|
|
ircd-catch
|
|
>
|
|
</div>
|
|
<div
|
|
class="invite member"
|
|
ng-show="members.filter == 'invite'"
|
|
ng-include="'ircd_room_members_invite'"
|
|
>
|
|
</div>
|
|
</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.control.show_members = members.filter != name;
|
|
members.filter = name;
|
|
"
|
|
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"
|
|
>
|
|
<input
|
|
name="pattern"
|
|
type="text"
|
|
autocomplete="off"
|
|
/>
|
|
<label
|
|
class="h6"
|
|
>
|
|
SEARCH MEMBERS
|
|
</h6>
|
|
</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_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>
|
|
|
|
|
|
<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>
|
|
|
|
|
|
<script
|
|
id="charybdis_login"
|
|
type="text/ng-template"
|
|
>
|
|
<form
|
|
id="charybdis_login_form"
|
|
ircd-catch
|
|
>
|
|
<h3>
|
|
<b>I</b>nternet <b>R</b>elay <b>C</b>hat
|
|
</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.auth['m.login.password'](); $event.stopPropagation();"
|
|
>
|
|
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'](); $event.stopPropagation();"
|
|
>
|
|
REGISTER
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</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>
|
|
|
|
<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.state['m.room.history_visibility'].content.history_visibility == name,
|
|
pending: room.pending['m.room.history_visibility'].content.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.state['m.room.join_rules'].content.join_rule == name,
|
|
pending: room.pending['m.room.join_rules'].content.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.state['m.room.guest_access'].content.guest_access == name,
|
|
pending: room.pending['m.room.guest_access'].content.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.state['m.room.power_levels'].content"
|
|
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.state['m.room.name'].content.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.state['m.room.topic'].content.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_indicator"
|
|
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.state['m.room.name'].content.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.state['m.room.canonical_alias'].content.alias}}
|
|
</h3>
|
|
</div>
|
|
<div
|
|
class="id"
|
|
ng-click="room.control.show_detail = !room.control.show_detail"
|
|
>
|
|
<button
|
|
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-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-gears pointer"
|
|
aria-hidden="true"
|
|
>
|
|
</i>
|
|
</button>
|
|
<div
|
|
class="state"
|
|
>
|
|
<p
|
|
class="count"
|
|
>
|
|
{{ Object.keys(room.state).length }}
|
|
</p>
|
|
<h5>
|
|
ST
|
|
</h5>
|
|
</div>
|
|
<div
|
|
class="timeline"
|
|
>
|
|
<p
|
|
class="count"
|
|
>
|
|
{{ room.timeline.length }}
|
|
</p>
|
|
<h5>
|
|
TL
|
|
</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="room.control.show_members = !room.control.show_members"
|
|
>
|
|
<button
|
|
ng-class="
|
|
{
|
|
selected: room.control.show_members,
|
|
}">
|
|
<i
|
|
class="members icon fa fa-users"
|
|
aria-hidden="true"
|
|
>
|
|
</i>
|
|
</button>
|
|
<div
|
|
ng-repeat="(name, item) in mc.room.membership.indicator"
|
|
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_indicator_charybdis_menu'"
|
|
>
|
|
</div>
|
|
</script>
|
|
|
|
<script
|
|
id="ircd_room_control_indicator_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>
|
|
|
|
<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.state['m.room.member'][event.sender].content.avatar_url"
|
|
ng-href="room.state['m.room.member'][event.sender].content.avatar_url"
|
|
>
|
|
<img
|
|
ng-src="room.state['m.room.member'][event.sender].content.avatar_url"
|
|
alt="{{ room.state['m.room.member'][event.sender].content.avatar_url }}"
|
|
target="_blank"
|
|
/>
|
|
</a>
|
|
|
|
<span
|
|
class="name"
|
|
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"
|
|
>
|
|
{{ mc.m.sid(event.sender) }}
|
|
</span>
|
|
</span>
|
|
|
|
|
|
|
|
<span
|
|
class="domain"
|
|
>{{ mc.m.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__member"
|
|
type="text/ng-template"
|
|
>
|
|
<p
|
|
class="join"
|
|
ng-switch-when="join"
|
|
>
|
|
{{ event.content.displayname }} joined the channel.
|
|
</p>
|
|
|
|
<p
|
|
class="leave"
|
|
ng-switch-when="leave"
|
|
ng-if="!event.target || event.target == event.sender"
|
|
>
|
|
{{ event.content.displayname }} left the channel.
|
|
</p>
|
|
|
|
<p
|
|
class="leave"
|
|
ng-switch-when="leave"
|
|
ng-if="event.target && event.target != event.sender"
|
|
>
|
|
<b>kicked</b> {{ event.content.displayname }}
|
|
</p>
|
|
|
|
<p
|
|
class="invite"
|
|
ng-switch-when="invite"
|
|
>
|
|
<b>invited</b> {{ event.content.displayname }}
|
|
</p>
|
|
|
|
<p
|
|
class="default unhandled"
|
|
ng-switch-default
|
|
>
|
|
unhandled m.room.member type '{{ event.content.membership }}'
|
|
</p>
|
|
</script>
|
|
|
|
<script
|
|
id="ircd_room_event__message"
|
|
type="text/ng-template"
|
|
>
|
|
</script>
|
|
|
|
<script
|
|
id="ircd_room_event__create"
|
|
type="text/ng-template"
|
|
>
|
|
<div
|
|
class="changed"
|
|
>
|
|
<h5>
|
|
created
|
|
</h5>
|
|
<h3>
|
|
ROOM
|
|
</h3>
|
|
</div>
|
|
<h1>
|
|
{{ id }}
|
|
</h1>
|
|
</script>
|
|
|
|
<script
|
|
id="ircd_room_event__power_levels"
|
|
type="text/ng-template"
|
|
>
|
|
<div
|
|
class="changed"
|
|
>
|
|
<h5>
|
|
changed
|
|
</h5>
|
|
<h3>
|
|
PRIVILEGE LEVELS
|
|
</h3>
|
|
</div>
|
|
<div
|
|
class="new levels"
|
|
>
|
|
<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__canonical_alias"
|
|
type="text/ng-template"
|
|
>
|
|
<div
|
|
class="changed"
|
|
>
|
|
<h5>
|
|
changed
|
|
</h5>
|
|
<h3>
|
|
CANONICAL ALIAS
|
|
</h3>
|
|
</div>
|
|
<h2>
|
|
{{ event.content.alias }}
|
|
</h2>
|
|
</script>
|
|
|
|
<script
|
|
id="ircd_room_event__join_rules"
|
|
type="text/ng-template"
|
|
>
|
|
<div
|
|
class="changed"
|
|
>
|
|
<h5>
|
|
changed
|
|
</h5>
|
|
<h3>
|
|
JOIN RULES
|
|
</h3>
|
|
</div>
|
|
<div
|
|
class="join_rules menu"
|
|
>
|
|
<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__history_visibility"
|
|
type="text/ng-template"
|
|
>
|
|
<div
|
|
class="changed"
|
|
>
|
|
<h5>
|
|
changed
|
|
</h5>
|
|
<h3>
|
|
HISTORY VISIBILITY
|
|
</h3>
|
|
</div>
|
|
<h2>
|
|
{{ event.content.history_visibility }}
|
|
</h2>
|
|
</script>
|
|
|
|
<script
|
|
id="ircd_room_event__guest_access"
|
|
type="text/ng-template"
|
|
>
|
|
<div
|
|
class="changed"
|
|
>
|
|
<h5>
|
|
changed
|
|
</h5>
|
|
<h3>
|
|
GUEST ACCESS
|
|
</h3>
|
|
</div>
|
|
<h2>
|
|
{{ event.content.guest_access }}
|
|
</h2>
|
|
</script>
|
|
|
|
<script
|
|
id="ircd_room_event__aliases"
|
|
type="text/ng-template"
|
|
>
|
|
<div
|
|
class="changed"
|
|
>
|
|
<h5>
|
|
changed
|
|
</h5>
|
|
<h3>
|
|
ALIASES
|
|
</h3>
|
|
</div>
|
|
<div
|
|
class="aliases row nowrap grow center"
|
|
>
|
|
<h2
|
|
class="alias full-center"
|
|
ng-repeat="alias in event.content.aliases"
|
|
>
|
|
{{ alias }}
|
|
</h2>
|
|
</div>
|
|
</script>
|
|
|
|
<script
|
|
id="ircd_room_event_unhandled"
|
|
type="text/ng-template"
|
|
>
|
|
<h4>
|
|
UNHANDLED EVENT
|
|
</h4>
|
|
<p
|
|
style="white-space: pre-wrap;"
|
|
>
|
|
{{ debug.stringify(event, 2) }}
|
|
</p>
|
|
</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_events"
|
|
type="text/ng-template"
|
|
>
|
|
<div
|
|
class="event"
|
|
ng-repeat="event in room.timeline"
|
|
ng-if="events.can_render(event, $index)"
|
|
ng-show="events.can_show(event, $index)"
|
|
ng-switch on="event.type"
|
|
ng-class="
|
|
{
|
|
zoom: room.control.content.zoom == event.event_id,
|
|
}">
|
|
<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-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="member"
|
|
ng-switch-when="m.room.member"
|
|
>
|
|
<div
|
|
ng-switch on="event.content.membership"
|
|
ng-include="'ircd_room_event__member'"
|
|
>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
class="message"
|
|
ng-switch-when="m.room.message"
|
|
ng-switch on="event.content.msgtype"
|
|
>
|
|
<div
|
|
class="notice"
|
|
ng-switch-when="m.notice"
|
|
>{{event.content.body}}</div>
|
|
|
|
<p
|
|
class="text"
|
|
ng-switch-when="m.text"
|
|
>{{event.content.body}}</p>
|
|
|
|
<p
|
|
class="emote"
|
|
ng-switch-when="m.emote"
|
|
>{{event.content.body}}</p>
|
|
|
|
<div
|
|
class="image"
|
|
ng-switch-when="m.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>
|
|
|
|
<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>
|
|
|
|
<p
|
|
class="default unhandled"
|
|
ng-switch-default
|
|
>
|
|
unhandled message type '{{ event.content.msgtype }}'
|
|
</p>
|
|
</div>
|
|
|
|
<div
|
|
class="state create"
|
|
ng-switch-when="m.room.create"
|
|
>
|
|
<div
|
|
ng-include="'ircd_room_event__create'"
|
|
>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
class="state power_levels"
|
|
ng-switch-when="m.room.power_levels"
|
|
>
|
|
<div
|
|
ng-include="'ircd_room_event__power_levels'"
|
|
>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
class="state canonical_alias"
|
|
ng-switch-when="m.room.canonical_alias"
|
|
>
|
|
<div
|
|
ng-include="'ircd_room_event__canonical_alias'"
|
|
>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
class="state join_rules"
|
|
ng-switch-when="m.room.join_rules"
|
|
>
|
|
<div
|
|
ng-include="'ircd_room_event__join_rules'"
|
|
>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
class="state history_visibility"
|
|
ng-switch-when="m.room.history_visibility"
|
|
>
|
|
<div
|
|
ng-include="'ircd_room_event__history_visibility'"
|
|
>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
class="state guest_access"
|
|
ng-switch-when="m.room.guest_access"
|
|
>
|
|
<div
|
|
ng-include="'ircd_room_event__guest_access'"
|
|
>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
class="state aliases"
|
|
ng-switch-when="m.room.aliases"
|
|
>
|
|
<div
|
|
ng-include="'ircd_room_event__aliases'"
|
|
>
|
|
</div>
|
|
</div>
|
|
|
|
<div
|
|
class="default unhandled"
|
|
ng-switch-default
|
|
>
|
|
<div
|
|
ng-include="'ircd_room_event_unhandled'"
|
|
>
|
|
</div>
|
|
</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_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>
|
|
|
|
<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.state['m.room.name'].content.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_motd"
|
|
type="text/ng-template"
|
|
>
|
|
<h3>
|
|
WELCOME TO CHARYBDIS 5
|
|
</h3>
|
|
<p>
|
|
The free and open-source Internet Relay Collaboration daemon implementing the
|
|
<b>Matrix</b> chat federation protocol.
|
|
</p>
|
|
<h3>
|
|
FREE & OPEN SOURCE SOFTWARE COLLABORATION
|
|
</h3>
|
|
<p>
|
|
Charybdis extends the Matrix chat protocol to facilitate collaboration with IRC<sup>3</sup>
|
|
("IRC cubed" or "Internet Relay Collaboration") protocol. For capable clients, project files can
|
|
be edited by developers and observed by contributors in realtime; live discussions take place
|
|
adjacent to the code being developed; a timeline of updates form a commit made to git; webhooks
|
|
to Github and <i>continuous integration</i> are conducted by the server.
|
|
</p>
|
|
<h3>
|
|
CHARYBDIS CLUSTER
|
|
</h3>
|
|
<p>
|
|
<i>Cluster</i> facilitates load-balancing and redundancy for groups of
|
|
trusted servers. Cluster introduces a technology called <i>Proteus</i>: a <b>single
|
|
shared content and event repository among servers</b>, without replicating copies
|
|
between them and thus reducing storage cost.
|
|
</p>
|
|
<h3>
|
|
CHARYBDIS PEERING
|
|
</h3>
|
|
<p>
|
|
<i>Peering</i> allows groups of <i>untrusted</i> servers in the federation
|
|
that have formed a <i>clique</i> of users, rooms, assets, etc to utilize the same technology
|
|
as <i>Charybdis Cluster</i> at a larger scale.
|
|
</p>
|
|
</script>
|
|
|
|
<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>
|
|
|
|
|
|
<!-- --------------------------------------------------------------------------
|
|
|
|
#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="charybdis/util.js"></script>
|
|
<script src="charybdis/debug.js"></script>
|
|
<script src="charybdis/ircd.js"></script>
|
|
<script src="charybdis/mc.js"></script>
|
|
<script src="charybdis/ng.js"></script>
|
|
<script src="charybdis/error.js"></script>
|
|
<script src="charybdis/watch.js"></script>
|
|
<script src="charybdis/task.js"></script>
|
|
<script src="charybdis/storage.js"></script>
|
|
<script src="charybdis/datetime.js"></script>
|
|
<script src="charybdis/random.js"></script>
|
|
<script src="charybdis/ui.js"></script>
|
|
<script src="charybdis/scroll.js"></script>
|
|
<script src="charybdis/menu.js"></script>
|
|
<script src="charybdis/io.js"></script>
|
|
<script src="charybdis/io.request.js"></script>
|
|
<script src="charybdis/m.js"></script>
|
|
<script src="charybdis/my.js"></script>
|
|
<script src="charybdis/event.js"></script>
|
|
<script src="charybdis/user.js"></script>
|
|
<script src="charybdis/users.js"></script>
|
|
<script src="charybdis/room.js"></script>
|
|
<script src="charybdis/room/timeline.js"></script>
|
|
<script src="charybdis/room/state.js"></script>
|
|
<script src="charybdis/room/power.js"></script>
|
|
<script src="charybdis/room/members.js"></script>
|
|
<script src="charybdis/room/send.js"></script>
|
|
<script src="charybdis/room/typing.js"></script>
|
|
<script src="charybdis/room/receipt.js"></script>
|
|
<script src="charybdis/room/input.js"></script>
|
|
<script src="charybdis/room/input.history.js"></script>
|
|
<script src="charybdis/room/attach.js"></script>
|
|
<script src="charybdis/room/scroll.js"></script>
|
|
<script src="charybdis/room/account.js"></script>
|
|
<script src="charybdis/room/notifications.js"></script>
|
|
<script src="charybdis/room/dom.js"></script>
|
|
<script src="charybdis/room/sync.js"></script>
|
|
<script src="charybdis/room/focus.js"></script>
|
|
<script src="charybdis/room/events.js"></script>
|
|
<script src="charybdis/room/controller.js"></script>
|
|
<script src="charybdis/room/misc.js"></script>
|
|
<script src="charybdis/rooms.js"></script>
|
|
<script src="charybdis/rooms/current.js"></script>
|
|
<script src="charybdis/rooms/create.js"></script>
|
|
<script src="charybdis/rooms/info.js"></script>
|
|
<script src="charybdis/rooms/search.js"></script>
|
|
<script src="charybdis/rooms/public.js"></script>
|
|
<script src="charybdis/rooms/sync.js"></script>
|
|
<script src="charybdis/rooms/list.js"></script>
|
|
<script src="charybdis/console.js"></script>
|
|
<script src="charybdis/settings.js"></script>
|
|
<script src="charybdis/filter.js"></script>
|
|
<script src="charybdis/sync.js"></script>
|
|
<script src="charybdis/auth.js"></script>
|
|
<script src="charybdis/main.js"></script>
|
|
<script src="charybdis.js"></script>
|
|
|
|
</body>
|
|
</html>
|